Lỗi nghiêm trọng: sử dụng trình khởi tạo chưa được thực hiện 'init (coder :)' cho lớp


156

Tôi quyết định tiếp tục dự án còn lại của mình với Swift. Khi tôi thêm lớp tùy chỉnh (lớp con của UIViewcontroller) vào trình điều khiển chế độ xem bảng phân cảnh của mình và tải dự án, ứng dụng sẽ gặp sự cố bất ngờ với lỗi sau:

lỗi nghiêm trọng: sử dụng trình khởi tạo chưa được thực hiện 'init (coder :)' cho lớp

Đây là một mã:

import UIKit

class TestViewController: UIViewController {

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    override func viewDidLoad() {
        super.viewDidLoad()
              // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
}

Xin đề nghị một cái gì đó

Câu trả lời:


207

Vấn đề

Điều này được gây ra bởi sự vắng mặt của trình khởi tạo init?(coder aDecoder: NSCoder)trên mục tiêu UIViewController. Phương pháp đó là bắt buộc vì khởi tạo một UIViewControllertừ một UIStoryboardcuộc gọi nó.

Để xem cách chúng tôi khởi tạo a UIViewControllertừ a UIStoryboard, vui lòng xem tại đây

Tại sao điều này không phải là vấn đề với Objective-C?

Bởi vì Objective-C tự động kế thừa tất cả các bộ UIViewControllerkhởi tạo cần thiết .

Tại sao Swift không tự động kế thừa các công cụ khởi tạo?

Swift theo mặc định không kế thừa các trình khởi tạo do an toàn. Nhưng nó sẽ kế thừa tất cả các trình khởi tạo từ siêu lớp nếu tất cả các thuộc tính có một giá trị (hoặc tùy chọn) và lớp con chưa xác định bất kỳ trình khởi tạo được chỉ định nào.


Giải pháp

1. Phương pháp đầu tiên

Thực hiện thủ công init?(coder aDecoder: NSCoder)trên mục tiêuUIViewController

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

2. Phương pháp thứ hai

Xóa init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)mục tiêu của bạn UIViewControllersẽ kế thừa tất cả các công cụ khởi tạo cần thiết từ siêu lớp khi Dave Wood chỉ vào câu trả lời của mình bên dưới



4
Cảm ơn vì điều đó. Theo dõi nhanh ... Khi bạn tạo tệp TableViewControll, Xcode đã bao gồm init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Tại sao chúng ta có thể có hai hàm init? Và có ai biết tại sao Apple không bao gồm init thứ 2 theo mặc định không?
Trevor McKendrick

Điều này không liên quan gì đến iOS 7 hoặc iOS 8. Điều này được kết nối với cách Swift kế thừa những người hướng dẫn!
Sulthan

init công cộng (xem: UIViewController, khung: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (khung: khung)}
scrainie

Phương pháp đầu tiên đã làm việc! Bảng năng động của tôi cuối cùng chứa đầy các tế bào động !!! Tất cả chỉ vì dòng fatalError( "init(coder:) has not been implemented")dừng ứng dụng của tôi.
Jose Manuel Abarca Rodríguez

25

Một tùy chọn khác ngoài @ 3r1d là thay vào đó loại bỏ phương thức init sau khỏi lớp của bạn:

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // Custom initialization
}

Bao gồm phương thức init đó, ngăn lớp phụ kế thừa init(coder aDecoder: NSCoder!)từ lớp siêu của nó. Bằng cách không bao gồm nó, lớp của bạn sẽ kế thừa cả hai.

Lưu ý: Xem WWDC 2014 Phiên 403 "Trung cấp Swift" ở khoảng 33:50 để biết thêm chi tiết.


Cảm ơn đã chỉ ra lời giải thích về Phần 403. Nhưng nếu lớp con chỉ có các trình khởi tạo tiện lợi thì nó sẽ kế thừa các trình khởi tạo siêu lớp phải không?
jamiltz

1
Đúng. Bạn chỉ ngăn các phương thức init siêu hạng được kế thừa nếu bạn cung cấp các phương thức init được chỉ định của riêng bạn (những phương thức gọi siêu cấp). Sau đó, bạn phải chỉ định loại siêu năng lực nào sẽ hỗ trợ bằng cách thêm chúng vào lớp của bạn và chỉ cần gọi phiên bản siêu (như trong câu trả lời của @ 3r1d)
Dave Wood

Chỉ có init () không có (được chỉ định) init () trong lớp con của bạn sẽ gây ra lỗi biên dịch. Đó là bởi vì hàm init () tiện lợi phải gọi self.init () bên trong định nghĩa hàm.
Ohmy

@narumolPug Điều đó không chính xác. Bạn không cần bao gồm initcác phương pháp được chỉ định . Lớp con của bạn sẽ kế thừa chúng từ lớp siêu. Bạn vẫn có thể gọi self.init()mà sẽ thực hiện phiên bản siêu.
Dave Wood

Thời điểm chính xác của video có thể được tìm thấy ở đây youtu.be/W1s9ZjDkSN0?t=2030
Mật ong

10

Đối với những người có cùng vấn đề với swift UICollectionViewCells, hãy thêm mã mà @ 3r1d đề xuất cho UICollectionViewCelllớp tùy chỉnh của bạn chứ không phải vào Trình điều khiển xem:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}

bạn đang đề cập đến UICollectionViewCell nào? Khởi đầu với coder là cách để khởi tạo viewContoder
E-Riddie

Không phải trong ví dụ này nhưng trong trường hợp bất kỳ ai có vấn đề với nó (tôi đã làm) ... nếu bạn cố gắng sử dụng UICollectionViewCont kiểm soát, trong tệp .swift tùy chỉnh của bạn, bạn cần đặt init với bộ mã hóa.
Nick Yap

2
Bạn cần thêm mã này mỗi khi bạn sử dụng cách này ngay lập tức stackoverflow.com/questions/24035984/iêu
E-Riddie

3

Đối với những người cần mã trong Swift:

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

[Chỉnh sửa] Đây là phiên bản cũ hơn của Swift. Có thể không hoạt động nữa.


3

Tôi đã gặp vấn đề này trong một bộ sưu tập Xem chương trình và mặc dù op đang hỏi về một vc tôi vẫn gặp phải câu hỏi này khi tìm kiếm câu trả lời. Đối với tôi vấn đề là tôi đã có

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

thực hiện vì vậy câu trả lời hàng đầu đã không làm việc. Những gì tôi không có trong tế bào là trình khởi tạo:

// my programmatic cell was missing this
override init(frame: CGRect) {
    super.init(frame: frame)
}

Khi tôi thêm nó, lỗi đã biến mất


1

Thay vì thêm một số phương thức để làm cho cơ chế bên trong hoạt động tốt, tôi sẽ đi với việc xác định các thuộc tính của mình là @lazy và khởi tạo chúng ngay trong phạm vi lớp.


bạn cũng có thể khai báo tài sản của bạn là tùy chọn thông qua ?.
Julian B.
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.