IBOutletはnilですが、ストーリーボードSwiftに接続されています


102

Swift 1.1およびXcode 6.2の使用。

単一のカスタムUIViewControllerサブクラスを含むUIStoryboardがあります。その上に、そのコントローラからサブクラスへの@IBOutletタイプの接続がありますUIViewUIView ストーリーボードのます。そのビューのサブビューにも同様のアウトレットがあります。図Aを参照してください。

しかし、実行時には、これらのプロパティはゼロです(図B)。確かに、Interface Builderでコンセントを接続していることは確かです。

考え

  • サブクラスのサブクラスを使用しているために、初期化で何かがおかしくなっている可能性がありますか?初期化子を上書きしていません
  • awakeFromNib: 何らかの理由で呼び出されていません
  • 多分それはサブビューのサブビューに接続していません

私が試したこと:

  • マッチング@IBOutletとストーリーボードのアイテムタイプ(の代わりにUIView
  • プロパティとアウトレットを削除して再度追加した

図A

図A *

図B

図B

*隠されたコードFigure Aは次のとおりです。

@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!

ありがとうございました。


変更しないでください!へ?

ストーリーボードにリンクされていないため、clearViewはnilです(コードの左側にある穴のある円を参照してください。リンクされていないことを示しています)。スクリーンショットでは、annotationOptionViewの宣言が表示されていません。
Javier Flores Font

@JavierFloresFont:clearViewゼロになることを期待しています。それは私がまだリファクタリングしていないものです。図Aの脚注も参照してください。@ShaanSinghこれは正しいはずです。ストーリーボードからの接続は実行時に設定される(想定される)ため、nilにしないでください。
Stefan Arambasich 2015年

このView Controllerはどのように読み込まれますか?それを要求するコードを示すか、それに接続するセグエを説明してください。
rob mayoff 2015年

1
それは右のストーリーボードを取得している: let vc = UIStoryboard(name: "LocationPickerModal", bundle: nil) .instantiateViewControllerWithIdentifier("LocationPickerModalViewController") as LocationPickerModalViewController
ステファンArambasich

回答:


146

通常、これは、ビューコントローラーがまだビュー階層をロードしていないために発生します。ビューコントローラーは、何かがviewメッセージを送信したときにのみビュー階層を読み込みます。システムは、実際に画面上のビュー階層を置くための時間であるとき、これを行うようなものの後に起こっているprepareForSegue:sender:とはviewWillAppear:戻ってきました。

VCはまだビュー階層をロードしていないため、アウトレットはまだありません。

と言うことで、VCにビュー階層を強制的にロードさせることができます_ = self.view


4
これは、viewWillAppear:が呼び出されたときに発生します。そのコンセントで初めて何かをしたときです。ビューにアクセスしても何も起こりません。まだありません。
Stefan Arambasich 2015年

ありがとう!これも私にとってはうまくいきました。var v = viewcontroller.view; ビュー階層を強制的にロードしました。ちょっとしたトリック!;)
Yordi Uytersprot 2015

@YordiUytersprotこの行をどこに配置しますか?
非同期

4
まあ、あなたがビューコントローラをインスタンス化する場合:vc = self.storyboard?.instantianteViewControllerWithIdentifier( "StoryboardIDfromVC")を次のように?CustomVC; let = vc.view; //現在、ここでCustomVCからIBOutletsにアクセスできます。.vc.customTextField.text = "Lalala"; お役に立てば幸いです。:)
Yordi Uytersprot 2015年

4
UIViewcontroller.loadViewIfNeeded()ここで使用する正しい方法です。
orkoden

27

製品>クリーンを実行してみましたか?私にとって非常によく似た問題を解決しました。


やった。申し訳ありませんが、私の答えをマークするためのものです。DerivedDataプロジェクトのフォルダを削除した後にのみ機能し始めました。
Stefan Arambasich、2015

3
ビュー階層の真ん中にあるアウトレットのうち2つだけがゼロでした。製品->クリーンは私のために働きました!
Rikco

1
obj c、プロジェクトをクリーンアップするだけでうまくいきました... 1時間以上費やしたことは信じられず、プロジェクトをクリーンアップすることすら考えていませんでした:/しかし、ありがとうございます!!
温室

