2016-05-01 14 views
24

Tôi có một dự án Swift nơi tôi muốn đính kèm một phương thức vào sự kiện nhấn của UIButton. Tôi có đoạn mã sau:Swift muốn đối số của #selector để được tiếp xúc với Objective-C

class MyClass { 
    let myButton = UIButton(frame: CGRectMake(50, 50, 100, 50)) 
    init() { 
    myButton.addTarget(self, #selector(self.didTap(_:)), forControlEvents: .TouchUpInside) 
    } 

    func didTap(sender: UIButton) { 
    print("Tapped") 
    } 
} 

XCode nhấn mạnh dòng addTarget tôi và nói:

Argument of '#selector' refers to a method that is not exposed to Objective-C 

Nếu tôi thêm tiền tố @objc-func didTap của tôi như nó gợi ý sau đó tất cả mọi thứ hoạt động tốt.

Tôi có điều gì đó được bật trong cài đặt bản dựng của mình gây ra hành vi lạ này không?

PS. Tôi nhận được hành vi này trong 7.3.1. Nhưng nếu tôi thử điều này trong 7.2.1, nó không chấp nhận cú pháp #selector(method(_:)), và Selector("method:") hoạt động tốt.

Trả lời

58

Bộ chọn là một tính năng của Mục tiêu-C và chỉ có thể được sử dụng với các phương pháp được tiếp xúc với thời gian chạy Obj-C động. Bạn không thể có một bộ chọn cho một phương thức Swift thuần túy.

Nếu lớp học của bạn được kế thừa từ NSObject thì phương pháp công khai của nó được tự động tiếp xúc với Obj-C. Vì lớp của bạn không kế thừa từ NSObject, bạn phải sử dụng thuộc tính @objc để cho biết rằng bạn muốn phương pháp này tiếp xúc với Obj-C để nó có thể được gọi bằng bộ chọn Obj-C.

#selector() là cú pháp mới trong Swift 2.2. Nó cho phép trình biên dịch kiểm tra rằng bộ chọn mà bạn đang cố gắng sử dụng thực sự tồn tại. Cú pháp cũ không còn được dùng nữa và sẽ bị loại bỏ trong Swift 3.0.

+1

câu trả lời ngắn gọn và toàn diện. Chính xác đến điểm. – MadNik

11

Nếu tôi thêm tiền tố @objc vào func didTap như nó gợi ý thì mọi thứ hoạt động tốt.

Tôi có điều gì đó được bật trong cài đặt bản dựng của mình gây ra hành vi lạ này không?

No. Những gì bạn thấy là bình thường. Selectors là một tính năng Objective-C, và như vậy là sử dụng một bộ chọn để gửi một thông báo đến cá thể lớp của bạn. Cách duy nhất Objective-C có thể gửi thông điệp đó là nếu nó có thể thấy cả lớp của bạn hoặc chính phương thức đó. MyClass không có nguồn gốc từ NSObject, vì vậy Objective-C không thể nhìn thấy nó. Vì vậy, nếu bạn không muốn lấy nó từ NSObject, ít nhất bạn cũng phải vạch ra phương thức cho Objective-C bằng cách đánh dấu nó bằng @objc.

và Selector ("phương pháp:") hoạt động tốt

Trong các phiên bản trước đó của Swift, trình biên dịch sẽ không giúp bạn trong trường hợp này, do đó, mã của bạn sẽ biên dịch. Nhưng bạn sẽ bị rơi khi tin nhắn đến và Objective-C không thể tìm ra phương pháp. Toàn bộ điểm của cú pháp #selector là giúp bạn tránh được sự cố đó. Và đó chỉ là những gì nó đã làm!

-2

Bạn phải phân lớp từ NSObject

Các vấn đề liên quan