Je suis codage ObjC (de comptage de référence manuel) et a trouvé un comportement étrange qui empêche UITableView et UITableViewCells de se libéré, bien que ma gestion de la mémoire est correcte. UITableView et UITableViewCell semblent se conserver mutuellement. Et oui, j'ai trouvé un moyen de forcer l'UITableView et ses cellules à se libérer l'une l'autre (supprimer les cellules mises en cache). Pour ce faire, vous demandez essentiellement une vue de table pour une cellule réutilisable. La vue de table le supprimera de son cache de cellules réutilisable. Après tout, vous dites à cette cellule de supprimer de son aperçu. Terminé.
Maintenant, en tant que classe autonome ... Tout d'abord, vous avez besoin d'un tableau de tous les identifiants de cellules que vous avez utilisés. Ensuite, vous implémentez une source de données factices et laissez cette source de données effacer le UITableView par lui-même rechargeant avec les « ClearAllCachedCells » Source de données:
#import <UIKit/UIKit.h>
@interface ClearAllCachedUITableViewCellsDataSource : NSObject <UITableViewDataSource, UITableViewDelegate>
+(void)clearTableView:(UITableView*)tv
reuseIdentifiers:(NSArray<NSString*>*)cellIdentifiers
delegateAfterFinish:(id<UITableViewDelegate>)dg
dataSourceAfterFinish:(id<UITableViewDataSource>)ds;
@end
Et la magie se produit dans le fichier .m:
#import "ClearAllCachedUITableViewCellsDataSource.h"
@interface ClearAllCachedUITableViewCellsDataSource() {
BOOL clearing;
}
@property (nonatomic, readonly) UITableView *tv;
@property (nonatomic, readonly) NSArray<NSString*> *identifiers;
@property (nonatomic, readonly) id ds;
@property (nonatomic, readonly) id dg;
@end
@implementation ClearAllCachedUITableViewCellsDataSource
-(void)dealloc {
NSLog(@"ClearAllCachedUITableViewCellsDataSource (%i) finished", (int)_tv);
[_tv release];
[_ds release];
[_dg release];
[_identifiers release];
[super dealloc];
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
[self performSelectorOnMainThread:@selector(clear) withObject:nil waitUntilDone:NO];
NSLog(@"TV (%i): reloading with zero cells", (int)_tv);
return 0;
}
-(void)clear {
if (!clearing) {
clearing = YES;
for (NSString *ident in self.identifiers) {
UITableViewCell *cell = [_tv dequeueReusableCellWithIdentifier:ident];
while (cell) {
NSLog(@"TV (%i): removing cached cell %@/%i", (int)_tv, ident, (int)cell);
[cell removeFromSuperview];
cell = [_tv dequeueReusableCellWithIdentifier:ident];
}
}
self.tv.delegate = self.tv.delegate == self ? self.dg : self.tv.delegate;
self.tv.dataSource = self.tv.dataSource == self ? self.ds : self.tv.dataSource;
[self release];
}
}
+(void)clearTableView:(UITableView*)tv
reuseIdentifiers:(NSArray<NSString*>*)cellIdentifiers
delegateAfterFinish:(id<UITableViewDelegate>)dg
dataSourceAfterFinish:(id<UITableViewDataSource>)ds {
if (tv && cellIdentifiers) {
NSLog(@"TV (%i): adding request to clear table view", (int)tv);
ClearAllCachedUITableViewCellsDataSource *cds = [ClearAllCachedUITableViewCellsDataSource new];
cds->_identifiers = [cellIdentifiers retain];
cds->_dg = [dg retain];
cds->_ds = [ds retain];
cds->_tv = [tv retain];
cds->clearing = NO;
tv.dataSource = cds;
tv.delegate = cds;
[tv performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
@end
OK merci. J'espérais trouver un moyen d'invalider toute la cache d'un seul coup. Cependant, cette solution (effacez manuellement les données pour invalider le cache et faire l'invalidation, une ligne à la fois) devrait aussi fonctionner –
Je ne pense pas que vous compreniez la réponse de Giao. Il n'a rien suggéré du tout pour toi. La méthode 'prepareForReuse:' est envoyée à chaque cellule lorsqu'elle est supprimée, avant qu'elle ne vous soit remise. C'est quelque chose qui se passe automatiquement, et vous vous en souciez seulement si vous implémentez votre propre sous-classe de UITableViewCell. –