代码之家  ›  专栏  ›  技术社区  ›  Nitzan Wilnai

似乎无法使用NSArray调用NSInvocationOperation

  •  2
  • Nitzan Wilnai  · 技术社区  · 12 年前

    我正在尝试从url加载背景中的图像。如果我传递的只是NSUrl,那么代码就非常有效。如果我试图传递一个带有附加变量的NSArray,它永远不会被调用:

    这段代码运行得很好,调用了LoadImage2,这反过来又很好地调用了ImageLoaded2。

    - (void)LoadBackgroundImage2: (char*)pImageURL
    {
    
        NSString* pImageURLString = [NSString stringWithFormat:@"%s", pImageURL];
    
        NSLog( @"LoadBackgroundImage2: %@", pImageURLString );
    
        NSOperationQueue *queue = [NSOperationQueue new];
        NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                        initWithTarget:self
                                        selector:@selector(LoadImage2:)
                                        object:pImageURLString];
        [queue addOperation:operation];
        [operation release];
    }
    
    
    - (void)LoadImage2: (NSString*)pImageURL
    {
        NSLog( @"LoadImage2: %@", pImageURL );
    
        NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:pImageURL]];
        UIImage* image = [[[UIImage alloc] initWithData:imageData] autorelease];
        [imageData release];
        [self performSelectorOnMainThread:@selector(ImageLoaded2:) withObject:image waitUntilDone:NO];
    }
    

    此代码不起作用。LoadImage从未被调用:

    - (void)LoadBackgroundImage: (char*)pImageURL :(int)textureID :(int)textureType
    {
    
        printf( "LoadBackgroundImage( %s, %d, %d)\n", pImageURL, textureID, textureType );
    
        NSString* pImageURLString = [NSString stringWithFormat:@"%s", pImageURL];
    
        NSArray* pUrlAndReferences = [[[NSArray alloc] initWithObjects: pImageURLString, textureID, textureType, nil] autorelease];
    
        NSOperationQueue *queue = [[NSOperationQueue new] autorelease];
        NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                        initWithTarget:self
                                        selector:@selector(LoadImage:)
                                        object:pUrlAndReferences];
    
        [queue addOperation:operation];
        [operation release];
    }
    
    
    - (void)LoadImage: (NSArray*)pUrlAndReferences
    {
        NSString* pImageUrl = [pUrlAndReferences objectAtIndex: 0];
        int textureId = [ [ pUrlAndReferences objectAtIndex: 1 ] intValue ];
        int textureType = [ [ pUrlAndReferences objectAtIndex: 2 ] intValue ];
    
        NSLog( @"\n\nLoadImage: %@, %d, %d\n", pImageUrl, textureId, textureType );
    
        NSData* pImageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:pImageUrl]];
        UIImage* pImage = [[[UIImage alloc] initWithData:pImageData] autorelease];
    
        NSArray* pImageAndReferences = [[[NSArray alloc] initWithObjects: pImage, textureId, textureType, nil] autorelease];
    
        [pImageData release];
        [self performSelectorOnMainThread:@selector(ImageLoaded:) withObject:pImageAndReferences waitUntilDone:NO];
    }
    

    有人知道为什么LoadImage没有被调用吗?

    谢谢

    1 回复  |  直到 12 年前
        1
  •  1
  •   txulu    12 年前

    我的猜测是你没有排队。下面是发生的事情

    1. 你的数组(自动释放)进入 NSInvocationOperation 它被保留了下来(没问题)
    2. 你的 NS定位操作 进入队列(保留),然后释放。这里没有问题,因为保留计数仍然是一:1( alloc )+1( retain )-1个( release )=1=未解除锁定。
    3. 您的队列已分配( new = 分配 + init )然后自动释放,但它不会在其他地方保留。问题来了:由于您已经自动释放了队列,一旦方法 LoadBackgroundImage 完成后,队列的保留计数为0,并且会自动释放,因此,不会执行Invocation。

    如果这是问题所在,您可以尝试删除 autorelease 从队列中调用。如果我是正确的,你的代码应该可以工作。但要注意,这不是一个好的解决方案,因为你正在失去记忆。只是看看它是否有效。

    您肯定应该创建一个类、一个singleton、一个实例变量或任何您喜欢的东西来保留队列的那个实例。此外,对于所有的 加载背景图像 调用,而不是每次都创建一个新队列。