我在一个有趣的小iPhone应用程序上做了很多工作。有一次,我从Persistant商店获得了一堆玩家对象,然后在屏幕上显示它们。我还可以选择添加新的播放器对象(它们只是自定义的UIButtons)并删除选定的播放器。
但是,我相信我遇到了一些内存管理问题,因为应用程序无法保存哪些“播放器”正在显示。
示例:我显示了4个玩家,我将它们全部选中然后全部删除。他们都消失了。但是如果我退出然后重新打开应用程序,它们都会再次出现。好像他们从未离开过。所以在我的代码中,它们并没有“真正”被删除。
MagicApp201AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *desc = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:context];
[request setEntity:desc];
NSError *error;
NSMutableArray *objects = [[[context executeFetchRequest:request error:&error] mutableCopy] autorelease];
if (objects == nil) {
NSLog(@"Shit man, there was an error taking out the single player object when the view did load. ", error);
}
int j = 0;
while (j < [objects count]) {
if ([[[objects objectAtIndex:j] valueForKey:@"currentMultiPlayer"] boolValue] == NO) {
[objects removeObjectAtIndex:j];
j--;
}
else {
j++;
}
}
[self setPlayers:objects]; //This is a must, it NEEDS to work Objects are all the players playing
所以在这个snippit中(在viewdidLoad方法中),我从持久性商店中抓取玩家,然后删除我不想要的对象(那些boolValue为NO的对象),其余的保留。这很有效,我很确定。我认为问题在于我删除玩家。这是代码:
NSLog(@"Remove players");
/**
For each selected player:
Unselect them (remove them from SelectedPlayers)
Remove the button from the view
Remove the button object from the array
Remove the player from Players
*/
NSLog(@"Debugging Removal: %d", [selectedPlayers count]);
for (int i=0; i < [selectedPlayers count]; i++) {
NSManagedObject *rPlayer = [selectedPlayers objectAtIndex:i];
[rPlayer setValue:[NSNumber numberWithBool:NO] forKey:@"currentMultiPlayer"];
int index = [players indexOfObjectIdenticalTo:rPlayer]; //this is the index we need
for (int j = (index + 1); j < [players count]; j++) {
UIButton *tempButton = [playerButtons objectAtIndex:j];
tempButton.tag--;
}
NSError *error;
if ([context hasChanges] && ![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
UIButton *aButton = [playerButtons objectAtIndex:index];
[players removeObjectAtIndex:index];
[aButton removeFromSuperview];
[playerButtons removeObjectAtIndex:index];
}
[selectedPlayers removeAllObjects];
NSError *error;
if ([context hasChanges] && ![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
NSLog(@"About to refresh YES");
[self refreshAllPlayers:YES];
第二个代码片段中的重要部分是我为currentMultiPlayer将它们设置为NO。 NO NO NO NO NO,当视图加载时,它们不应该回来,永远不会。直到我说出来。代码中没有其他相关部分将其设置为YES。这让我觉得......也许他们没有得救。也许这不会保存,也许这些对象不再被管理,因此它们不会被保存。是否有一个生命(隐喻)的NSManaged对象? Players数组与我在“viewDidLoad”方法中设置的相同,并且SelectedPlayers包含所选的玩家,对NSManagedObjects的引用。是否与从阵列中删除它们有关?我很困惑,一些见解会非常感激!!
答案 0 :(得分:0)
看起来您正在从各种内部数组中删除播放器对象,但不会从NSManagedObjectContext
本身删除它们。
答案 1 :(得分:0)
经过多次调试(相当多)我发现了这个问题。代码工作正常,直到你“删除”第一个玩家,或插槽0中的玩家。我看着玩家被过滤后:
while (j < [objects count]) {
if ([[[objects objectAtIndex:j] valueForKey:@"currentMultiPlayer"] boolValue] == NO) {
[objects removeObjectAtIndex:j];
j--;
}
else {
j++;
}
}
并且意识到如果第一个玩家没有玩,那么j变为-1,然后它突破循环并且无法验证其余玩家,导致奇怪的错误让他们全部回到游戏中。它根本没有与内存管理有关,但我确实修复了一些泄漏,以便找到bug。谢谢!