IBOutlet sıfır, ancak film şeridi Swift ile bağlantılı


102

Swift 1.1 ve Xcode 6.2'yi kullanma.

Tekil, özel bir UIViewControlleralt sınıf içeren bir UIStoryboard'um var . Üzerinde, bu denetleyiciden film şeridindeki bir alt sınıfa bir @IBOutlettür bağlantım var . Bu görünümün alt görünümleri için de benzer çıkışlarım var. Şekil A'ya bakın.UIViewUIView

Ancak çalışma zamanında bu özellikler sıfırdır (Şekil B). Arabirim Oluşturucu'daki çıkışları bağladığıma emin olmama rağmen.

Düşünceler :

  • Bir alt sınıfın bir alt sınıfını kullandığım için başlatma işlemini bir şeyin bozması mümkün mü? Herhangi bir başlatıcıyı geçersiz kılmıyorum
  • awakeFromNib: nedense aranmıyor
  • Belki alt görünümlerdeki alt görünümlere bağlanmıyor

Denediğim şeyler:

  • @IBOutletTam olarak eşleşen ve film şeridi öğe türleri (yerine UIView)
  • Mülk ve priz silme ve yeniden ekleme

Şekil A

Şekil A *

Şekil B

Şekil B

* İçindeki gizlenmiş kod Figure A:

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

Teşekkür ederim.


Neden! için?

clearView nil çünkü film şeridine bağlı değil (kodun solundaki, bağlantılı olmadığını gösteren bir delikli daireye bakın), ekran görüntüsünde annotationOptionView bildirimini göremiyorum.
Javier Flores Font

@JavierFloresFont: Sıfır clearViewolmasını bekliyorum. Henüz yeniden düzenlemem gereken bir şey. Ayrıca şekil A için dipnota bakın. @ShaanSingh Olmalı! çünkü hikaye tahtalarından gelen bağlantılar çalışma zamanında ayarlanır (olması gerekir) ve sıfır olmamalıdır.
Stefan Arambasich

Bu görüntü denetleyicisi nasıl yüklenir? Bize onu isteyen kodu gösterin veya ona bağlanan segmenti açıklayın.
rob mayoff

1
Doğru film let vc = UIStoryboard(name: "LocationPickerModal", bundle: nil) .instantiateViewControllerWithIdentifier("LocationPickerModalViewController") as LocationPickerModalViewController
şeridine

Yanıtlar:


146

Genellikle bu, görünüm denetleyicinizin görünüm hiyerarşisini henüz yüklemediği için olur. Bir görünüm denetleyicisi, yalnızca bir şey kendisine viewmesaj gönderdiğinde kendi görünüm hiyerarşisini yükler . Sistem bunu, görünüm hiyerarşisini gerçekten ekrana koyma zamanı geldiğinde yapar, bu, benzer şeyler prepareForSegue:sender:ve viewWillAppear:geri döndükten sonra gerçekleşir .

VC'niz henüz görünüm hiyerarşisini yüklemediğinden, çıkışlarınız hala sıfırdır.

VC'yi şunu söyleyerek görünüm hiyerarşisini yüklemeye zorlayabilirsiniz _ = self.view.


4
Bu, viewWillAppear:o prizle ilk kez bir şey yaptığımda çağrıldığında meydana geliyor. Görünüme erişmek benim için hiçbir şey yapmıyor. Hâlâ sıfır.
Stefan Arambasich

Teşekkürler! Bu benim için de çalıştı. var v = viewcontroller.view; görünüm hiyerarşisini yüklemeye zorlandı. Güzel küçük numara! ;)
Yordi Uytersprot

@YordiUytersprot Bu satırı nereye koyardınız?
Async

4
Peki, bir görünüm denetleyicisini başlatırsanız: let vc = self.storyboard? .İnstantianteViewControllerWithIdentifier ("StoryboardIDfromVC") olarak? CustomVC; let view = vc.view; // Şu anda, IBOutlets'e CustomVC'den buradan erişebilirsiniz .. vc.customTextField.text = "Lalala"; Umarım size yardımcı olur! :)
Yordi Uytersprot

