2017-05-12 3 views
0

今週早々に奇妙なバグに遭遇し、問題の根本的な原因を防ぐ方法を確認するためにフォローアップしたかったのです。アイテムをviewDidLoadで安全に初期化することを参照してください。

次のコードを使用してください。だから、someMethodTestViewController前に解雇され

//***************************** 
//MAINVIEWCONTROLLER CLASS CODE 
//***************************** 

//Some event happens that triggers me to want to load up TestViewController. 
func showViewController(){ 
    var testController = TestViewController() 
    testController.someMethod("Test1") 

    self.navigationController?.pushViewController(testController, animated: true) 
} 

//***************************** 
//TESTVIEWCONTROLLER CLASS CODE 
//***************************** 
testView:TestView! 

override func viewDidLoad(){ 
    super.viewDidLoad() 
    testView = TestView() 
    ... 
}  

func someMethod(someData:String){ 
    testView.name = someData   //AppCrashes here because testView might be nil. 
    ... 
} 

は通過とtestViewを作成する機会がありました。 testViewはnilであり、私はそのプロパティにアクセスしているので、オプションの値をアンラップできません。

私が実行しているアプリケーションは6つの異なる場所で動作している可能性がありますが、5/6は問題なく動作していますが、1/6はこのエラーを表示しています。私は、someMethodが実行される前に、viewDidLoadが即座に実行されるか、完了することが保証されていないためにその推測を行っていますが、なぜこの6つの使用例すべてでは起こりませんか。

だから、私の主な質問は以下のとおりです。

  1. なぜこのクラッシュが起こるのでしょうか?
  2. これを避けるためのベストプラクティスは何ですか?

ありがとう!思いやりのある答えがいつものように票を集めるでしょう!もっと情報が役立つかどうかを教えてください。

+2

あなたはsomeMethod' '呼ぶのですかどこ?条件に応じて 'testView'をアンラップする必要があります。 'viewDidLoad'は、初めてビューコントローラの' view'プロパティが参照されるときに実行されます。 – Paulw11

+1

あなたのコードがどのように遵守されているか不思議です。 testViewはオプションか暗黙的なオプションか? – user1046037

+1

あなたが尋ねていることを示す実際のコードを投稿してください。これはコンパイルされず、さらに重要なことに、あなたの記述にも一致しません。 –

答えて

1

を呼び出さないのViewControllerを初期化しますUI要素を含むソースコントローラーから呼び出された宛先コントローラーでコードを実行しないでください。プロパティを作成し、元のコントローラでそれを設定し、例えば、先のコントローラのviewDidLoad()にUI要素に値を割り当てる:

//***************************** 
//MAINVIEWCONTROLLER CLASS CODE 
//***************************** 

//Some event happens that triggers me to want to load up TestViewController. 
func showViewController(){ 
    var testController = TestViewController() 
    testController.someData = "Test1" 

    self.navigationController?.pushViewController(testController, animated: true) 
} 

//***************************** 
//TESTVIEWCONTROLLER CLASS CODE 
//***************************** 
testView:TestView! 

var someData = "" 

override func viewDidLoad(){ 
    super.viewDidLoad() 
    testView = TestView() 
    testView.name = someData 
    ... 
}  
+0

素晴らしいので、ViewDidLoadはTestViewController()のinitで呼び出されることはなく、viewDidLoadの前に必要な値を設定しても問題ありません。 viewDidLoadはいつ起こるのですか? pushViewControllerの後に? view.addSubviewで? +1 – Unome

+0

'viewDidLoad'は' pushViewController'の後に初めてビューが表示される直前に呼び出されます。それを証明するために 'print'行を追加してください。 – vadian

+0

サブビューを介してViewControllerを手動で追加すると、同じ動作が一貫していますか?とaddChildViewController?あなたの助けをありがとう – Unome

1

viewDidLoadは、ViewControllerがロード準備完了時に呼び出されます。セグーが起こったとき、または現在に関わっているとき。

testViewはオプションですが、あなたのコードはコンパイルしてはいけませんが、2つのオプションがあります。オプションを使用します(この場合、viewDidLoadの後にコールされないとビューが情報を取得しない可能性がありますが、クラッシュしません)、渡された情報を格納し、viewDidLoadまたはviewWillAppearでビューを更新します。あなたが知っておくしたい場合があります

何かがあなたがでviewDidLoadメソッドを強制することができviewIfLoaded

+0

いつviewDidLoadが呼び出されますか?私が渡したい値を持つプロパティを追加し、viewDidLoad内からsomeMethodを呼び出して、viewDidLoadが呼び出されたときに値が設定されることは保証されていますか? – Unome

1

あると:

var testViewController = TestViewController() _ = testViewController.view testViewController.someMethod("Test")

自動的に基本的のviewDidLoad

+0

pushViewController()を呼び出すとviewDidLoadが呼び出されますか? – Unome

+0

testMethodをpushViewControllerの後に移動すると、まだクラッシュします。 – Unome

関連する問題