Кажется, не может вызвать NSInvocationOperation с NSArray

Я пытаюсь загрузить изображение в фоновом режиме из 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 ответ

Решение

Я думаю, вы не сохраняете свою очередь. Вот что происходит

  1. Ваш массив (автоматически выпущенный) переходит в NSInvocationOperation и это сохраняется (нет проблем)
  2. Ваш NSInvocationOperation идет в очередь (сохраняется) и затем освобождается. Здесь нет проблем, так как количество сохранений равно 1: (alloc) + 1 (retain) - 1 (release) = 1 = не освобожден.
  3. Ваша очередь выделена (new знак равно alloc+init) и затем автоматически выпущен, но он не сохраняется в другом месте. Здесь возникает проблема: поскольку вы автоматически освободили очередь, после того, как метод LoadBackgroundImage Закончено, что очередь имеет счет сохранения 0 и автоматически освобождается, поэтому ваш вызов не будет выполнен.

Вы можете попробовать, если это проблема, просто удалив autorelease звонок из очереди. Если я прав, ваш код должен работать. Но знайте, что это не очень хорошее решение, потому что вы теряете память. Просто посмотреть, работает ли это.

Вы должны определенно создать класс, синглтон, переменную экземпляра или что угодно, чтобы сохранить этот экземпляр очереди. Кроме того, это хорошая идея, чтобы иметь только одну очередь для всех LoadBackgroundImage звонки вместо создания новой очереди каждый раз.

Другие вопросы по тегам