Làm cách nào để tạo động một bộ chọn trong thời gian chạy với Objective-C?


93

Tôi biết cách tạo một SELlúc biên dịch bằng cách sử dụng @selector(MyMethodName:)nhưng những gì tôi muốn làm là tạo một bộ chọn động từ một NSString. Điều này thậm chí có thể?

Những gì tôi có thể làm được:

SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];

Điều tôi muốn làm: (mã giả, điều này rõ ràng không hoạt động)

SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];

Tôi đã tìm kiếm tài liệu API của Apple, nhưng không tìm thấy cách nào không dựa vào @selector(myTarget:)cú pháp thời gian biên dịch .

Câu trả lời:


180

Tôi không phải là một lập trình viên Objective-C, chỉ đơn thuần là một người đồng tình, nhưng có lẽ NSSelectorFromString là thứ bạn cần. Nó được đề cập rõ ràng trong Tham chiếu thời gian chạy mà bạn có thể sử dụng nó để chuyển đổi một chuỗi thành một bộ chọn.


5
Tôi cần tìm hiểu kỹ về Google-fu của mình. đó chính xác là những gì tôi (hoặc không như nó có thể) đang tìm kiếm.
craigb 22/09/08

Chà, tôi vẫn thấy các liên kết bay xung quanh trong dấu trang của mình kể từ khi tôi đọc qua tài liệu Objective-C 2.0 cách đây vài ngày.
Torsten Marek

40

Theo tài liệu XCode, về cơ bản psuedocode của bạn hoạt động đúng.

Hiệu quả nhất là gán giá trị cho các biến SEL tại thời điểm biên dịch với chỉ thị @selector (). Tuy nhiên, trong một số trường hợp, một chương trình có thể cần chuyển đổi một chuỗi ký tự thành một bộ chọn trong thời gian chạy. Điều này có thể được thực hiện với chức năng NSSelectorFromString:

setWidthHeight = NSSelectorFromString(aBuffer);

Chỉnh sửa: Bummer, quá chậm. : P


2
NSStringFromSelector(@"doWork")cải nó theo cách khác (chỉ FYI)
bendytree

8
Tôi nghĩ ý bạn là, NSStringFromSelector (@selector (doWork))
jpswain

Và bộ chọn đó được cho là làm gì? Chúng ta không nên chỉ định một khối hay một cái gì đó?
user4951 4/11/12

12

Tôi phải nói rằng nó phức tạp hơn một chút so với câu trả lời của những người trả lời trước có thể đề xuất ... nếu bạn thực sự muốn tạo một bộ chọn ... không chỉ "gọi một" mà bạn "đã đặt xung quanh" .. .

Bạn cần tạo một con trỏ hàm sẽ được gọi bởi phương thức "mới" của bạn .. vì vậy đối với một phương thức như [self theMethod:(id)methodArg];, bạn sẽ viết ...

void (^impBlock)(id,id) = ^(id _self, id methodArg) { 
     [_self doSomethingWith:methodArg]; 
};

và sau đó bạn cần tạo IMPkhối động, lần này là truyền, "tự" SEL, và bất kỳ đối số nào ...

void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);

và thêm nó vào lớp của bạn, cùng với một chữ ký phương thức chính xác cho toàn bộ phần mềm (trong trường hợp này là "v@:@"void return, object caller, object object)

 class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");

Bạn có thể xem một số ví dụ điển hình về loại trò tai quái trong thời gian chạy này , trong một trong những repo của tôi, tại đây.


5

Tôi biết điều này đã được trả lời từ lâu, nhưng tôi vẫn muốn chia sẻ. Điều này cũng có thể được thực hiện bằng cách sử dụng sel_registerName.

Mã ví dụ trong câu hỏi có thể được viết lại như sau:

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];

2
Trên thực tế, NSSelectorFromStringđược đề cập bởi @ torsten-marek sử dụng ẩn sel_registerName. appledev : "NSSelectorFromString chuyển biểu diễn ký tự được mã hóa UTF-8 của aSelectorName đến sel_registerName và trả về giá trị được trả về bởi hàm đó"
PLG
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.