Just Product-> Cleanは機能しませんでしたが、別のシミュレーターを起動して機能しました。DerivedDataフォルダーにも問題があるはずです。
endavid '25 /

22

ストーリーボードまたはNIBからビューコントローラをインスタンス化しましたか、それともイニシャライザを介して直接インスタンス化しましたか?

イニシャライザを使用してクラスを直接インスタンス化した場合、アウトレットは接続されません。Interface Builderは、クラスのカスタマイズされたインスタンスを作成し、それらのインスタンスをNIBとストーリーボードにエンコードして繰り返しデコードします。クラス自体は定義しません。これが問題である場合は、コントローラーを作成するコードを変更して、代わりにUIStoryboardまたはUINibのメソッドを使用する必要があります。


2
UIStoryboardインスタンスを作成して呼び出しinstantiateViewControllerWithIdentifierています。
Stefan Arambasich 2015年

15

ストーリーボードは、追加したUIの要素を認識していませんでした。実行時には、すべての参照がゼロでした。そのため、派生データフォルダーをクリアすると、それらの接続が再び機能しました。


2
これが答えです。私はかなり長い間これに立ち向かい、ビルドフォルダーとすべてをクリーニングしました。私の場合、viewDidLoad()すべての接続が行われましたが、viewWillAppear()ほとんどすべての接続が行われましたnil(1つまたは2つがまだ接続されている場合がありました)。私はすべてを試し、最後に派生データフォルダーを削除して再構築しましたが、すべて順調でした。
ruttopia

6
3年経っても、Xcode 9.2には同じバグがあります。どうもありがとうございます。
Kemal Can Kaynak

1
これがXcode 11にまだ存在することを報告するためにここに::(
sentag

13

これは、カスタムコレクションビューセルで発生していました。registerClassforReuseIdentifierメソッドをregisterNibに置き換える必要がありました。それで解決しました。


あなたが正しいです。Swiftプログラミング言語のARCカウントコンテンツを詳しく読みました。私は理由を見つけることができません、なぜIBOutletの弱いプロパティがまだnilであるのか。ついに私は「@IBOutlet swift nil」をググってSOであなたの答えを見つけました。次に、viewDidLoadに「self.collectionView!.registerClass」が追加されたXcodeテンプレートの行をマークアウトしました。その後、動作します。あなたは私の命を救います。
charles.cc.hsu

12

これは、ストーリーボードを介してインスタンス化するのではなく、誤って直接ビューコントローラーをインスタンス化していたためです。を介して直接インスタンス化するとMyViewController()、アウトレットは接続されません。


XIBファイルを使用する場合、直接インスタンス化は引き続き正常に機能します。
Luat Vu Dinh

11

私の場合、loadViewViewControllerサブクラスのメソッドをオーバーライドしたが、追加するのを忘れたために発生しました。[super loadView]

-(void)loadView {
// blank
}

loadViewメソッドをオーバーライドするときは、サブビューを初期化する必要があります。あなたがそれをオーバーライドするので、インターフェースビルダーからのビューはココアオブジェクトに変換する機会がなく、アウトレットはゼロのままです。

loadViewViewをビューコントローラーサブクラスに実装する場合は、UI要素をストーリーボード/ xibからコードにロードする必要があります。

または電話するだけ

[super loadView];

そのため、スーパークラスがストーリーボード/ xibをコードにロードする機会を得ます。


8

を呼び出しcontroller.viewて強制的にビューをロードし、IBOutletsを初期化すると、値を割り当てることができます。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}

7

view controllerプログラムでインスタンス化する場合。次に、以下のように作成してみてください

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

直接ではなく

let initialVC = InitialVC()

これでうまくいきました。


6

私にとって、これは誤ってビューコントローラーのクラスを次のように宣言したときに発生しました

class XYZViewController: UINavigationController {
}

(つまりとしてではUINavigationControllerないUIViewController)。

Xcodeはクラスがビルド罰金に思える、この間違いにピックアップし、そのようにオーバーライド機能しませんviewDidLoadviewWillAppearなどのすべての作業を正しく。しかし、どれもIBOutlet接続され。

