IBOutlet là con số không, nhưng nó được kết nối trong bảng phân cảnh, Swift


102

Sử dụng Swift 1.1 và Xcode 6.2.

Tôi có một UIStoryboard chứa một UIViewControllerlớp con tùy chỉnh, số ít . Trên đó, tôi có một loại @IBOutletkết nối UIViewtừ bộ điều khiển đó đến một UIView lớp con trên bảng phân cảnh. Tôi cũng có các cửa hàng tương tự cho các lượt xem phụ của chế độ xem đó. Xem hình A.

Nhưng tại thời điểm chạy, các thuộc tính này là 0 (Hình B). Mặc dù tôi đã đảm bảo rằng tôi đã kết nối các cửa hàng trong Trình tạo giao diện.

Suy nghĩ :

  • Có thể là do tôi đang sử dụng một lớp con của một lớp con có gì đó gây rối với quá trình khởi tạo không? Tôi không ghi đè bất kỳ trình khởi tạo nào
  • awakeFromNib: không được gọi vì một số lý do
  • Có thể nó không kết nối với lượt xem phụ trên lượt xem phụ

Những điều tôi đã thử:

  • Các @IBOutletloại mục đối sánh và phân cảnh chính xác (thay vì UIView)
  • Xóa thuộc tính và cửa hàng và thêm lại chúng

Hình A

Hình A *

Hình B

Hình B

* Mã bị che khuất trong Figure Alà:

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

Cảm ơn bạn.


Tại sao không thay đổi! đến ?

clearView là nil vì không được liên kết với bảng phân cảnh (xem vòng tròn ở bên trái của mã có một lỗ, điều đó cho thấy nó không được liên kết), trong ảnh chụp màn hình, tôi không thể thấy phần khai báo của annotationOptionView.
Javier Flores Font vào

@JavierFloresFont: clearViewTôi mong đợi là con số không. Đó là một cái gì đó tôi vẫn chưa cấu trúc lại. Cũng xem chú thích cho hình A. @ShaanSingh Nó nên được! bởi vì các kết nối từ bảng phân cảnh được (phải) đặt trong thời gian chạy và không được bằng 0.
Stefan Arambasich

Làm thế nào để bộ điều khiển chế độ xem này được tải? Cho chúng tôi xem mã yêu cầu nó hoặc mô tả segue kết nối với nó.
cướp mayoff

1
Nó đang có được bảng phân cảnh phù hợp: let vc = UIStoryboard(name: "LocationPickerModal", bundle: nil) .instantiateViewControllerWithIdentifier("LocationPickerModalViewController") as LocationPickerModalViewController
Stefan Arambasich

Câu trả lời:


146

Điều này thường xảy ra vì bộ điều khiển chế độ xem của bạn chưa tải hệ thống phân cấp chế độ xem của nó. Bộ điều khiển chế độ xem chỉ tải cấu trúc phân cấp chế độ xem của nó khi có thứ gì đó gửi viewthông báo cho nó . Hệ thống thực hiện điều này khi đến lúc thực sự đặt hệ thống phân cấp chế độ xem trên màn hình, điều này xảy ra sau khi những thứ như prepareForSegue:sender:viewWillAppear:đã quay trở lại.

Vì VC của bạn chưa tải hệ thống phân cấp chế độ xem của nó, nên các cửa hàng của bạn vẫn là con số không.

Bạn có thể buộc VC tải hệ thống phân cấp chế độ xem của nó bằng cách nói _ = self.view.


4
Điều này xảy ra khi viewWillAppear:được gọi, lần đầu tiên tôi làm bất cứ điều gì với ổ cắm đó. Truy cập chế độ xem không làm bất cứ điều gì cho tôi. Vẫn là con số không.
Stefan Arambasich

Cảm ơn! Cái này cũng có tác dụng với tôi. var v = viewcontroller.view; buộc phải tải phân cấp chế độ xem. Mẹo nhỏ hay! ;)
Yordi Uytersprot

@YordiUytersprot Bạn sẽ đặt dòng này ở đâu?
Async-

4
Chà, nếu bạn khởi tạo bộ điều khiển chế độ xem: let vc = self.storyboard? .InstantianteViewControllerWithIdentifier ("StoryboardIDfromVC") bằng? CustomVC; let view = vc.view; // Ngay bây giờ, bạn có thể truy cập IBOutlets từ CustomVC tại đây .. vc.customTextField.text = "Lalala"; Hy vọng nó sẽ giúp bạn! :)
Yordi Uytersprot