4
UIViewcontroller.loadViewIfNeeded()burada kullanılacak doğru yöntemdir.
orkoden

27

Ürün> Temizle'yi çalıştırmayı denediniz mi? Benim için çok benzer bir sorunu çözdü.


Yaptım. Üzgünüm, cevabımı işaretlemek istedim. Yalnızca DerivedDataproje klasörünü sildikten sonra çalışmaya başladı .
Stefan Arambasich

3
Görünüm hiyerarşimin ortasında yer alan satış noktalarımdan yalnızca ikisi sıfırdı .. Ürün -> Temiz benim için çalıştı!
Rikco

1
obj c, sadece projeyi temizlemek benim için çalıştı ... bir saatten fazla zaman harcadığına inanamıyorum ve projeyi temizlemeyi bile düşünmedim: / ama teşekkür ederim !!
sera

Sadece Ürün -> Temiz benim için çalışmadı, ancak farklı bir simülatör başlattım ve işe yaradı, bu nedenle DerivedData klasöründe de bir sorun olmalı.
44'te endavid

22

Görünüm denetleyicinizi bir Storyboard veya NIB'den mi somutlaştırdınız yoksa doğrudan bir başlatıcı aracılığıyla mı somutlaştırdınız?

Sınıfınızı doğrudan başlatıcıyla somutlaştırdıysanız, çıkışlar bağlanmayacaktır. Interface Builder, sınıflarınızın özelleştirilmiş örneklerini oluşturur ve bu örnekleri tekrarlanan kod çözme için NIB'lere ve Storyboard'lara kodlar, sınıfların kendisini tanımlamaz. Bu sizin sorununuzsa, UIStoryboard veya UINib'deki yöntemleri kullanmak için denetleyicinizi oluşturduğunuz kodu değiştirmeniz yeterlidir.


2
Bir UIStoryboardörnek oluşturuyorum ve instantiateViewControllerWithIdentifieronu çağırıyorum .
Stefan Arambasich

16

Film şeridi, ona eklediğim başka UI şeylerini tanımıyordu. Çalışma zamanında tüm referanslar sıfırdı. Bu yüzden türetilmiş veri klasörümü temizledim ve sonra bu bağlantılar tekrar çalıştı.


2
İşte cevap. Bununla bir süre savaştım, yapı klasörünü ve her şeyi temizledim. Benim durumumda, viewDidLoad()tüm bağlantılar yapıldı, ancak viewWillAppear()neredeyse hepsinde nil(bazen bir veya iki hala bağlıydı). Her şeyi denedim ve sonunda türetilmiş veri klasörünü sildim, yeniden oluşturdum ve her şey yolunda gitti.
ruttopia

6
3 yıl sonra bile, Xcode 9.2 hala aynı lanet olası hataya sahip. Çok teşekkür ederim.
Kemal Can Kaynak

1
Bunun Xcode 11'de hala mevcut olduğunu bildirmek için burada. :(
harcandı

13

Bu, özel koleksiyon görünümü hücremde başıma geliyordu. RegisterClassforReuseIdentifier yöntemimi registerNib ile değiştirmem gerektiği ortaya çıktı. Bu benim için sorunumu çözdü.


Haklısın. ARC sayım içeriğini Swift Programlama Dili'nde detaylı olarak okudum. IBOutlet zayıf özelliğinin neden hala sıfır olmasının nedenini bulamıyorum. Sonunda '@IBOutlet swift nil' için google'da aradım ve cevabınızı SO'da buldum. Sonra Xcode şablonunun viewDidLoad'a eklenen 'self.collectionView! .RegisterClass' satırını işaretledim. Sonra işe yarıyor. Hayatımı kurtardın.
charles.cc.hsu

12

