2014-06-29 17 views
8

Vấn đề với phân lớp UITextView (và UICollectionView) là hàm tạo được chỉ định là "initWithFrame". Nhưng trong cuộc sống thực, khi nó tải từ bảng phân cảnh, initWithCoder sẽ được gọi.Swift: Phân lớp UITextView hoặc UICollectionView và khởi tạo thích hợp

class BorderedTextView: UITextView { 
    //will be called 
    init(coder: NSCoder?){ 
     //constant values here is not an option 
     super.init(frame: CGRectMake(0,0,100,100), textContainer: nil) 
    } 
    //will not be called 
    init(frame: CGRect, textContainer: NSTextContainer!) { 
     super.init(frame: frame, textContainer: textContainer) 
    } 
} 

Kết quả là tôi không thể gọi bất kỳ mã tùy chỉnh giao diện người dùng nào trên init và cung cấp bất kỳ giá trị khởi tạo nào cho biến Swift ngoại trừ các giá trị mặc định.

Tôi cho rằng vấn đề có thể được giải quyết tạm thời bằng cách trích xuất kích thước khung hình từ "coder", nhưng tôi không tìm thấy chìa khóa cho nó.

Bất kỳ ý tưởng nào tốt hơn giá trị khung hardcode?

+0

Tôi hy vọng rằng 'super.init (coder: coder)' hoạt động - và cho các lớp con của UIView hoặc UILabel nó (ít nhất trình biên dịch không phàn nàn). Nhưng đối với các lớp con của 'UITextView', nó không thành công với thông báo lỗi" Phải gọi initializer được chỉ định ... ". Một lỗi Swift? –

+0

Cách giải quyết có thể là thực hiện khởi tạo trong 'awakeFromNib' thay thế. –

+0

Bạn nói đúng, có vẻ như nó hoạt động cho UIView (tôi đã cập nhật câu hỏi). Nhưng tôi cũng có cùng một vấn đề với UICollectionView, do đó, vấn đề không chỉ với UITextView. –

Trả lời

12

(Từ nhận xét ở trên của tôi :) Điều này giống như lỗi Swift. initWithCoder: được gọi khi một cái nhìn (hoặc bộ điều khiển xem) được khởi tạo từ một tập tin Storyboard hoặc NIB, và trọng rằng phương pháp làm việc trong Objective-C:

- (instancetype)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     // Initialization code 
    } 
    return self; 
} 

Nhưng mã Swift tương đương

class BorderedTextView: UITextView { 
    init(coder: NSCoder!) { 
     super.init(coder: coder) 
    } 
} 

không thành công với thông báo lỗi "phải gọi một trình khởi tạo được chỉ định của siêu lớp 'UITextView'".

Sự cố này xảy ra với tất cả các lớp con của UIView có trình khởi tạo được chỉ định của riêng chúng (ví dụ: UITextView, UICollectionView). Mặt khác, vấn đề không xảy ra với các lớp con của UILabel, trong đó không có trình khởi tạo được chỉ định. Ngôn ngữ Swift rất nghiêm ngặt về việc gọi trình khởi tạo được chỉ định của lớp siêu, nhưng phải có cách để ghi đè initWithCoder: cho tất cả các lớp con tùy chỉnh UIView, vì vậy tôi xem đây là lỗi Swift.

Là một khắc phục, bạn có thể thực hiện khởi động tùy chỉnh trong

override func awakeFromNib() { 
    super.awakeFromNib() 
    // ... 
} 

Cập nhật cho Swift 1.2: này dường như đã được sửa. Tham số đã thay đổi, nó không còn là một tùy chọn không được khai báo hoàn toàn. Vì vậy, đây biên dịch và làm việc như mong đợi (thử nghiệm với Xcode 6.4):

class BorderedTextView: UITextView { 
    required init(coder: NSCoder) { 
     super.init(coder: coder) 

     // ... 
    } 
} 

Cập nhật cho Swift 2 (Xcode 7):init(coder:) là một failable initializer bây giờ:

class BorderedTextView: UITextView { 
    required init?(coder: NSCoder) { 
     super.init(coder: coder) 

     // ... 
    } 
} 
+0

Tính năng này có hoạt động trong Swift 1.2 không? – Jacob

0

Câu trả lời hoàn chỉnh hơn cho Swift 3:

class ValidatedTextField:UITextField, UITextFieldDelegate 
{ 
    required override init(frame: CGRect) 
    { 
     super.init(frame: frame) 
     //custom code 
     self.delegate = self 
    } 

    required init?(coder: NSCoder) 
    { 
     super.init(coder: coder) 
     //custom code 
     self.delegate = self 
    } 
Các vấn đề liên quan