2009-07-12 10 views
6

Mục tiêu-C sử dụng hệ thống truyền thông phức tạp khi một đối tượng gọi một phương thức trên đối tượng khác. Tôi muốn biết nếu nó có thể, trong phương pháp được gọi, để xác định những gì các đối tượng gọi là?Có thể sử dụng các tính năng thời gian chạy Objective-C để xác định một phương thức được gọi từ đâu không?

Ví dụ:

@implementation callingClass 
- (void)performTest 
{ 
    calledObject = [[[calledClass alloc] init] autorelease]; 
    id result = [calledObject calledMethod]; 

    assert(result == this); 
} 
@end 

@implementation calledClass 
- (id)calledMethod 
{ 
    id objectThatCalledThisMethod = ... // <-- what goes here? 

    return objectThatCalledThisMethod; 
} 
@end 

Những gì tôi có thể viết trong dòng nhận xét để làm cho đèo khẳng định khi tôi thực hiện performTest?

Trả lời

11

Không có thời gian chạy. Tất cả các tin nhắn gửi cuối cùng làm việc ra một cuộc gọi chức năng dọc theo các dòng objc_msgSend(id receiver, SEL selector, /*method arguments*/...). Như bạn thấy, không có thông tin nào được truyền về đối tượng gửi tin nhắn. Có lẽ nó có thể xác định đối tượng gọi bằng cách đi bộ ngăn xếp, nhưng cách đó nằm điên khùng. Cách thực tế duy nhất để biết ai được gọi là phương pháp là để cho nó một đối số sender giống như tất cả các phương pháp IBAction có.

2

Không, bạn không thể xác định đối tượng nào được gọi là bạn. Vâng, về mặt kỹ thuật, nó có thể có thể poke xung quanh theo dõi ngăn xếp trở lại, nhưng chắc chắn nó không thực tế cho mã thực.

Nếu bạn nhìn vào hầu hết các phương pháp đại biểu, bạn có thể thấy rằng các định dạng cuộc gọi đại biểu tiêu chuẩn giống như thế này:

- (NSSize) windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; 
- (BOOL) windowShouldClose:(id)window; 
- (void) windowWillMove:(NSNotification *)notification; 

Lưu ý cách cửa sổ (gọi) được thông qua như là đối số đầu tiên, và làm thế nào "cửa sổ" là phần đầu tiên của tên phương thức. Trong trường hợp cuối cùng, người gọi cửa sổ tiềm ẩn trong NSNotification (notification.object là cửa sổ).

2

Bạn có thể thử và lấy được lớp học của riêng mình từ NSInvocation mang thông tin người gọi. Hoặc quấn một lớp xung quanh NSInvocation reimplementing một số các cuộc gọi trong đó.

+0

NSInvocation cũng không có bất cứ điều gì về người gọi - chỉ cần mục tiêu, chọn, và tranh luận. –

+0

Đó là lý do tại sao tôi đề xuất phát sinh một lớp mới hoặc gói nó xung quanh, điều này ít nhất có thể cung cấp cho bạn một cách nhất quán để chuyển người gửi vào hàm gọi hoặc có thể xây dựng cấu trúc dữ liệu nơi thông tin có thể được lấy từ đầu người nhận. Nó phụ thuộc vào những gì anh ta đang cố gắng hoàn thành –

4

Tôi hy vọng rằng điều này sẽ giúp:

NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1]; 
    // Example: 1 UIKit        0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163 
    NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"]; 
    NSMutableArray *array = [NSMutableArray arrayWithArray:[origen componentsSeparatedByCharactersInSet:separatorSet]]; 
    [array removeObject:@""]; 

    NSLog(@"Pila = %@", [array objectAtIndex:0]); 
    NSLog(@"Framework = %@", [array objectAtIndex:1]); 
    NSLog(@"Memory address = %@", [array objectAtIndex:2]); 
    NSLog(@"Class caller = %@", [array objectAtIndex:3]); 
    NSLog(@"Function caller = %@", [array objectAtIndex:4]); 
    NSLog(@"Line caller = %@", [array objectAtIndex:5]);