2012-05-28 32 views
13

Vì vậy, tôi đã rối tung xung quanh với các objc-runtime nữa (ngạc nhiên ngạc nhiên), và tôi thấy một khối thú vị của mã here:Tại sao chúng ta không thể sử dụng C-strings như SELs?

const char *sel_getName(SEL sel) { 
#if SUPPORT_IGNORED_SELECTOR_CONSTANT 
    if ((uintptr_t)sel == kIgnore) return "<ignored selector>"; 
#endif 
    return sel ? (const char *)sel : "<null selector>"; 
} 

Vì vậy, điều này nói với tôi là một SEL tương đương vào một chuỗi C, theo mọi cách thức. Làm một bãi chứa hex của 16 byte đầu tiên của SEL có chứa @selector(addObject:) đưa ra sau đây:

61 64 64 4F 62 6A 65 63 74 3A 00 00 00 00 00 00

Đó là bằng C-string addObject:.

Với điều đó đã nói, tại sao mã này gặp sự cố khi tôi sử dụng chuỗi C làm công cụ chọn?

SEL normalSEL = @selector(addObject:); 
SEL cStringSEL = (SEL) "addObject:"; 

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", nil]; 

[arr performSelector:normalSEL withObject:@"3"]; 
[arr performSelector:cStringSEL withObject:@"4"]; 

NSLog(@"%@", arr); 

Theo như tôi có thể biết, nội dung của bộ chọn giống nhau, vậy tại sao tai nạn trên hộp chọn thứ hai có thông báo lỗi sau?

*** Chấm dứt ứng dụng do ngoại lệ còn tự do 'NSInvalidArgumentException', lý do: '- [__ NSArrayM AddObject:]: chọn không được công nhận gửi đến dụ 0x101918720' ***

+3

Lưu ý rằng bạn có thể sử dụng 'sel_registerName()' để biến một chuỗi C thành một SEL may mắn (về cơ bản chỉ đơn giản là chuỗi đằng sau hậu trường để bảo tồn danh tính con trỏ tiếp theo). Cũng lưu ý rằng bạn không nên trực tiếp dựa vào SEL là 'char *'. Nó có lẽ sẽ luôn luôn, nhưng điều đó không làm cho giả định chính xác. – bbum

Trả lời

22

Selectors đang thực tập nội trú chuỗi C và so với địa chỉ của họ, không phải nội dung của họ. Nội dung chuỗi chỉ được sử dụng để chuyển đổi thành/từ một biểu diễn chuỗi bên ngoài. Interning được thực hiện để cải thiện hiệu năng - khi thời gian chạy tìm kiếm phương thức thực hiện phù hợp với bộ chọn, nó có thể so sánh trực tiếp các con trỏ chọn thay vì dereferencing mỗi con trỏ và so sánh các ký tự.

+0

Hmm ... sau khi nhìn vào '__sel_registerName' Tôi tin rằng bạn là chính xác. Tuy nhiên, tôi tự hỏi có bao nhiêu sự khác biệt hiệu suất thực sự sẽ là ... –

+0

Điều này cũng ngụ ý mạnh mẽ bởi API chuỗi/selector; xem tài liệu cho ['NSSelectorFromString()'] (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/doc/ uid/20000055-BCIEICGB) và kết nối của nó với 'sel_registerName()'. –

+13

objc_msgGửi cho chạy trong khoảng 8 chu kỳ những ngày này. Không có nhiều chỗ cho một strcmp() trong đó;) –

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