假设我有一个具有以下签名的方法:
-(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled;
我应该如何将 UIColor 和 BOOL 以及 Polygon 放进去呢?
我应该将它们包装在 NSArray 中,在调用的方法内部取出来吗?这意味着我需要改变方法的签名,对吗?
有更简洁的方法吗?
假设我有一个具有以下签名的方法:
-(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled;
我应该如何将 UIColor 和 BOOL 以及 Polygon 放进去呢?
我应该将它们包装在 NSArray 中,在调用的方法内部取出来吗?这意味着我需要改变方法的签名,对吗?
有更简洁的方法吗?
虽然还不算优雅,但比改变整个API要好一些的方法是使用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];
几周前,我回答了一个相似的问题。下面是为这个问题编辑过的答案。
通常情况下,我避免使用NSInvocation
来完成这种工作。它往往会成为维护上的头痛,并且特别地,在未来重构时会带来困难。
首先,考虑以下这个方法:
-(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled;
通常会声明为:
-(void)plotPoly:(Polygon *)aPoly color:(UIColor *)aColor filled:(BOOL)filledFlag;
这个更贴近命名惯例。
现在,我会将参数捕获到一个简单的类中,该类提供一个 -invoke
方法。
接口如下:
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
使用方法很简单。只需创建一个PolygonPlotter实例,并告诉它在延迟后或主线程上执行选择器plot
即可。
考虑到问题,我怀疑您在绘图时可能需要更多的上下文信息?如果是这样,您可以将该信息作为参数传递给-plot
,例如声明该方法:
- (void) plot: (UIView *) aViewToPlotIn;
或者类似这样。
像我说的那样,代码稍微多一些,但比NSInvocation模式更灵活、易于重构。例如,你可以很容易地将PolygonPlotter设置为可存档的。
Joe Hewitt的Three20库有一些高级版本的performSelector方法,你可能会发现它们很有用(我只发布了一个片段):
- (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;
}
}
NSObject
类别中即可。我认为NSArray是一个合理的解决方案,是的,这意味着改变方法签名以接受一个NSArray*作为其唯一参数。