web-dev-qa-db-ja.com

IBOutletはありませんが、ストーリーボードで接続されています、Swift

Swift 1.1およびXcode 6.2を使用します。

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

ただし、実行時には、これらのプロパティはゼロです(図B)。 Interface Builderでコンセントを接続したことを保証しましたが。

思考

  • サブクラスのサブクラスを使用しているため、初期化で何かが台無しになる可能性はありますか?イニシャライザーをオーバーライドしていません
  • awakeFromNib:が何らかの理由で呼び出されない
  • サブビューのサブビューに接続していない可能性があります

私が試したもの:

  • UIViewの代わりに)@IBOutletとストーリーボードのアイテムタイプを正確に一致させる
  • プロパティとアウトレットを削除して再追加しました

Figure A

図A *

Figure B

図B

* Figure Aの不明瞭なコードは次のとおりです。

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

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

91

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

15

通常、これは、View Controllerがビュー階層をまだロードしていないために発生します。 View Controllerは、何かがviewメッセージを送信したときにのみビュー階層をロードします。システムは、ビュー階層を実際に画面に配置するときにこの処理を行います。これは、prepareForSegue:sender:viewWillAppear:などが返された後に発生します。

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

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

131
rob mayoff

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

27
ThottChief

ストーリーボードまたはNIBからView Controllerをインスタンス化しましたか、または初期化子を介して直接インスタンス化しましたか?

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

20
Jon Hess

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

11
rounak

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

-(void)loadView {
// blank
}

loadViewメソッドをオーバーライドする場合、サブビューを初期化するのはユーザーの責任です。これをオーバーライドするため、インターフェイスビルダーからのビューは、ココアオブジェクトに変換する機会を得られないため、アウトレットはゼロのままです。

View ControllerサブクラスにloadViewを実装する場合、ストーリーボード/ xibからコードにUI要素をロードするのはあなたの責任となります。

またはただ電話する

[super loadView];

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

10
zinnuree

これは、ストーリーボードを介してインスタンス化するのではなく、誤ってView Controllerを直接インスタンス化していたために起こりました。 MyViewController()を介して直接インスタンス化する場合、アウトレットは接続されません。

8
Eric Conner

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
zs2020

私にとって、これは誤ってView Controllerのクラスを次のように宣言したときに発生しました

class XYZViewController: UINavigationController {
}

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

Xcodeはこの間違いを認識せず、クラスは正常に構築され、viewDidLoadviewWillAppearなどのオーバーライド関数はすべて正常に動作するようです。しかし、IBOutletsはどれも接続されません。

宣言を変更する

class XYZViewController: UIViewController {
}

完全に修正しました。

6
HughHughTeotl

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

スーパークラスのinit()を使用するだけでは、ストーリーボードで作業したものを開始できません。そのため、ViewControllerの初期化を変更する必要があります。 let XXViewController = XXViewController()let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewControllerに置き換えますこれにより、プログラムはストーリーボードに移動してXXViewControllerを見つけ、ストーリーボード内のIBOutletをすべて開始します。

このヘルプを願っています〜GL

4
user3882355

Swiftの場合3。

func configureView() {
    let _  = self.view
}
3
prog_24

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

2
maven25

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

  1. クラスCustomViewControllerを作成:UIViewController
  2. ビューCustomViewControllerView.xibを作成します
  3. Interface BuilderのCustomViewControllerView.xibで、プレースホルダー->ファイルの所有者を選択します。
  4. 「属性インスペクタ」で、クラスをCustomViewControllerに設定します
  5. 「接続インスペクタ」で、「ビュー」をxibのトップレベルビューに接続します(トップレベルビューのクラスがCustomViewControllerを指していないことを確認します)
  6. 「接続インスペクター」で他のコンセントを接続します(必要な場合/存在する場合)
  7. 親View Controller/App Delegateで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")
1
Roman M

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

1
Amr Lotfy

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

これを捕まえて、ファイル名にクラス名を反映させると、すべてうまくいきました!

私はそれが誰かを助けることを願っています。

1
Brian Trzupek

その他の場合:

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

1

ファイル所有者またはビューに接続されている場合は、IBOutlet接続を確認してください。間違いがあるかもしれません。

1
Ahd Radwan

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

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

直接ではなく

let initialVC = InitialVC()

これは私のために働いた。

1
Vinoth Vino

私にとって、これはcontainerViewがnilだったためにクラッシュしていました。

クラッシュのコードです。

@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)
}
1
BLC

もう1つ...

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

1
Phantom59

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

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}
1
A. Trejo
  1. .hおよび.mビューコントローラーファイルの両方を選択します
  2. それらのファイルの参照を削除します
  3. プロジェクトツリーにファイルを再度追加します
  4. ストーリーボードを開き、最終的にプロジェクトを再構築します
0

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

override var nibName

そして

override var nibBundle

メソッド。

それらを削除した後、私のコンセントが動作し始めました。

0
smukamuka

不足しているコンセントや接続されていないコンセントがあるかどうかを確認します。

enter image description here

偶然 View ControllerをAVPlayerViewControllerではなくUIViewControllerでサブクラス化しました。それをUIViewControllerの事柄に再生することで、正常に戻ります。これが役立つはずです。

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

0
Hemang

ViewController !?を使用しているようです。 ViewControllerクラスでは必須-viewDidLoadを使用、not-awakeFromNib-awakeFromNibUIViewクラスに使用

0
EvGeniy Ilyin

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

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

通常、View Controllerを次のようにインスタンス化します

let newVC = MYCustomViewController()

.... xibがView Controllerクラスと同じ名前である限り、何らかの理由で機能するようです(ただし、どのように機能するかはわかりません。ただし、notnil引数でinit(nibName:bundle:)を呼び出すか、通常_selfinit()をオーバーライドして、推奨されるように...)。

だから私は明示的に呼び出してみました

 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」

そしてthen、見た:

。xibファイルの[ターゲットメンバーシップ]チェックボックスはオフになっています。


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

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

0
Nicolas Miari

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

0
Gthoma2

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

0
ScottyBlades