J'ai un problème déconcertant en essayant de remplir un NSMutableArray avec UIImages.
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderMask;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
while(...) // <--- Iterates through data sets
{
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, numBytes, NULL);
CGImageRef cImage = CGImageCreate(iw, ih, 8, 32, 4 * iw, colorSpace, bitmapInfo, provider, NULL, NO, renderingIntent);
UIImage *finalImage = [UIImage imageWithCGImage:cImage];
[images addObject:finalImage]; // <--- Declared and instantiated earlier
[delegate sendImage:finalImage];
CGImageRelease(cImage);
CGDataProviderRelease(provider);
}
CGColorSpaceRelease(colorSpace);
[delegate operationCompletedWithImages:images];
C'est comme ça que j'ai le code qui s'exécute. J'ai donc essentiellement une fonction exécutée dans l'instruction while qui renvoie le prochain ensemble de données bitmap, je crée ensuite une UIImage et la stocke dans le tableau mutable.
J'ai testé cela en écrivant chaque fichier sur le disque, puis en y accédant, ce qui donne le bon ensemble d'images. Le problème est que lors de l'utilisation du tableau pour conserver les données en mémoire, en accédant à n'importe quel objet image du tableau, j'obtiens exactement la même image encore et encore. L'image est aussi toujours la dernière image de l'ensemble.
J'ai essayé de tester le contenu en définissant le tableau comme un tableau d'animation UIImageView et en utilisant un NSTimer pour faire défiler le contenu. De toute façon, c'est juste la même image (la dernière image tirée) encore et encore.
J'ai cette opération en cours d'exécution dans un objet NSOperation sous-classé afin qu'elle ne bloque pas l'interface. Un autre aspect intéressant ici est que lorsque le tableau d'images envoyé avec operationCompletedWithImages me donnait le tableau d'images en double, j'ai essayé d'utiliser le message sendImage et de stocker les images dans un tableau différent à l'intérieur l'objet délégué (en pensant que c'était peut-être un problème de thread). Cela m'a donné les mêmes résultats.
Cela fait plus d'une semaine que je suis bloqué dessus sans aucun progrès. Je n'ai jamais rien vu de tel et je ne trouve personne d'autre qui a eu un problème similaire. Je serais heureux de fournir des informations supplémentaires si quelqu'un pense que cela aiderait à résoudre ce problème.
Si quelqu'un pouvait apporter de l'aide, je l'apprécierais grandement.
3 réponses
Compris le problème. S'est avéré être un problème avec le pointeur de sauvegarde data.
Là où auparavant j'accédais aux données à chaque fois en pensant qu'elles seraient itérées et écrasées avec de nouveaux contenus, et que les nouveaux contenus seraient branchés sur mon CGDataProviderRef. Ce n'était pas le cas, j'ai fini par fournir un pointeur vers les mêmes données de sauvegarde pour le fournisseur. La solution consistait à copier les données dans un objet NSData et à utiliser cette copie pour le DataProvider.
Donc au lieu de:
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, numBytes, NULL);
Ce serait:
NSData *pxData = [[NSData alloc] initWithBytes:pFrameRGB->data length:numBytes];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)pxData);
Je ne sais pas si c'est le problème, mais vous devriez probablement informer votre délégué des modifications sur le thread principal, et non sur le thread sur lequel l'opération NSO s'exécute.
[delegate performSelectorOnMainThread:@selector(sendImage:) withObject:finalImage waitUntilDone:YES];
Et de même pour le dernier message. Si le délégué modifie quoi que ce soit en rapport avec UIKit, il doit être invoqué sur le thread principal !
On pourrait supposer que le NSMutableArray gérerait la gestion de la mémoire de l'objet qui lui est ajouté, mais peut-être parce que vous avez affaire aux assistants Quartz / wrappers Core de niveau C, cela peut ne pas être le cas.
Dans d'autres méthodes de manipulation d'images que j'ai expérimentées, elles sont généralement encapsulées dans un pool de libération automatique si elles sont impliquées dans des threads.
Avez-vous essayé d'expérimenter avec release/autorelease sur l'image finale ?
Questions connexes
De nouvelles questions
objective-c
Cette balise ne doit être utilisée que sur les questions concernant les fonctionnalités d'Objective-C ou dépendant du code du langage. Les balises [cocoa] et [cocoa-touch] doivent être utilisées pour poser des questions sur les cadres ou les classes d'Apple. Utilisez les balises associées [ios], [macos], [apple-watch] et [tvos] pour les problèmes spécifiques à ces plates-formes.