38658


iOSの開発に興味を持ち簡単な例で試してみようと  
swiftの勉強を始めました。  
そこで画面上に丸(型：SKShapeNode)を表示し  
update()で動かしてみようと思ってコードを書いていたところ  
下記の問題にぶつかりました。知識が浅いためか調べても解決できなかったため質問させていただきました。とても初歩的な質問で申し訳ありませんが、回答お待ちしております。

■やりたかったこと  
1.var circle = SKShapeNode(circleOfRadius:xx)  
のxxで画面サイズ基準で初期化したかった  
（例えばxx=self.frame.width/100.0のようにしたかった）

■問題点  
1.下記コードのcircleの宣言部分で  
"Value of type '(NSObject) -> () -> GameScene' has no member 'frame'"  
と怒られてしまいました。

[code]

    import SpriteKit
    import GameplayKit
    import UIKit
    
    class GameScene: SKScene{
    
        var circle = SKShapeNode(circleOfRadius:self.frame.width/100.0)
    
        func getWidthHeight(){
            width=self.frame.width
            height=self.frame.width
        }...
    
[/code]

■回答いただきたいこと  
1."Value of type '(NSObject) -> () -> GameScene' has no member 'frame'"と怒られた理由  
2.上記コードのfunc内ではなぜ怒られないのか  
3.上記コードのfunc内のself.frame.widthのselfはGameSceneのことではないのか

以上３つについて回答をお願いしたいです。  
よろしくお願いいたします。


CC BY-SA 3.0
2017-10-13T01:29:03.953
38656
2017-10-13T01:59:02.873
2017-10-13T01:52:20.773
76
25745
question
swift ios
GameSceneクラスでself.frameが関数の中で使えるのに外で使えない理由


ご質問文のタイトルには「【初歩的な質問です】」のように、ご質問内容を表現するのに不要な情報は含めないようにしてください。

**_1."Value of type '(NSObject) -> () -> GameScene' has no member
'frame'"と怒られた理由_**

インスタンスプロパティの初期化式の中では`self`がインスタンスを表さないからです。  
(現在のSwiftの実装では[`NSObject`の`self`メソッド](https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418954-self)として解釈されるようですが、実用的な意味はないので、「Swiftではインスタンスプロパティの初期化式の中で(普通の意味の)`self`は使えない」と覚えておいてください。)

**_2.上記コードのfunc内ではなぜ怒られないのか_**

インスタンスメソッドの中では`self`がインスタンスを表すからです。

**_3.上記コードのfunc内のself.frame.widthのselfはGameSceneのことではないのか_**

こう言った微妙な状況では「GameSceneのこと」と言う表現ではYesともNoとも答えられませんが、`GameScene`のインスタンスメソッドの中では`self`は`GameScene`のインスタンスを表します。

「Swiftではインスタンスプロパティの初期化式の中で(普通の意味の)`self`は使えない」と言うのは、Swiftの初期化に関わる厳密な制約によるものです。ご興味がおありならば[Swift本](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/index.html#//apple_ref/doc/uid/TP40014097)の[Class
Inheritance and
Initialization](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID216)あたりを熟読して見てください。

* * *

「回答いただきたいこと」にはありませんが、上記の制約を回避する方法として、`lazy`を使う方法が知られています。

[code]

    lazy var circle = SKShapeNode(circleOfRadius:self.frame.width/100.0)
    
[/code]

`lazy`なインスタンスプロパティは最初に参照される直前に初期化され、その初期化式内の`self`は普通にインスタンスを表すものとして解釈されます。初期化のタイミングが関わるような処理でなければ、「やりたかったこと」が実現できるのではないかと思います。


CC BY-SA 3.0
2017-10-13T01:59:02.873
38658
2017-10-13T01:59:02.873
13972
38656
answer