4
UIViewcontroller.loadViewIfNeeded()là phương pháp phù hợp để sử dụng ở đây.
orkoden

27

Bạn đã thử chạy Sản phẩm> Sạch sẽ chưa. Đã giải quyết một vấn đề rất giống với tôi.


Tôi đã làm. Xin lỗi, có nghĩa là để đánh dấu câu trả lời của tôi. Nó chỉ bắt đầu hoạt động sau khi tôi xóa DerivedDatathư mục cho dự án.
Stefan Arambasich

3
Chỉ có hai cửa hàng của tôi ở giữa hệ thống phân cấp chế độ xem của tôi là con số không .. Sản phẩm -> Sạch sẽ phù hợp với tôi!
Rikco

1
obj c, chỉ làm sạch dự án làm việc cho tôi ... không thể tin được đã dành hơn một giờ và thậm chí không nghĩ để làm sạch dự án: / nhưng cảm ơn bạn !!
nhà kính

Just Product -> Clean không hoạt động với tôi, nhưng tôi đã khởi động một trình mô phỏng khác và nó hoạt động, vì vậy chắc chắn có điều gì đó sai trong thư mục DerivedData.
endavid

22

Bạn đã khởi tạo bộ điều khiển chế độ xem của mình từ Bảng phân cảnh hoặc NIB hay bạn đã khởi tạo nó trực tiếp thông qua bộ khởi tạo?

Nếu bạn khởi tạo lớp của mình trực tiếp bằng trình khởi tạo, các cửa hàng sẽ không được kết nối. Interface Builder tạo các phiên bản tùy chỉnh của các lớp của bạn và mã hóa các phiên bản đó thành NIB và Bảng phân cảnh để giải mã lặp lại, nó không tự định nghĩa các lớp. Nếu đây là vấn đề của bạn, bạn chỉ cần thay đổi mã nơi bạn tạo bộ điều khiển của mình để thay vào đó sử dụng các phương pháp trên UIStoryboard hoặc UINib.


2
Tôi đang tạo một UIStoryboardphiên bản và gọi instantiateViewControllerWithIdentifiernó.
Stefan Arambasich

15

Bảng phân cảnh không nhận ra bất kỳ thứ gì khác về giao diện người dùng mà tôi đã thêm vào nó. Tại thời điểm chạy, tất cả các tham chiếu đều là con số không. Vì vậy, tôi đã xóa thư mục dữ liệu dẫn xuất của mình và sau đó các kết nối đó hoạt động trở lại.


2
Đây là câu trả lời. Tôi đã chiến đấu với điều này khá lâu, dọn dẹp thư mục xây dựng và mọi thứ. Trong trường hợp của tôi, trong viewDidLoad()tất cả các kết nối đã được thực hiện, nhưng viewWillAppear()hầu như tất cả chúng đều được nilkết nối (đôi khi một hoặc hai vẫn được kết nối). Tôi đã thử mọi thứ và cuối cùng đã xóa thư mục dữ liệu có nguồn gốc, xây dựng lại và tất cả đều ổn.
ruttopia

6
Thậm chí sau 3 năm, Xcode 9.2 vẫn dính một lỗi chết tiệt. Cảm ơn bạn rất nhiều.
Kemal Can Kaynak

