NSInvocationOperation使用params定义选择器

dug*_*ets 2 objective-c selector nsinvocation function-declaration ios

我正在尝试创建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");
}
Run Code Online (Sandbox Code Playgroud)

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

- (void) loadImagesWithOperation {
 NSLog(@"loadImagesWithOperation");
}
Run Code Online (Sandbox Code Playgroud)

一切都变好了.我试图在@selector的代码块中使用不同的语法,如@selector(loadImagesWithOperation :)@selector(loadImagesWithOperation:bounds :),但没有成功.

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

谢谢.

Jac*_*kin 5

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

@selector(loadImagesWithOperation:)
Run Code Online (Sandbox Code Playgroud)

所以,你的NSInvocationOperation对象应该像这样初始化:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
               selector:@selector(loadImagesWithOperation:)
                 object:params];
Run Code Online (Sandbox Code Playgroud)

哦,就像一个侧面说明,你有你的初始化内存泄漏NSArraygetImages::

NSArray * params = [NSArray arrayWithObjects:
      [[NSNumber alloc] initWithInt: bounds.location],
      [[NSNumber alloc] initWithInt: bounds.length]];
Run Code Online (Sandbox Code Playgroud)

这增加了已经有对象retainCount1,因为你使用的+alloc,因此,当他们被添加到NSArray,他们得到发送的-retain消息,从而增加了retainCount2.

当这NSArray被解除分配时,这些对象将不会被释放,因为它们retainCount将是1,而不是0.

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

  1. autorelease将这些对象添加到之前将其发送到每个对象NSArray.
  2. 使用NSNumber's numberWithInt:class方法获取自动释放的NSNumber对象.
  3. 创建对这些NSNumber对象的引用,将它们添加到NSArray,然后添加,向它们发送-release消息.