我正在运行一个参数列表,但在这些参数中,值可以是NSInteger,Selector到NSObjects。但如果是NSObject,则需要妥善保留。我不能简单地检查该类是否与NSObject相同,或者它是否响应了retain方法,因为如果你在选择器或整数上执行它,它将简单地崩溃。那么你怎么能这样做呢?我不知道。
我甚至尝试将@try @catch放入其中,尝试保留,如果不是,它可能是一个不需要保留的对象。但它也立即崩溃了:(这里没有错误异常。
如果我只能测试某个参数是否有类,如果找到一个类,我可以检查它是否为NSObject类,如果没有找到类,则不应该保留它。我找到了:
object_getClass();
但是当你在其中传递NSInteger时它会崩溃。
查看NSInvocation类,您可以调用retainArguments方法,不幸的是,这也会使应用程序崩溃。但是在setArgument的描述中有一些奇怪的东西:
当参数值是对象时,将指针传递给应从中复制对象的变量(或内存)
这意味着有一些“东西”可以检测出一个参数是一个对象,但是如何?
代码(到现在为止)
- (void)addObserver:(NSObject *)observer selector:(SEL)selector arguments:(id)firstObj, ... {
// Define signature
NSMethodSignature *signature = [[observer class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
// Prepare invocation
[invocation setTarget:observer];
[invocation setSelector:selector];
id currentObject;
va_list argumentsList;
NSInteger currentIndex = 2;
if (firstObj) {
va_start (argumentsList, firstObj);
while (currentObject = va_arg(argumentsList, id)) {
[invocation setArgument:¤tObject atIndex:currentIndex];
currentIndex++;
}
va_end(argumentsList);
}
// The observer can easily be retained by doing [observer retain];
// However the arguments may consist of NSIntegers etc. which really don't like
// to be retained (logically). So I want to skip the argument that don't need
// retaining.
}
目标
我想要完成的是以下内容:
我有一个随机方法,如:
- (void)fetchFruitApples:(NSInteger)amount inRange:(NSRange)range withString:(NSString *)aString {
//Can I fetch fruit?
//If so, execute method.
//If not wait for a certain event to occur (without blocking the main thread)
//Then retry this method with the arguments passed.
//Thats why here I want to do [MyObject addObserver:self selector:@selector(fetchFruitApples:inRange:withString:) arguments:amount, range, aString, nil];
}
答案 0 :(得分:0)
如何将您的数字作为NSNumber对象传递,这样您就可以确保获得的所有内容都是一个对象,并会响应[arg retain]
和[arg isKindOfClass:[NSNumber class]]
我肯定不知道这一点,但我会做出有根据的猜测,没有办法做到这一点。您可以在int和对象之间进行区分,但是要指出指向选择器的指针和指向对象的指针?值得怀疑的。
答案 1 :(得分:0)
你声明的目标让我觉得你应该探索NSOperationQueue。
“这让我接下来讨论NSOperation依赖项.NSThread目前还没有用于添加依赖项的内置机制。但是NSOperation有 - (void)addDependency:(NSOperation *)操作方法,它允许一个简单的机制(当与NSOperationQueue一起使用时)用于依赖管理。所以我们进入NSOperationQueue ......“
来自http://cocoasamurai.blogspot.com/2008/04/guide-to-threading-on-leopard.html
答案 2 :(得分:0)
您最好的选择可能只是使用格式字符串,就像使用[NSString stringWithFormat:]
一样。调用者总是知道正确的类型,那么为什么不让它传递信息呢?
例如,如果您将方法签名更改为:
- (void)addObserver:(NSObject *)observer selector:(SEL)selector argumentFormat:(NSString*)format arguments:(id)firstObj, ... {
// parse format
}
format
类似于:isS
并且意味着第一个参数是一个整数,第二个是字符串,第三个是选择器(即保留第二个参数但不保留另一个二)。
答案 3 :(得分:0)
可能是最简单的解决方案:
[myInvocation setRetainArguments:YES];
这将告诉调用实例保留您设置的任何对象参数。所以从你的角度来看,根本就没有工作。
如果您需要手动执行,那么您应该查看方法-[NSMethodSignature getArgumentTypeAtIndex:]
。它将返回char *
,其编码类型与@encode()
使用的格式相同。可以这样使用:
char* type = [myMethodSignature getArgumentTypeAtIndex:3];
if (strcmp(type, @encode(id)) == 0) {
// It is an object!
}
最后,我已经完成了您可能需要的工作,您可以轻松创建NSInvocation
个实例,以使用单个语句调用任何类型的参数。在后台/主线程,延迟和操作队列上都有。
我已就该主题发表过博文,完整的源代码可从此处获取:http://blog.jayway.com/2010/03/30/performing-any-selector-on-the-main-thread/
以及更多:http://blog.jayway.com/2010/08/19/future-cocoa-operation/
答案 4 :(得分:0)
最后解决方案
经过艰难的一天,希望发现看起来不可能的事情,我终于有了解决方案,特别感谢PeyloW指出我正确的方向。阅读他的博客: http://blog.jayway.com/2010/03/30/performing-any-selector-on-the-main-thread/
关键是:
const char *type = [signature getArgumentTypeAtIndex:index];
NSString *dataType = [[[NSString alloc] initWithCString:type] autorelease];
if ([dataType isEqualToString:@"@"]) // The argument is an object!