1
Dưới đây báo cáo rằng đây vẫn còn tồn tại trong Xcode 11. :(
spentag

13

Điều này đã xảy ra với tôi với ô xem bộ sưu tập tùy chỉnh của tôi. Hóa ra tôi đã phải thay thế phương thức registerClassforReuseIdentifier của mình bằng registerNib. Điều đó đã sửa nó cho tôi.


Bạn đúng rồi. Tôi đã đọc chi tiết nội dung đếm ARC trong Ngôn ngữ lập trình Swift. Tôi không thể tìm thấy lý do, tại sao thuộc tính yếu của IBOutlet vẫn là con số không. Cuối cùng, tôi đã google cho '@IBOutlet swift nil' và tìm thấy câu trả lời của bạn trong SO. Sau đó, tôi đã đánh dấu mẫu Xcode dòng đã thêm 'self.collectionView! .RegisterClass' trong viewDidLoad. Sau đó, nó hoạt động. Bạn cứu lấy cuộc sống của tôi.
charles.cc.hsu

12

Điều này xảy ra với tôi vì tôi đã vô tình khởi tạo trực tiếp bộ điều khiển chế độ xem của mình thay vì khởi tạo nó thông qua bảng phân cảnh. Nếu bạn khởi tạo trực tiếp qua MyViewController()thì các cửa hàng sẽ không được kết nối.


Nếu bạn sử dụng tệp XIB, việc khởi tạo trực tiếp vẫn hoạt động thành công.
Luat Vu Dinh

11

Trong trường hợp của tôi, điều này đã xảy ra vì tôi ghi đè loadViewphương thức trong lớp con ViewController của mình, nhưng quên thêm[super loadView]

-(void)loadView {
// blank
}

Khi bạn ghi đè loadViewphương thức này, bạn có trách nhiệm bắt các lượt xem phụ của mình. Vì bạn ghi đè nó, các khung nhìn từ trình tạo giao diện không có cơ hội chuyển đổi thành các đối tượng ca cao và do đó các cửa hàng vẫn là con số không.

Nếu bạn triển khai loadView trong lớp con của bộ điều khiển chế độ xem, thì trách nhiệm của bạn là tải các phần tử giao diện người dùng từ bảng phân cảnh / xib vào mã.

Hoặc chỉ cần gọi

[super loadView];

Để lớp cha có cơ hội tải bảng phân cảnh / xib vào mã.


8

Bạn có thể gọi controller.viewđể buộc tải chế độ xem để khởi tạo IBOutlets, sau đó bạn sẽ có thể gán các giá trị.

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

Nếu bạn khởi tạo view controllerthông qua lập trình. Sau đó, hãy thử tạo nó như bên dưới

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

thay vì trực tiếp

let initialVC = InitialVC()

Điều này đã làm việc cho tôi.


6

Đối với tôi, điều này xảy ra khi tôi vô tình khai báo lớp của bộ điều khiển chế độ xem của mình là

class XYZViewController: UINavigationController {
}

(tức là UINavigationControllerkhông phải a UIViewController).

Xcode không nhặt về sai lầm này, lớp dường như xây dựng tốt, và chức năng ghi đè như viewDidLoad, viewWillAppearvv tất cả các công việc một cách chính xác. Nhưng không có cái nào IBOutletđược kết nối.

Thay đổi khai báo thành

class XYZViewController: UIViewController {
}

đã sửa nó hoàn toàn.


5

Tôi gặp phải vấn đề này gần đây! Đây là suy nghĩ của tôi. Vấn đề không nằm ở bạn bảng phân cảnh hay bất kỳ vấn đề liên kết nào. Đó là về cách bạn khởi tạo ViewController của mình. Đặc biệt là khi bạn đang sử dụng Swift. (Hầu như không có gì trong trình chỉnh sửa khi bạn tạo tệp lớp)

Bằng cách đơn giản sử dụng init()từ siêu lớp không thể khởi tạo bất cứ điều gì bạn đã làm việc với bảng câu chuyện. Vì vậy, những gì bạn cần làm là thay đổi cách khởi tạo ViewController. Thay thế let XXViewController = XXViewController() bằng let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController Điều này yêu cầu chương trình đi đến bảng phân cảnh tìm XXViewController và bắt đầu tất cả IBOutlettrong bảng phân cảnh của bạn.

Hy vọng điều này giúp đỡ ~ GL


Đó không phải là vấn đề
Stefan Arambasich

4

2019, MỘT KHẢ NĂNG CHO VẤN ĐỀ KHÓ KHĂN NÀY:

  • Giả sử bạn có thể có một chế độ xem vùng chứa hiển thị một số loại đồng hồ. Vì vậy, bạn có

    đồng hồ lớp: UIViewController

Bạn thực sự sử dụng nó ở một số nơi trong ứng dụng .

Trên màn hình chính, trên màn hình chi tiết, trên màn hình chỉnh sửa.

Bạn có một ứng dụng hiện đại giống như snapchat phức tạp.

Trong thực tế, Clockthực sự có thể được nạp nhiều hơn một lần tại cùng một thời điểm ở đâu đó trên cùng một màn hình . (Có thể nó bị ẩn trong một số trường hợp.)

Bạn bắt đầu làm việc với một phiên bản của Clockmột trong nhiều bảng phân cảnh của bạn.

Trên bảng phân cảnh đó, bạn thêm một nhãn, NewLabel.

Đương nhiên, bạn thêm cửa hàng trong mã. Mọi thứ sẽ hoạt động. Tất cả các cửa hàng khác hoạt động hoàn hảo.

Bạn chắc chắn đã liên kết ổ cắm.

Nhưng ứng dụng gặp sự cố với NewLabel là con số không.

Xcode cho bạn biết rõ ràng "bạn quên kết nối ổ cắm".

Lý do là vì .......... bạn có "NewLabel" chỉ trên một trong những cách sử dụng bảng phân cảnh của Đồng hồ!

Sự cố thực sự là từ >>> một nơi khác <<<< bạn đang sử dụng Đồng hồ !!!!

Xcode không cho bạn biết sự cố hoàn toàn là từ một nơi khác , không phải từ nơi bạn đang làm việc!

Sự cố thực ra không phải từ nơi bạn đang làm việc - mà là từ một bảng phân cảnh khác , nơi không có mục "Nhãn mới" trên bảng phân cảnh đó !!!

Bực bội.


3

Đối với Swift 3.

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

2

Trước tiên, bạn cần tải hệ thống phân cấp chế độ xem để khởi tạo các cửa hàng trong bảng phân cảnh. Đối với điều này, bạn có thể gọi các phương thức loadView hoặc loadViewIfNeeded theo cách thủ công.


2

Trong trường hợp của tôi, ứng dụng bắt đầu bị lỗi đột ngột. Gỡ lỗi nó tiết lộ rằng tất cả các cửa hàng vẫn còn nilở thời điểm viewDidLoad().

Ứng dụng của tôi vẫn sử dụng ngòi (không phải bảng phân cảnh) cho hầu hết các bộ điều khiển chế độ xem. Mọi thứ đã ở đúng vị trí, tất cả các ổ cắm đều có dây đúng cách. Tôi đã kiểm tra lại.

Chúng tôi thường khởi tạo bộ điều khiển chế độ xem của mình dưới dạng

let newVC = MYCustomViewController()

... mà vì một lý do dường như làm việc miễn là .xib được đặt tên giống như các lớp view controller (không chắc chắn làm thế nào mà các công trình, mặc dù. Chúng tôi đang không gọi init(nibName:bundle:)với đối số bằng không, hoặc trọng init()để làm như vậy trên selfnhư nó thường được đề xuất ...).

Vì vậy, tôi đã cố gắng gọi một cách rõ ràng

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

... chỉ được chào đón với lỗi ngoại lệ thời gian chạy:

*** Chấm dứt ứng dụng do ngoại lệ chưa được thông báo 'NSInternalInconsistencyException', lý do: 'Không thể tải NIB trong gói:' NSBundle </ Users / nicolasmiari / Library / Developer / CoreSimulator / Devices / 3DA3CF21-108D-498F-9649-C4FC9E3C1A8D / data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (đã tải) 'với tên' MYCustomViewController ''

sau đó , tôi thấy nó:

Hộp kiểm "Tư cách thành viên mục tiêu" của tệp .xib đã được bỏ chọn.


Chắc hẳn đã xảy ra khi giải quyết một trong những xung đột hợp nhất thường xuyên liên quan đến tệp dự án Xcode.

Apple chắc chắn cần đưa ra định dạng tệp dự án thân thiện hơn với SCM.


2

Giải pháp làm việc 100% để tạo ViewControllers từ XIB mà không có StoryBoards

  1. Tạo lớp CustomViewController: UIViewController
  2. Tạo chế độ xem CustomViewControllerView.xib
  3. Trong CustomViewControllerView.xib trong Trình tạo giao diện, chọn Trình giữ chỗ -> Chủ sở hữu tệp
  4. Trong "Trình kiểm tra thuộc tính" đặt Lớp thành CustomViewController
  5. Trong "Trình kiểm tra kết nối", kết nối "chế độ xem" với chế độ xem cấp cao nhất của xib (đảm bảo Lớp của chế độ xem cấp cao nhất không trỏ đến CustomViewController)
  6. Trong "Trình kiểm tra kết nối", hãy kết nối các cửa hàng khác (nếu cần / tồn tại)
  7. Tạo một phiên bản của CustomViewController trong bộ điều khiển chế độ xem chính / Đại biểu ứng dụng

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

Câu trả lời tuyệt vời, cảm ơn! Đối với giá trị của nó, bạn cũng có thể ghi đè init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)và gọi bước 7.2 với selftrực tiếp trong lớp CustomViewController.
brandonscript