宣言を

class XYZViewController: UIViewController {
}

完全に修正しました。


5

最近この問題に遭遇しました!これが私の考えです。問題はストーリーボードやリンクの問題ではありません。ViewControllerを開始する方法についてです。特にSwiftを使用している場合(クラスファイルを作成しても、エディターにはほとんど何もありません)

init()fromスーパークラスを使用するだけでは、ストーリーボードを操作することはできません。したがって、ViewControllerの初期化を変更する必要があります。Replace let XXViewController = XXViewController() by let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController これは、ストーリーボードに移動してXXViewControllerを見つけるようにプログラムに指示し、IBOutletします。

よろしくお願いします〜GL


それは問題ではありませんでした
Stefan Arambasich 2015年

4

2019年、この恐ろしい問題に対する1つの可能性:

  • たとえば、ある種の時計を表示するコンテナビューがあるとします。だからあなたは

    クラスClock:UIViewController

あなたは実際にアプリのいくつかの場所でそれ使用しますます。

メイン画面、詳細画面、編集画面。

複雑なスナップチャットのような最新のアプリがあります。

実際には、Clock実際にロードすることができる複数回同じ時間にどこかに同じ画面。(場合によっては非表示になることがあります)。

の1つのインスタンスで作業を開始します Clock多くのストーリーボードの1ます。

そのストーリーボードで、ラベルNewLabelを追加します。

当然、コードでアウトレットを追加します。すべてが機能するはずです。他のすべてのアウトレットは完全に動作します。

あなたは間違いなくコンセントをリンクしています。

しかし、アプリはNewLabelでクラッシュしますをnilとしてます。

Xcodeは、「コンセントを接続するのを忘れた」ことを明確に伝えます。

その理由はこれです.......... 時計のストーリーボード使用の1つだけに「NewLabel」があります!

クラッシュは実際には>>>他の場所からです<<<<あなたは時計を使用しています!!!!

Xcode 、クラッシュが完全に別の場所からのものであることを通知しません。からのものであると言っているのでは、作業している!

クラッシュは実際にはあなたが働いている場所からではありません-それはのものからですではなく、ストーリーボードに「NewLabel」アイテムがないストーリーボードです!!!

イライラする。



2

ストーリーボードでアウトレットをインスタンス化するには、最初にビュー階層をロードする必要があります。このため、loadViewまたはloadViewIfNeededメソッドを手動で呼び出すことができます。


2

私の場合、アプリが突然クラッシュし始めました。これをデバッグすると、すべてのアウトレットがまだnil当時のものであることがわかりましたviewDidLoad()

私のアプリはまだnibsを使用しています、ほとんどのView Controllerでまだストーリーボードではなくます。すべてが整い、すべてのコンセントが正しく配線されました。再確認しました。

通常、ビューコントローラは次のようにインスタンス化します

let newVC = MYCustomViewController()

...何らかの理由で長い.xibは、ビューコントローラクラスと同じ名前が付けられて(確認してくださいどのような作品は、しかし。私たちはされていないと仕事に思われていない呼び出しinit(nibName:bundle:)nilの引数を持つ、または上書きinit()にそうするようにselfそれのような通常は推奨されます...)。

だから私は明示的に呼び出そうとしました

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

...ランタイム例外エラーでのみ迎えられる:

***キャッチされない例外 'NSInternalInconsistencyException'によりアプリを終了します、理由: 'バンドルでNIBをロードできませんでした:' NSBundle </ Users / nicolasmiari / Library / Developer / CoreSimulator / Devices / 3DA3CF21-108D-498F-9649-C4FC9E3C1A8D / data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app>(loaded)」という名前の「MYCustomViewController」

そして、その後、私はそれを見ました:

.xibファイルの[Target Membership]チェックボックスがオフになっています。


Xcodeプロジェクトファイルに関する頻繁なマージ競合の1つを解決するときに発生したに違いありません。

アップルは間違いなく、よりSCMに適したプロジェクトファイル形式を考え出す必要があります。


2