Bu benim için oldu çünkü görüntü denetleyicimi film şeridi aracılığıyla örneklemek yerine yanlışlıkla doğrudan örneklendiriyordum. Doğrudan aracılığıyla somutlaştırırsanız MyViewController(), çıkışlar bağlanmayacaktır.


XIB dosyası kullanırsanız, doğrudan örnekleme başarılı bir şekilde çalışmaya devam eder.
Luat Vu Dinh

11

Benim durumumda, bu, loadViewViewController alt sınıfımdaki yöntemi geçersiz kıldığım, ancak eklemeyi unuttuğum için oldu[super loadView]

-(void)loadView {
// blank
}

loadViewYöntemi geçersiz kıldığınızda , alt görünümlerinizi başlatmak sizin sorumluluğunuzdadır. Bunu geçersiz kıldığınız için, arayüz oluşturucunun görünümleri kakao nesnelerine dönüştürme şansı bulamaz ve bu nedenle çıkışlar sıfır kalır.

LoadView'i görünüm denetleyicisi alt sınıfınızda uygularsanız, UI öğelerini storyboard / xib'den koda yüklemek sizin sorumluluğunuz olur.

Ya da sadece ara

[super loadView];

Böylece süper sınıf, storyboard / xib'i koda yükleme şansı elde eder.


8

controller.viewIBOutlet'leri başlatmak için görünümü yüklemeye zorlamak için çağırabilirsiniz , ardından değerleri atayabilirsiniz.

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 controllerProgramlı olarak somutlaştırırsanız . Sonra aşağıdaki gibi oluşturmayı deneyin

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

doğrudan yerine

let initialVC = InitialVC()

Bu benim için çalıştı.


6

Benim için bu, görüntüleme denetleyicimin sınıfını yanlışlıkla ilan ettiğimde meydana geldi.

class XYZViewController: UINavigationController {
}

(yani a UINavigationControllerdeğil olarak UIViewController).

Xcode sınıf inşa cezası görünüyor, bu hatadan üzerinde pick up, ve bu şekilde geçersiz kılma işlevleri vermez viewDidLoad, viewWillAppearvb tüm çalışma doğru. Ama hiçbiri IBOutletbağlantılı değil.

Beyanı olarak değiştirme

class XYZViewController: UIViewController {
}

tamamen düzeltti.


5

Bu sorunla son zamanlarda karşılaşıyorum! İşte benim düşüncem. Sorun, film şeridi veya herhangi bir bağlantı sorunu ile ilgili değil. Bu, ViewController'ınızı nasıl başlattığınız ile ilgilidir. Özellikle Swift kullandığınızda. (Bir sınıf dosyası oluşturduğunuzda düzenleyicide neredeyse hiçbir şey yoktur)

init()Süper sınıftan basitçe kullanarak storyboard ile çalıştığınız hiçbir şeyi başlatamazsınız. Bu yüzden yapmanız gereken, ViewController'ın ilklendirilmesini değiştirmektir. Değiştir let XXViewController = XXViewController() tarafından let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController Bunların hepsi XXViewController ve inisiyelere bulmak storyboard gitmek için programı söyler IBOutlethikaye akışınıza.

Umarım bu yardım ~ GL


Sorun bu değildi
Stefan Arambasich

4

2019, BU KORKUNÇ SORUN İÇİN BİR OLANAK:

  • Bir çeşit saati gösteren bir kap görünümünüz olduğunu varsayalım. Yani sahipsin

    sınıf Saat: UIViewController

Aslında bunu uygulamada birkaç yerde kullanıyorsunuz .

Ana ekranda, ayrıntılar ekranında, düzenleme ekranında.

Snapchat benzeri karmaşık bir modern uygulamanız var.

Aslında, Clockaslında yüklenmiş olabilir defadan fazla at aynı zaman üzerinde yere aynı ekranda . (Belki bazı durumlarda gizlidir.)

ClockBirçok storyboard'ınızdan birinin tek bir örneği üzerinde çalışmaya başlıyorsunuz .

Bu film şeridine NewLabel adlı bir etiket eklersiniz.

