Tại sao tôi không thể gọi mặc định super.init () trên UIViewController trong Swift?


84

Tôi không sử dụng một UIViewControllerbảng phân cảnh và tôi muốn có một initchức năng tùy chỉnh nơi tôi chuyển một NSManagedObjectIDtrong số các đối tượng. Tôi chỉ muốn gọi super.init()như tôi có trong Objective-C. Như thế này:

init(objectId: NSManagedObjectID) {
    super.init()
}

Nhưng tôi gặp lỗi trình biên dịch sau:

Phải gọi trình khởi tạo được chỉ định của lớp siêu cấp UIViewController

Tôi có thể đơn giản là không làm điều này nữa không?

Câu trả lời:


119

Trình khởi tạo được chỉ định cho UIViewControllerinitWithNibName:bundle:. Bạn nên gọi nó thay thế.

Xem http://www.bignerdranch.com/blog/real-iphone-crap-2-initwithnibnamebundle-is-the-designated-initializer-of-uiviewcontroller/

Nếu bạn không có nib, hãy chuyển nilnibName vào (gói cũng là tùy chọn). Sau đó, bạn có thể tạo một chế độ xem tùy chỉnh trong loadViewhoặc bằng cách thêm các chế độ xem phụ vào self.viewtrong viewDidLoad, giống như bạn đã từng làm.


4
Vì vậy, hiện tại tôi không thể tạo phương thức init tùy chỉnh trong lớp con UIViewController không phải từ nib?
SirRupertIII

1
Ahh, cảm ơn !! Tôi đã chuyển vào "" cho tên ngòi.
SirRupertIII

2
Ồ, sau khi đào sâu một chút, hóa ra nó initWithCoder:đến từ NSCodinggiao thức ... Tôi vẫn không thể tìm ra vai trò của nó trong việc khởi tạo cá thể UIViewController là gì, cho dù đó là bộ khởi tạo "được chỉ định" của UIViewController hay bất kỳ lớp cha nào của nó .. .
Nicolas Miari

6
Cảm ơn! Đối với bản sao nhanh / dán chỉ cần gọi này sau khi cài đặt của bạn lettài sản, nếu có: super.init(nibName: nil, bundle: nil).
Ferran Maylinch

3
Init With coder được sử dụng khi bạn cần khôi phục trạng thái. Khi bạn lưu trạng thái của bộ điều khiển chế độ xem bằng cách sử dụng chức năng khôi phục trạng thái, bộ mã hóa sẽ trả về các giá trị bạn đã lưu khi trạng thái được lưu. Từ đó, bạn có thể xây dựng lại bộ điều khiển chế độ xem về trạng thái ban đầu cuối cùng của nó kể từ khi bạn đóng ứng dụng. Vì vậy, để người sử dụng mà nó họ rời khỏi
Esko918

44

Một giải pháp hay khác là khai báo trình khởi tạo mới của bạn dưới dạng trình conveniencekhởi tạo như sau:

convenience init( objectId : NSManagedObjectID ) {
    self.init()

    // ... store or user your objectId
}

Nếu bạn khai báo không có bộ khởi tạo được chỉ định nào trong lớp con của mình, chúng sẽ được kế thừa tự động và bạn có thể sử dụng self.init()trong bộ khởi tạo thuận tiện của mình.

Trong trường hợp của UIViewController phương pháp init mặc định sẽ gọi init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!)với nilcho cả đối số (Command-Click vào UIViewController sẽ cung cấp cho bạn thông tin đó).

TL; TR : Nếu bạn thích làm việc theo chương trình với UIViewControllers thì đây là một ví dụ làm việc hoàn chỉnh bổ sung trình khởi tạo mới với đối số tùy chỉnh:

class MyCustomViewController: UIViewController {
    var myString: String = ""

    convenience init( myString: String ) {
        self.init()

        self.myString = myString
    }
}

Đây là một giải pháp thanh lịch hơn và làm việc tại bất kỳ trường hợp chung
Ciprian

2
Tôi đã thử thực hiện việc này trong một tiện ích mở rộng và nó tự gọi tên đệ quy.
Danyal Aytekin

12
Các "lừa" để câu trả lời này là myStringđược thiết lập để ""nên initkhông cần thiết. Giải pháp này sụp đổ nếu bạn không muốn sử dụng một giá trị ban đầu, và trong trường hợp đó bạn cần phải sử dụngself.init(nibName: nil, bundle:nil)
Dan Rosenstark

2
@Yar hoặc bạn thực hiện myStringsở hữu một tùy chọn
Klaas

1
@Klaas vâng: vấn đề của tôi là tôi CHỈ sử dụng trình khởi tạo để tránh các tùy chọn và lấy mã của tôi để biên dịch.
Dan Rosenstark

16

Để cải thiện câu trả lời của Occulus :

init() {
     super.init(nibName: nil, bundle: nil)
}

15

Cập nhật: thêm liên kết

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init

Theo tài liệu dành cho iOS, trình khởi tạo được chỉ định cho UIViewController là initWithNibName: bundle:.

Nếu bạn phân lớp UIViewController, bạn phải gọi siêu triển khai của phương thức này, ngay cả khi bạn không sử dụng NIB.

Bạn có thể thực hiện như sau:

init(objectId : NSManagedObjectID) {

    super.init(nibName: (xib's name or nil'), bundle: nil)

   // other code...
}

hoặc là

Khai báo trình khởi tạo mới làm trình khởi tạo tiện lợi:

 convenience init( objectId : NSManagedObjectID ) {

    self.init()

     // other code...

}


1
Bạn nên liên kết đến bản gốc để ghi nhận tác giả, thay vì để nó dưới dạng bản tóm tắt màn hình.
Nathan Tuggy

Tôi đã sử dụng quy trình tương tự như @NcNc đã nói. Nó đã làm việc cho tôi. Đây là liên kết
Anil Gupta

@NathanTuggy Không, anh ấy không nên. Các liên kết có tính năng hết hạn hoặc di chuyển vào một ngày nào đó. Ai muốn thấy lỗi 404 thay vì thông tin mà anh ấy / cô ấy đang tìm kiếm?
mykolaj

1
@mykolaj: Thông tin đã có ở đây, trong câu trả lời này. (Nếu không, tôi đã gắn cờ để xóa như một câu trả lời chỉ có liên kết.) Nhưng ghi nhận tác giả cũng rất quan trọng để bất kỳ ai đọc bài này đều có thể tìm hiểu nguồn gốc của nó và ghi công cho họ. Ảnh chụp màn hình không hoạt động cho điều đó, nhưng một liên kết thì có. Nếu một liên kết bị thối rữa, thì đó là điều không may, nhưng bạn không thể nói với tôi rằng đó là một tình huống tồi tệ hơn là không bao giờ có bất kỳ loại tín dụng nào. Những sự phản đối SO có câu trả lời liên kết chỉ là để link- chỉ câu trả lời. Không liên kết. Liên kết thông tin cũng là công thức mong muốn.
Nathan Tuggy

@NathanTuggy Tôi vừa thêm liên kết. Cảm ơn lời nhắc của bạn
NcNc 22/03/18
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.