2009-10-18 28 views
5

Hãy nói rằng tôi có một phương pháp có chữ ký này:Làm thế nào để sử dụng performSelector: withObject: afterDelay: trên một phương pháp với nhiều đối số

-(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled; 

Làm thế nào để có được điều đó UIColorBOOL trong đó là cũng như Đa giác?

Tôi có nên bọc chúng trong một NSArray và kéo chúng ra bên trong phương pháp được gọi không? Điều đó có nghĩa là tôi phải thay đổi phương thức sig, đúng không?

Có cách nào thanh lịch hơn để làm điều đó không?

+0

Chúng ta có nên giả định từ UIColor rằng bạn đang sử dụng iPhone không? – nall

+0

Tôi. Điều đó làm cho một sự khác biệt? – willc2

+1

Có - nếu bạn đang sử dụng Snow Leopard, bạn có thể sử dụng một khối để giải quyết vấn đề này. – bbum

Trả lời

7

Tôi đã trả lời câu hỏi tương tự cách đây vài tuần. Trả lời dưới đây đã chỉnh sửa cho câu hỏi này.

Nói chung, tôi tránh NSInvocation cho loại công việc này. Nó có xu hướng là một nhức đầu bảo trì và, đặc biệt, tạo ra khó khăn trong tái cấu trúc trong tương lai.

Đầu tiên, được đưa ra phương pháp này:

-(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled; 

Nó sẽ thường được khai báo là:

-(void)plotPoly:(Polygon *)aPoly color:(UIColor *)aColor filled:(BOOL)filledFlag; 

này theo quy ước đặt tên một chút chặt chẽ hơn.

Bây giờ, những gì tôi sẽ làm là thực sự nắm bắt các đối số thành một lớp đơn giản cung cấp phương thức -invoke.

Something với một giao diện như thế này:

PolyPlotter.h:

@interface PolyPlotter : NSObject 
{ 
    Polygon *poly; 
    UIColor *color; 
    BOOL filled; 
} 

+ plotterWithPoly: (Polygon *) aPoly color: (UIColor *) aColor filled: (BOOL) filledFlag; 

- (void) plot; 
@end 

PolyPlotter.m:

@interface PolyPlotter() 
@property Polygon *poly; 
@property UIColor *color; 
@property BOOL filled; 
@end 

@implementation PolyPlotter 
@synthesize poly, color, filled; 

+ plotterWithPoly: (Polygon *) aPoly color: (UIColor *) aColor filled: (BOOL) filledFlag; 
{ 
    PolyPlotter *polygonPlotter = [PolyPlotter new]; 
    polygonPlotter.poly = aPoly; 
    polygonPlotter.color = aColor; 
    polygonPlotter.filled = filledFlag; 
    return [polygonPlotter autorelease]; 
} 

- (void) plot; 
{ 
    // ... do your plotting here ... 
} 
@end 

Cách sử dụng rất đơn giản. Chỉ cần tạo một thể hiện của PolygonPlotter và yêu cầu nó thực hiện bộ chọn plot sau khi trì hoãn hoặc trên sợi chính hoặc bất kỳ thứ gì.

Với câu hỏi, tôi nghi ngờ rằng bạn có thể cần thêm một chút ngữ cảnh tại thời điểm vẽ? Nếu vậy, bạn có thể chuyển thông tin đó như là một cuộc tranh cãi để -plot bởi, nói, tuyên bố phương pháp như:

- (void) plot: (UIView *) aViewToPlotIn; 

Hoặc một cái gì đó như thế.

Như tôi đã nói, mã hơi hơn, nhưng linh hoạt hơn và có thể tái cấu trúc hơn so với mẫu NSInvocation. Ví dụ, bạn có thể dễ dàng làm cho một cái gì đó PolygonPlotter có thể được lưu trữ.

0

Tôi tin rằng NSArray là một giải pháp hợp lý, và có nghĩa là thay đổi chữ ký phương thức để lấy NSArray * làm đối số duy nhất của nó.

4

thư viện three20 Joe Hewitt có một số phiên bản tiên tiến của performSelector mà bạn có thể thấy hữu ích (tôi chỉ đăng một đoạn):

- (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3 { 
    NSMethodSignature *sig = [self methodSignatureForSelector:selector]; 
    if (sig) { 
    NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig]; 
    [invo setTarget:self]; 
    [invo setSelector:selector]; 
    [invo setArgument:&p1 atIndex:2]; 
    [invo setArgument:&p2 atIndex:3]; 
    [invo setArgument:&p3 atIndex:4]; 
    [invo invoke]; 
    if (sig.methodReturnLength) { 
     id anObject; 
     [invo getReturnValue:&anObject]; 
     return anObject; 
    } else { 
     return nil; 
    } 
    } else { 
    return nil; 
    } 
} 

Chỉ cần thêm chúng vào một loại của NSObject.

+0

Làm cách nào để triển khai hàm afterDelay:? – willc2

9

Vẫn không chính xác những gì tôi sẽ gọi tao nhã, nhưng ít yuck vì phải thay đổi toàn bộ API là NSInvocation:

Polygon *poly; 
UIColor *color; 
BOOL filled; 
// Assume the above variables exist 
NSInvocation *inv = [NSInvocation invocationWithMessageSignature:[target messageSignatureForSelector:message]]; 
[inv setArgument:&poly atIndex:2]; 
[inv setArgument:&color atIndex:3]; 
[inv setArgument:&filled atIndex:4]; 
[inv performSelector:@selector(invokeWithTarget:) withObject:target afterDelay:1]; 

Các lựa chọn tốt nhất khác chỉ là để tạo ra một phương pháp wrapper mà gọi phương thức ban đầu bạn muốn với các đối số thích hợp (có thể được đưa ra như một từ điển hoặc mảng), phù hợp với chữ ký cần thiết để thực hiện sau một sự chậm trễ.

+1

Tại sao chỉ số đối số bắt đầu ở mức 3 và không phải 2 (như các tài liệu dường như chỉ ra)? – willc2

+0

Nó sẽ bắt đầu ở 2, không 3. –

+0

Nó bắt đầu tại 2. Đối số 0 và 1 được dành riêng cho các tham số 'self' và' _cmd' ẩn. –

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