1

Kiểm tra kết nối IBOutlet của bạn nếu nó được kết nối với chủ sở hữu Tệp hoặc chế độ xem. Có thể có sai lầm.


1

Trường hợp khác:

Các cửa hàng của bạn sẽ không được thiết lập cho đến khi chế độ xem của bộ điều khiển chế độ xem thực sự được khởi tạo, điều này trong trường hợp của bạn có thể xảy ra ngay sau initWithNibName: pack: —tại thời điểm đó chúng sẽ vẫn là con số không. Bất kỳ thiết lập nào bạn thực hiện liên quan đến các cửa hàng đó sẽ diễn ra trong phương thức -viewDidLoad của bộ điều khiển chế độ xem của bạn.


1

Đối với tôi, tôi đã gặp lỗi tương tự trên bảng phân cảnh đã bản địa hóa, một phần tử được thêm vào một số ngôn ngữ chứ không phải trong ngôn ngữ khác, vì vậy tôi có tham chiếu rỗng cho phần tử đó khi chuyển sang ngôn ngữ phần tử bị thiếu, tôi phải xóa bản địa hóa (thừa) cho bảng phân cảnh đó bằng https://stackoverflow.com/a/42256341/1356559 .


1

Đối với tôi, điều này đã sụp đổ bởi vì con số containerViewkhông.