StoryBoardsなしでXIBからViewControllersを作成するための100%実用的なソリューション

  1. クラスCustomViewControllerを作成します。UIViewController
  2. CustomViewControllerView.xibビューを作成します。
  3. Interface BuilderのCustomViewControllerView.xibで、Placeholders-> File's Ownerを選択します
  4. 「属性インスペクタ」で、クラスをCustomViewControllerに設定します
  5. 「接続インスペクタ」で、「ビュー」をxibのトップレベルビューに接続します(トップレベルビューのクラスがCustomViewControllerを指していないことを確認します)
  6. 「接続インスペクタ」で他のコンセントを接続します(必要な場合/存在する場合)
  7. 親ビューコントローラー/アプリデリゲートにCustomViewControllerのインスタンスを作成します

7.1。

// creating instance
let controller = CustomViewController()

7.2。

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3。

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")

素晴らしい答え、ありがとう!その価値については、CustomViewControllerクラスinit(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)self直接ステップ7.2をオーバーライドして呼び出すこともできます。
ブランドンスクリプト、

1

IBOutlet接続がファイル所有者またはビューに接続しているかどうかを確認します。間違いがあるかもしれません。


1

その他の場合:

アウトレットは、ビューコントローラーのビューが実際にインスタンス化されるまで設定されません。この場合、おそらくinitWithNibName:bundle:の直後に発生しますが、その時点ではまだnilです。これらのアウトレットを含む設定は、ビューコントローラーの-viewDidLoadメソッドで行う必要があります。


1

私にとっては、ローカライズされたストーリーボードで同じエラーが発生しました。あるロケールに要素が追加され、他のロケールには要素が追加されなかったため、不足している要素ロケールに切り替えたときにその要素のnull参照がありました。https://stackoverflow.com/a/42256341/1356559を使用したスト​​ーリーボード。


1

私にとって、これはクラッシュした containerViewはnilた。

これがCrashの私のコードです。

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

不足しているのはを呼び出すことでしたsuper.loadView()。だからそれを追加すると問題が解決した。

修正済みコード

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}

loadView()を直接呼び出さないで(developer.apple.com/documentation/uikit/uiviewcontroller/…)、代わりにself.viewを呼び出す
Lio

1

ストーリーボードで識別子を既に定義した後で、カスタムセルのregister(_:forCellReuseIdentifier :)を以前に追加したときにも、同様の問題がありました。このコードをviewDidLoad()関数に含めました。削除すると、問題なく動作しました。


1

私がたまたま遭遇したさらに別のケース。UIViewControllerのクラスの名前を変更しましたが、インターフェイスが構築された.xibファイルの名前を変更するのを忘れていました。

これを見つけて、ファイル名にクラス名を反映させると、それはすべて良かったです!

それが誰かのお役に立てば幸いです。


1

もう1つ...

UITableViewCellのカスタムクラスがあるが、セルのスタイルでカスタムを指定し忘れた場合。


1

ビューがロードされているかどうかを検証できます。

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}

0
  1. 両方.hを選択して.mコントローラーファイルを表示する
  2. それらのファイルの参照を削除する
  3. ファイルをプロジェクトツリーに再度追加する
  4. ストーリーボードを開き、最終的にプロジェクトを再構築します

0

誤って、のAVPlayerViewController代わりにでビューコントローラをサブクラス化しましたUIViewControllerUIViewController正常に戻すために再生します。これは役立つはずです。

ビルドのクリーニングなし(通常および完全)、派生データフォルダーの削除、Xcodeの終了は私にとってはうまくいきました。


0

(xibにリンクされた)クラスをコピーして、(ストーリーボードにリンクされた)別のviewcontrollerクラスで再利用した後も、同じ問題が発生しました。削除するのを忘れた

override var nibName

そして

override var nibBundle

メソッド。

それらを取り除いた後、私のコンセントは機能し始めました。


0

使ってますViewControllerね!?でViewControllerクラスあなたがしなければならない使用-viewDidLoadない -awakeFromNib-awakeFromNibのために使用しUIViewたクラス



0

2つmain.storyboardsあり、間違ったものに変更を加えている場合、これが発生する可能性があります。これは、インスタンス化されていないコンセントからコンセントを接続するといつでも発生する可能性がありますstoryboard

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.