2012-09-20 13 views
2

我想从一个url的背景加载图像。如果我通过的是NSUrl,代码就很好用。如果我试图通过一个额外的变量NSArray,它永远不会被调用:似乎无法与一个NSArray调用NSInvocationOperation

这段代码很好用,调用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

我的猜测是你不保留你的队列。这里是发生了什么

  1. 你的阵列(自动释放)进入NSInvocationOperation和它被保留(没问题)
  2. NSInvocationOperation进入队列(保留),然后它的释放。这里没有问题,因为保留计数仍然是1:1(alloc)+1(retain)-1(release)= 1 =未处理。
  3. 您的队列已被分配(new = alloc + init),然后自动发布,但未在其他地方保留。问题来了:由于您已经自动释放队列,一旦方法LoadBackgroundImage完成,队列的保留计数为0并且它会自动释放,因此您的调用将不会执行。

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

你绝对应该创建一个类,一个单例,一个实例变量或任何你喜欢的东西来保留这个队列的实例。另外,对于所有的LoadBackgroundImage调用,只有一个队列是一个好主意,而不是每次都创建一个新的队列。