Bộ chọn trong Objective-C?


122

Đầu tiên, tôi không chắc mình thực sự hiểu bộ chọn là gì. Theo hiểu biết của tôi, đó là tên của một phương thức và bạn có thể gán nó cho một lớp kiểu 'SEL' và sau đó chạy các phương thức như responseToSelector để xem liệu người nhận có triển khai phương thức đó hay không. Ai đó có thể đưa ra một lời giải thích tốt hơn?

Thứ hai, đến thời điểm này, tôi có đoạn mã sau:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

Tuy nhiên, mặc dù thingrõ ràng là một loại NSString và phải phản hồi với chuỗi chữ thường, tôi không thể lấy điều kiện 'responseToSelector' để trả về "YES" ...


Bạn muốn đọc mô tả Bộ chọn trên trang web dành cho nhà phát triển của Apple: Bộ chọn .
lothar

14
Khóa học Stanford CS193P bài tập 1B? Tôi có chính xác câu hỏi tương tự ở đây! :)
Corstian Boerman

Câu trả lời:


181

Bạn phải rất cẩn thận về tên phương thức. Trong trường hợp này, tên phương thức chỉ là " lowercaseString", không phải " lowercaseString:" (lưu ý sự vắng mặt của dấu hai chấm). Đó là lý do tại sao bạn bị NOtrả lại, bởi vì NSStringcác đối tượng phản hồi lowercaseStringthông báo nhưng không phản hồilowercaseString: tin nhắn.

Làm thế nào để bạn biết khi nào cần thêm dấu hai chấm? Bạn thêm dấu hai chấm vào tên thư nếu bạn thêm dấu hai chấm khi gọi nó, điều này xảy ra nếu nó có một đối số. Nếu nó không có đối số (như trường hợp với lowercaseString), thì không có dấu hai chấm. Nếu cần nhiều hơn một đối số, bạn phải thêm các tên đối số bổ sung cùng với dấu hai chấm của chúng, như trong compare:options:range:locale:.

Bạn cũng có thể xem tài liệu và lưu ý sự hiện diện hay vắng mặt của dấu hai chấm ở cuối.


12

Bộ chọn là một cách hiệu quả để tham chiếu các phương thức trực tiếp trong mã đã biên dịch - trình biên dịch là thứ thực sự gán giá trị cho một SEL.

Khác đã bao gồm phần thứ hai của q của bạn, dấu ':' ở cuối khớp với một chữ ký khác với những gì bạn đang tìm kiếm (trong trường hợp này, chữ ký đó không tồn tại).


10

Đó là bởi vì bạn muốn @selector(lowercaseString), không phải @selector(lowercaseString:). Có một sự khác biệt nhỏ: cái thứ hai ngụ ý một tham số (lưu ý dấu hai chấm ở cuối), nhưng - [NSString lowercaseString]không có tham số.


5

Trong trường hợp này, tên của bộ chọn bị sai. Dấu hai chấm ở đây là một phần của chữ ký phương thức; nó có nghĩa là phương thức nhận một đối số. Tôi tin rằng bạn muốn

SEL sel = @selector(lowercaseString);

3

Phương thức của NSString là lowercaseString(0 đối số), không phải lowercaseString:(1 đối số).


1

Đừng nghĩ dấu hai chấm là một phần của tên hàm, hãy nghĩ nó như một dấu phân cách, nếu bạn không có bất kỳ thứ gì để phân tách (không có giá trị nào đi cùng với hàm) thì bạn không cần nó.

Tôi không chắc tại sao nhưng tất cả những thứ OO này dường như đều xa lạ với các nhà phát triển của Apple. Tôi thực sự khuyên bạn nên lấy Visual Studio Express và chơi với nó. Không phải vì cái này tốt hơn cái kia, chỉ là đó là một cách tốt để xem xét các vấn đề và cách suy nghĩ của thiết kế.

Giống

introspection = reflection
+ before functions/properties = static
- = instance level

Luôn luôn tốt khi nhìn một vấn đề theo nhiều cách khác nhau và lập trình là câu đố cuối cùng.


0

Theo hiểu biết của tôi về tài liệu của Apple, một bộ chọn đại diện cho tên của phương thức mà bạn muốn gọi. Điều thú vị về bộ chọn là bạn có thể sử dụng chúng trong trường hợp phương pháp chính xác được gọi khác nhau. Ví dụ đơn giản, bạn có thể làm một số việc như:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];

0

Theo tài liệu của apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Bộ chọn là tên được sử dụng để chọn một phương thức để thực thi cho một đối tượng hoặc mã định danh duy nhất thay thế tên khi mã nguồn được biên dịch. Một bộ chọn tự nó không làm bất cứ điều gì. Nó chỉ đơn giản là xác định một phương pháp. Điều duy nhất làm cho tên phương thức bộ chọn khác với một chuỗi thuần túy là trình biên dịch đảm bảo rằng bộ chọn là duy nhất. Điều làm cho một bộ chọn hữu ích là (kết hợp với thời gian chạy) nó hoạt động giống như một con trỏ hàm động, đối với một tên nhất định, sẽ tự động trỏ đến việc triển khai một phương thức thích hợp cho bất kỳ lớp nào mà nó được sử dụng. Giả sử bạn có một bộ chọn để chạy phương thức và các lớp Dog, Athlete và ComputerSimulation (mỗi lớp triển khai một phương thức chạy).

Ví dụ: (lldb) breakpoint - set selector viewDidLoad

Điều này sẽ đặt điểm ngắt trên tất cả các triển khai viewDidLoad trong ứng dụng của bạn. Vì vậy, bộ chọn là loại định danh toàn cầu cho một phương thức.

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.