Doğal olarak çıkışı kod olarak eklersiniz. Herşey çalışmalı. Diğer tüm çıkışlar mükemmel çalışıyor.

Sen var kesinlikle çıkış bağlantılı.

Ancak uygulama, NewLabel ile sıfır olarak çöküyor .

Xcode size açıkça "prizi bağlamayı unuttuğunuzu" söyler.

Nedeni bu .......... Clock'un storyboard kullanımlarından yalnızca birinde "NewLabel" var !

Kilitlenme aslında >>> başka bir yerden <<<< siz Clock kullanıyorsunuz !!!!

Xcode değil kazasında dan size haber başka , tamamen bir yerde değil nerede çalışıyoruz dan!

Çökme aslında çalıştığınız yerden değil - o film şeridinde "NewLabel" öğesinin olmadığı başka bir film şeridinden değil !!!

Sinir bozucu.


3

Swift 3 için.

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

2

Film şeridindeki çıkışları başlatmak için önce görünüm hiyerarşisini yüklemeniz gerekir. Bunun için, loadView veya loadViewIfNeeded yöntemlerini manuel olarak çağırabilirsiniz.


2

Benim durumumda, uygulama aniden çökmeye başladı. Tüm çıkışları hala olduğunu ortaya çıkardı ayıklama nilsırasında viewDidLoad().

Uygulamam hala çoğu görünüm denetleyicisi için uçlar (film şeridi değil) kullanıyor . Her şey yerindeydi, tüm prizler doğru şekilde kablolanmıştı. İki kez kontrol ettim.

Görüntü denetleyicilerimizi genellikle şu şekilde somutlaştırırız:

let newVC = MYCustomViewController()

... nedense uzun .xib, emin nasıl işler (görünüm denetleyicisi sınıfla aynı adlı olduğunca işin görünüyor Biz edilir. gerçi değil çağırarak init(nibName:bundle:)nil argümanlarla veya geçersiz kılma init()üzerine bunu selfböyle genellikle önerilir ...).

Bu yüzden açıkça aramaya çalıştım

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

... yalnızca çalışma zamanı istisna hatasıyla karşılanacak:

*** 'NSInternalInconsistencyException' istisnası nedeniyle uygulama sonlandırılıyor, nedeni: 'Pakette NIB yüklenemedi:' NSBundle </ Users / nicolasmiari / Library / Developer / CoreSimulator / Devices / 3DA3CF21-108D-498F-9649-C4FC9E3C1A8D / data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (yüklendi) '' MYCustomViewController 'adıyla' '

Ve sonra gördüm:

.Xib dosyasının "Hedef Üyelik" onay kutusunun işareti kaldırıldı.


Xcode proje dosyasıyla ilgili sık birleştirme çakışmalarından birini çözerken meydana gelmiş olmalı.

Apple'ın kesinlikle daha SCM dostu bir proje dosyası formatı bulması gerekiyor.


2

StoryBoards olmadan XIB'den ViewControllers oluşturmak için% 100 Çalışan bir çözüm

  1. CustomViewController sınıfı oluşturun: UIViewController
  2. CustomViewControllerView.xib görünümü oluştur
  3. Arayüz Oluşturucu'daki CustomViewControllerView.xib'de Yer Tutucular -> Dosyanın Sahibi'ni seçin
  4. "Attributes inspector" da Class'ı CustomViewController olarak ayarlayın
  5. "Bağlantı denetçisinde" "görünümü" xib'in üst düzey görünümüne bağlayın (üst düzey görünümün Sınıfının CustomViewController'ı işaret etmediğinden emin olun)
  6. "Bağlantılar denetçisinde" diğer çıkışları bağlayın (gerekirse / varsa)
  7. Üst görünüm denetleyicisinde / Uygulama temsilcisinde bir CustomViewController örneği oluşturun

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")

Harika cevap, teşekkürler! Değeri ne olursa olsun, doğrudan CustomViewController sınıfında init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)7.2 adımı geçersiz kılabilir ve çağırabilirsiniz self.
brandonscript

