NSInvocationOperation使用params定义选择器

时间:2011-01-24 22:46:54

标签: objective-c ios selector nsinvocation function-declaration

我正在尝试创建NSInvocationOperation,以便它应该使用params调用object的方法

- (void) getImages: (NSRange) bounds
{
    NSOperationQueue *queue = [NSOperationQueue new];
    NSArray * params = [NSArray arrayWithObjects:
          [[NSNumber alloc] initWithInt: bounds.location],
          [[NSNumber alloc] initWithInt: bounds.length]];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                   selector:@selector(loadImagesWithOperation)
                     object:params];

    [queue addOperation:operation];
    [operation release];

}

- (void) loadImagesWithOperation:(NSArray*)bounds {
 NSLog(@"loadImagesWithOperation");
}

此代码与EXC_BAD_ACCESS崩溃。如果我改变要调用的函数的定义

- (void) loadImagesWithOperation {
 NSLog(@"loadImagesWithOperation");
}
一切都变好了。我试图在 @selector 的代码块中使用不同的语法,如 @selector(loadImagesWithOperation :) @selector(loadImagesWithOperation:bounds :) ,但没有成功。

用params定义选择器和函数的正确方法是什么?

感谢。

2 个答案:

答案 0 :(得分:5)

定义带参数的SEL的正确方法是为每个参数使用冒号(":")字符,因此在您的情况下,选择器将如下所示:

@selector(loadImagesWithOperation:)

因此,您的NSInvocationOperation对象应该像这样初始化:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
               selector:@selector(loadImagesWithOperation:)
                 object:params];

哦,就像旁注一样,NSArraygetImages:的初始化存在内存泄漏:

NSArray * params = [NSArray arrayWithObjects:
      [[NSNumber alloc] initWithInt: bounds.location],
      [[NSNumber alloc] initWithInt: bounds.length]];

这会添加已retainCount 1 +alloc的对象,因为您使用的是NSArray,因此当它们添加到-retain时,会发送{ {1}}消息,从而将retainCount增加到2

取消分配此NSArray后,这些对象将不会被取消分配,因为他们的retainCount将是1,而不是0

这个问题有三种解决方案:

  1. 在将autorelease消息添加到NSArray之前,将NSNumber消息发送给每个对象。
  2. 使用numberWithInt:的{​​{1}}类方法获取自动释放的NSNumber对象。
  3. 创建对这些NSNumber个对象的引用,将其添加到NSArray,然后添加后,向其发送-release消息。

答案 1 :(得分:3)

  一切都变好了。我试过了   在@ selector中使用不同的语法   代码块就好   @选择(loadImagesWithOperation :)   和   @selector(loadImagesWithOperation:边界:)   但没有成功。

initWithTarget:selector:object:采用一个可以接受0或1个参数的选择器,不再是(不是2个)。那一个论点必须是一个对象。如果你需要更多的参数,可以使用块或重构你的代码(传递一个包含其余对象的数组是一个潜在的解决方案,是的 - 有点像你在那段代码中所做的那样(尽管注意内存泄漏)。 / p>

崩溃与您显示的代码无关。发布崩溃。

另请注意,在头部具有get的方法在Cocoa / iOS中具有非常特定的含义,并且不用于此类模式。我建议loadImages