2008-09-22 22 views
89

Tôi biết cách tạo SEL tại thời gian biên dịch bằng cách sử dụng @selector(MyMethodName:) nhưng điều tôi muốn làm là tạo công cụ chọn động từ NSString. Điều này thậm chí có thể?Làm thế nào tôi có thể tạo động một bộ chọn khi chạy với Objective-C?

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

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

Những gì tôi muốn làm: (pseudo code, đ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 các tài liệu của Apple API, nhưng chưa tìm ra cách nào không dựa vào cú pháp biên dịch @selector(myTarget:).

Trả lời

175

Tôi không phải là lập trình viên Mục tiêu-C, chỉ đơn thuần là người cảm thông, nhưng có thể NSSelectorFromString là những gì bạn cần. Nó được đề cập đến sự bùng nổ trong Runtime Reference 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 phải chải lên trên Google-fu của tôi. đó là chính xác những gì tôi đã (hoặc không phải là nó có thể được) tìm kiếm. – craigb

+0

Vâng, tôi vẫn có các liên kết bay xung quanh trong các chỉ mục của tôi vì tôi đã đọc qua các tài liệu Objective-C 2.0 một vài ngày trước. –

40

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

Hiệu quả nhất là gán giá trị cho biến SEL tại thời gian 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 phải chuyển đổi một chuỗi ký tự thành một bộ chọn khi chạy. Điều này có thể được thực hiện với các chức năng NSSelectorFromString:

setWidthHeight = NSSelectorFromString(aBuffer);

Chỉnh sửa: Thật là đáng tiếc, quá chậm. : P

+2

'NSStringFromSelector (@" doWork ")' chuyển đổi nó theo cách khác (chỉ fyi) – bendytree

+8

Tôi nghĩ bạn có nghĩa là, NSStringFromSelector (@selector (doWork)) – jpswain

+0

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

8

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 người được hỏi trước có thể đề nghị ... nếu bạn thực sự thực sự muốn tạo ra một selector ... không chỉ là "gọi một "mà bạn 'có đặt xung quanh' ...

bạn cần phải tạo một con trỏ hàm sẽ được gọi bằng bạn 'phương pháp mới' .. như vậy cho một phương pháp như [self theMethod:(id)methodArg];, bạn muốn viết ...

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

và sau đó bạn cần tạo IMP chặn tự động, thời gian này, đi qua, "tự", các SEL, và bất kỳ đối số ...

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

và thêm nó vào lớp học của bạn, cùng với chữ ký phương pháp chính xác cho toàn bộ Sucker (trong trường hợp này "[email protected]:@" , khoảng trống Đổi lại, đối tượng gọi, lập luận đối tượng)

class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "[email protected]:@"); 

Bạn có thể thấy một số ví dụ tốt của loại runtime shenanigans, in one of my repos, here.

3

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

Đoạn mã ví dụ trong câu hỏi có thể được viết lại như thế này:

+0

Trên thực tế, '' NSSelectorFromString'' được đề cập bởi @ torsten-marek sử dụng '' sel_registerName'' dưới mui xe. [appledev] (https://developer.apple.com/documentation/foundation/1395294-nsselectorfromstring?language=objc): _ "NSSelectorFromString chuyển biểu diễn ký tự được mã hóa UTF-8 của aSelectorName thành sel_registerName và trả về giá trị được trả về bởi hàm đó "_ – PLG

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