2014-10-03 16 views
26

Không thể kết nối thuộc tính đại biểu của CustomView được khai báo là @IBOutlet tới ViewController trong Trình tạo giao diện - không thể thiết lập kết nối.Trình tạo giao diện, @IBOutlet và các giao thức cho đại biểu và dữ liệuSource trong Swift

Dưới đây là đoạn code

class CustomView: UIView { 
    @IBOutlet var delegate: CustomViewDelegate? 
} 

@objc protocol CustomViewDelegate { 
    ... 
} 


class ViewController: UIViewController, CustomViewDelegate { 
    ... 
} 

@objc được sử dụng vì swift protocol, IBOutlet property cannot have non-object type, không biết tại sao protocol CustomViewDelegate: class {} không hoạt động.

Bất kỳ ai khác đều gặp phải điều gì đó như thế?

+0

Liệu 'của bạn UIViewController' trong Interface Builder có các lớp học đặc biệt thiết lập cho 'ViewController'? Ngoài ra, nó thường là một yêu cầu (cuối cùng tôi đã kiểm tra) rằng các thuộc tính '@ IBOutlet' được định nghĩa là các loại chưa được loại bỏ hoàn toàn, như sau:' CustomViewDelegate! '. Điều này cho phép họ được 'nil' tại instantiation, trong khi cho phép bạn sử dụng chúng mà không có ràng buộc tùy chọn sau khi họ đã được kết nối. –

Trả lời

56

Từ release notes Xcode:

Interface Builder không hỗ trợ kết nối với một ổ cắm trong một file Swift khi loại của cửa hàng là một giao thức.

Giải pháp thay thế: Khai báo loại ổ cắm là AnyObject hoặc NSObject, kết nối các đối tượng với ổ cắm bằng cách sử dụng Trình tạo giao diện, sau đó thay đổi kiểu của đầu ra trở lại giao thức.

CHỈNH SỬA: Ghi chú phát hành Xcode 9 beta 3 không còn cần thiết.

+3

Wowzer! Điều này làm việc, cảm ơn. Apple ... hãy làm cho nó cùng nhau! – josephap

+0

Không. "Lớp không tuân thủ khóa-giá trị" sau khi thay đổi trở lại loại Giao thức. – stone

+0

Điều này chỉ làm việc một phần cho tôi. Trong một trường hợp, nơi tôi xác định đại biểu của riêng tôi trên một UIView được nối với một UIViewController, nó làm việc. Trong một, nơi tôi xác định đại biểu của tôi trên một UIViewController được nối với UIViewController khác, nó không. Tôi đã thử rất nhiều cấu hình. Bất kỳ ý tưởng nào @matt những gì có thể xảy ra ở đây? – josephap

8

Một đó là không đẹp, nhưng:

@IBOutlet weak var ibDelegate: NSObject? 
@IBOutlet weak var ibDataSource: NSObject? 
var delegate: MultipleButtonViewDelegate? { return ibDelegate as? MultipleButtonViewDelegate } 
var dataSource: MultipleButtonViewDataSource? { return ibDataSource as? MultipleButtonViewDataSource } 
+0

Câu trả lời hay! Sử dụng cách này để ngăn chặn loại thay đổi thường là Outlet. – t4nhpt

13

Adam Waite provides a nice workaround. Tôi tuy nhiên thích các giải pháp sau đây vì nó nhấn mạnh đến cách giải quyết và tài sản phụ cũng có thể dễ dàng được gỡ bỏ một lần Xcode được cố định.

class CustomView: UIView { 
    @IBOutlet 
    public var delegate: CustomViewDelegate? 

    /// Workaround for Xcode bug that prevents you from connecting the delegate in the storyboard. 
    /// Remove this extra property once Xcode gets fixed. 
    @IBOutlet 
    public var ibDelegate: AnyObject? { 
     get { return delegate } 
     set { delegate = newValue as? CustomViewDelegate } 
    } 

    func someMethod() { 
     // Here we always refer to `delegate`, not `ibDelegate` 
     delegate?.onSomethingHappened() 
    } 
} 

@objc protocol CustomViewDelegate { 
    ... 
} 

Này, lỗi này đã một năm rưỡi chưa?

1

Đối với tôi, lý do là chế độ xem bảng là nil tại thời điểm tôi đã cố đặt nguồn dữ liệu và ủy quyền của mình. Điều này là do trình khởi tạo được chỉ định gọi initWithNibName:bundle: không đảm bảo initialized connections. Trì hoãn cài đặt đại biểu và nguồn dữ liệu của tôi cho viewDidload hoạt động như một sự quyến rũ.

2

Đây là một chủ đề cũ, nhưng tôi nghĩ rằng tôi muốn chỉ ra rằng tính Xcode 9 beta 3, nó bây giờ có thể kết nối đại biểu tùy chỉnh được viết nhanh chóng với trình tạo giao diện.

Theo ghi chú phát hành

Interface Builder bây giờ nhận ra cửa hàng, hành động và inspectable tính tuyên bố trên các lớp học trong đó có một phần mở rộng giao thức Swift. (22201035)

// Can connect this to interface builder now  
class MyViewController: UIViewController { 
    @IBOutlet weak var myDelegate: TheNewDelegate? 
} 
Các vấn đề liên quan