Swift: Trình khởi tạo ViewController tùy chỉnh


87

Làm cách nào để bạn thêm các bộ khởi tạo tùy chỉnh vào các UIViewControllerlớp con trong Swift?

Tôi đã tạo một lớp UIViewControllercon trông giống như sau:

class MyViewController : UIViewController
{
    init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
    {
        self.leftVC = leftVC;
        self.rightVC = rightVC;
        self.gap = gap;

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Khi tôi chạy nó, tôi gặp một lỗi nghiêm trọng:

lỗi nghiêm trọng: sử dụng trình khởi tạo chưa hoàn thành 'init (nibName: pack :)' cho lớp 'MyApp.MyViewController'

Tôi đã đọc ở đâu đó rằng khi thêm trình khởi tạo tùy chỉnh, người ta cũng phải ghi đè, init(coder aDecoder:NSCoder)vì vậy hãy ghi đè điều đó initvà xem điều gì sẽ xảy ra:

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

Nếu tôi thêm điều này, Xcode sẽ phàn nàn điều đó self.leftVC is not initialized at super.init call. Vì vậy, tôi đoán đó cũng không thể là giải pháp. Vì vậy, tôi tự hỏi làm thế nào tôi có thể thêm các trình khởi tạo tùy chỉnh đúng cách vào một ViewControllerlớp con trong Swift (vì trong Objective-C, điều này dường như không phải là vấn đề)?


Làm thế nào bạn đang cố gắng khởi tạo của bạn MyViewController?
Mike Pollard

Tại sao tất cả mọi thứ không nhanh chóng trong viewDidLoad (), có bạn có thể khởi tạo họ chỉ theo cách bạn muốn
tudoricc

@MikePollard với dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Tôi đã phát hiện ra mình cần sử dụng trình khởi tạo initWithNib.
Cầu

3
@tudoricc Bởi vì bạn thường muốn các thuộc tính thể hiện được khởi tạo an toàn trong trình khởi tạo với các tham số đã cho. Bạn không thể làm điều đó trong viewDidLoad vì nó sẽ không được đảm bảo rằng các thuộc tính có sẵn khi cần thiết.
Cầu

Tôi xin lỗi vì trong đầu tôi thấy viewDidLoad () như một trình khởi tạo. thanx cho lời giải thích
tudoricc

Câu trả lời:


123

Đã giải quyết nó! Người ta phải gọi bộ khởi tạo được chỉ định mà trong trường hợp này là init với nibName, rõ ràng là ...

init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
    self.leftVC = leftVC
    self.rightVC = rightVC
    self.gap = gap

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

    setupScrollView()
    setupViewControllers()
}

31
Loại bỏ những dấu chấm phẩy xấu xí đi :)
MobileMon

8
Tôi thích dấu chấm phẩy. Chúng làm cho mã ít mơ hồ hơn, đặc biệt là với những tên và chữ ký API Cocoa / Cocoa-Touch dài dòng đến mức nực cười. Quyết định tồi từ các nhà thiết kế Swift khi loại bỏ chúng IMHO.
Cầu lông:

25
IMHO, nếu bạn gõ một nhân vật và nó không thực hiện việc biên soạn nhị phân, bạn không nên gõ nó :)
Sam Soffes

32
@SamSoffes để bạn không sử dụng (thừa) khoảng trắng? Và bạn làm xáo trộn tất cả các ký hiệu thành các ký tự đơn lẻ?
Victor Jalencas

8
Cuộc thảo luận này khiến tôi liên tưởng đến tab và không gian ở Thung lũng Silicon
Aaron

13

Đối với một UIViewController chung chung hơn, bạn có thể sử dụng nó như Swift 2.0

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

11

Không chắc liệu bạn có giải quyết được đầy đủ vấn đề này hay không ... nhưng tùy thuộc vào cách bạn muốn giao diện lớp của mình trông như thế nào và liệu bạn có thực sự cần chức năng lập trình viên hay không, bạn cũng có thể sử dụng cách bên dưới:

convenience required init(coder aDecoder: NSCoder)
{
    //set some defaults for leftVC, rightVC, and gap
    self.init(leftVC, rightVC, gap)
}

init:leftVC:rightVC:gaplà trình khởi tạo được chỉ định, bạn có thể đáp ứng yêu cầu triển khaiinit:coder bằng cách làm cho nó trở thành một trình khởi tạo thuận tiện gọi trình khởi tạo được chỉ định của bạn.

Điều này có thể tốt hơn

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

bởi vì nếu bạn cần khởi tạo một số thuộc tính, thì bạn sẽ cần phải viết lại chúng.


8

Swift 5

Nếu bạn muốn viết bộ khởi tạo tùy chỉnh UIViewControllerđược khởi tạo bằngstoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Bạn có thể viết bộ khởi tạo tùy chỉnh cho chỉ Optionalcác thuộc tính.

class MyFooClass: UIViewController {
    var foo: Foo?

    init(with foo: Foo) {
        self.foo = foo
        super.init(nibName: nil, bundle: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.foo = nil
    }
}
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.