2017-05-08 8 views
5

遅延初期化を使用しているときに、このUIBarButtonItemターゲットの問題が無意識のうちに見つかりました。iOS lazy var UIBarButtonItemターゲットの問題

class ViewController: UIViewController { 
    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action1)) 
    lazy var barButtonItem2: UIBarButtonItem = { 
    let barButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action2)) 
    return barButtonItem 
    } 

    override func viewDidLoad() { 
    super.viewDidLoad() 

    print(barButtonItem1.target, barButtonItem2.target) 
    } 
} 

印刷結果はbarButtonItem1.targetがnilであることを示した、とbarButtonItem2.targetはクレイジーと思われる自己、でした! barButtonItem1の遅延書き込みを使用したときにこの問題が発生し、barButtonItem1のアクションを呼び出すことができないことが判明し、最後に問題はbarButtonItem1.targetがnilだったことです。

私はこれがなぜ起こるのかわかりませんが、これはバグだとはっきりしています。 これについて誰かが知っていますか?あなたがそれについて説明できるなら、本当に感謝します。

+1

私はあなたが正しく 'barButtonItem1'をやっているとは思いません。最初の 'lazy var'はデータ型で宣言しなければなりません。次に、通常のvarのように値を設定するだけです。お読みください:https://www.hackingwithswift。com/example-code/language/what-are-lazy-variables – thedp

+0

barButtonItem1の宣言は、[link](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language)に従って正しくなければなりません。 /Properties.html)。 – user5685969

+1

[link](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)によると、barButtonItem1の宣言は正しいはずです。しかし、私はbarButtonItem1のデータ型宣言を追加するように言ったが、今はうまく動作している。私はまだこの原因を知らない。 – user5685969

答えて

3

以下は私の推測ですです。残念ながら、私はコメントをするほどの評判がないので、私にあなたに答えをさせてください。

私の推測:これはコンパイラのバグです。


まず、私はUIBarButtonItemの小さな拡張を作成しました。 (2番目のパラメータはAny?しかしUIViewController?ではない)

extension UIBarButtonItem { 
    convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, targetViewController: UIViewController?, action: Selector?) { 
     // call the initializer provided by UIKit 
     self.init(barButtonSystemItem: systemItem, target: targetViewController, action: action) 
    } 
} 

そしてIは以下のコードと遅延記憶された変数を初期化することを試みました。

class ViewController: UIViewController { 

    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     print(barButtonItem1.target) 
    } 
    func action() { } 
} 

次に '(NSObjectの) - >() - >のViewController' 発生したエラーをコンパイラと

型の値を変換できませんと言う 予想引数の型に 'のUIViewController?'

これは、コンパイラがselfViewControllerであると判断できなかったことを示しています。 (第2のパラメータがAny?であるためのUIKitによって提供される初期化は、タイプ(NSObject) ->() -> ViewControllerの値を受け付けるコンパイルだろう。)

しかし

lazy var barButtonItem1: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

ソースコードのような怠惰な変数に与えるタイプ注釈は喜んでコンパイルしbarButtonItem1.targetselfに設定した。

私はタイプ注釈がコンパイルに役立つと思います。上記の理由は、あなたが直面した問題が、コンパイラのバグによって引き起こされたと思います。


参照:あなたが直面している問題に似て報告された問題があります。どちらもコンパイラのバグとして結論づけられます。

Swift lazy instantiating using self

Type inference when using lazy instantiation

+0

ありがとう!それは本当にコンパイラのバグです、リンゴがすぐにそれを修正することを願っています。今のところ、タイプ注釈を追加しましょう。 – user5685969

関連する問題