Đây là mã của tôi với Crash .

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

Điều còn thiếu được gọi là super.loadView(). Vì vậy, thêm nó đã giải quyết vấn đề cho tôi.

Mã cố định :

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

bạn không nên gọi trực tiếp loadView () ( developer.apple.com/documentation/uikit/uiviewcontroller/… ), thay vào đó hãy gọi self.view
Lio

1

Tôi đã gặp sự cố tương tự khi trước đó tôi đã thêm đăng ký (_: forCellReuseIdentifier :) cho ô tùy chỉnh sau khi tôi đã xác định số nhận dạng trong bảng phân cảnh. Có mã này trong hàm viewDidLoad (). Sau khi tôi xóa nó, nó hoạt động tốt.


1

Tuy nhiên, một trường hợp khác mà tôi vừa gặp phải. Tôi đã đổi tên lớp của mình cho UIViewController, nhưng tôi quên thay đổi tên của tệp .xib nơi giao diện được tạo.

Một khi tôi nắm bắt được điều này và làm cho tên tệp phản ánh tên lớp, tất cả đều tốt!

Tôi hy vọng điều đó sẽ giúp ai đó.


1

Còn một ...

Nếu bạn có một lớp tùy chỉnh cho UITableViewCell nhưng quên chỉ định Tùy chỉnh trong Kiểu của ô.


1

Bạn có thể xác nhận nếu chế độ xem được tải.

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

0
  1. chọn cả hai .h.mxem các tệp bộ điều khiển
  2. xóa tham chiếu của các tệp đó
  3. thêm lại các tệp vào cây dự án của bạn
  4. mở bảng phân cảnh, cuối cùng xây dựng lại dự án

0

Tình cờAVPlayerViewController thay vì xếp lớp phụ bộ điều khiển chế độ xem của tôi với UIViewController. Bằng cách phát lại nó để UIViewControllermọi thứ trở lại bình thường. Điều này sẽ giúp ích.

Không làm sạch bản dựng (bình thường và đầy đủ), xóa các thư mục dữ liệu có nguồn gốc và thoát Xcode đã làm việc cho tôi.


0

Tôi đã gặp sự cố tương tự sau khi sao chép một lớp (được liên kết với xib) để sử dụng lại nó với một lớp điều khiển chế độ xem khác (được liên kết với bảng phân cảnh). Tôi quên xóa

override var nibName

override var nibBundle

các phương pháp.

Sau khi loại bỏ chúng, các cửa hàng của tôi bắt đầu hoạt động.


0

Tôi thấy bạn sử dụng ViewController!? trong ViewControllerlớp học, bạn phải sử dụng -viewDidLoad, không phải -awakeFromNib , -awakeFromNibsử dụng cho UIViewlớp học



0

Nếu bạn có hai main.storyboardsvà bạn đang thực hiện thay đổi sai, điều này có thể xảy ra. Điều này có thể xảy ra bất cứ lúc nào bạn kết nối ổ cắm từ một ổ cắm không thông thường storyboard.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.