1

Dosya sahibine veya görünüme bağlıysa IBOutlet bağlantınızı kontrol edin. Hatalar olabilir.


1

Diğer durum:

Çıkışlarınız, görünüm denetleyicisinin görünümü gerçekte somutlaştırılıncaya kadar ayarlanmayacaktır, bu sizin durumunuzda muhtemelen initWithNibName: bundle: paketinden kısa bir süre sonra gerçekleşmektedir - ki bu noktada hala sıfır olacaktır. Bu çıkışları içeren herhangi bir kurulum, görünüm denetleyicinizin -viewDidLoad yönteminde gerçekleşiyor olmalıdır.


1

Benim için, yerelleştirilmiş bir film şeridinde aynı hatayı aldım, bazı yerel ayara bir öğe eklendi, diğerine eklenmedi, bu nedenle eksik öğe yerel ayarına geçerken bu öğe için boş referansım vardı, için (yedek) yerelleştirmeyi kaldırmam gerekti https://stackoverflow.com/a/42256341/1356559 kullanan bu film şeridi .


1

Benim için bu çöküyordu çünkü containerViewsıfırdı.

İşte Crash ile kodum .

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

Eksik şey çağırmaktı super.loadView(). Yani eklemek benim için sorunu çözdü.

Sabit Kod :

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

loadView () öğesini asla doğrudan ( developer.apple.com/documentation/uikit/uiviewcontroller/… ) çağırmamalısınız, bunun yerine self.view
Lio

1

Film şeridinde tanımlayıcıyı zaten tanımladıktan sonra özel hücre için daha önce kayıt (_: forCellReuseIdentifier :) eklediğimde benzer bir sorun yaşadım. Bu kod, viewDidLoad () işlevinde vardı. Onu çıkardıktan sonra iyi çalıştı.


1

Az önce karşılaştığım başka bir vaka daha. UIViewController için sınıfımın adını değiştirdim, ancak arayüzün oluşturulduğu .xib dosyasının adını değiştirmeyi unuttum.

Bunu yakalayıp dosya adlarının sınıf adını yansıtmasını sağladıktan sonra her şey yolunda gitti!

Umarım bu birine yardımcı olur.


1

Bir tane daha var ...

Bir UITableViewCell için özel bir sınıfınız varsa ancak hücrenin Stilinde Özel'i belirtmeyi unutursanız.


1

İs görünümünün yüklenip yüklenmediğini doğrulayabilirsiniz.

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

0
  1. ikisini de seç .hve.m denetleyici dosyalarını görüntüleyin
  2. bu dosyaların referansını kaldırın
  3. dosyaları proje ağacınıza yeniden ekleyin
  4. film şeridini açın, sonunda projeyi yeniden oluşturun

0

Yanlışlıkla görünüm denetleyicimi AVPlayerViewControlleryerine ile alt sınıflandırdım UIViewController. Her UIViewControllerşeyi normale döndürerek . Bu yardımcı olmalı.

Derleme temizliği yok (normal ve dolu), türetilmiş veri klasörlerini kaldırma ve Xcode'dan çıkmak benim için çalıştı.


0

Bir sınıfı kopyaladıktan sonra (bir xib'e bağlı) başka bir viewcontroller sınıfıyla (bir storyboard'a bağlı) yeniden kullanmak için aynı sorunu yaşadım. Kaldırmayı unuttum

override var nibName

ve

override var nibBundle

yöntemler.

Onları çıkardıktan sonra prizlerim çalışmaya başladı.


0

Kullanabileceğin bkz ViewController!? içinde ViewControllersınıfın sen gerekir kullanmak -viewDidLoad, değil -awakeFromNib , -awakeFromNibkullanmak UIViewsınıfın



0

Eğer iki tane varsa main.storyboardsve yanlış olanı değiştiriyorsanız, bu olabilir. Bu, doğrulanmamış bir prizi her bağladığınızda gerçekleşebilir storyboard.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.