J'ai une méthode dans un UIViewController de mon application iPhone (à l'intérieur d'un UINavigationController) qui est appelée chaque fois qu'une ligne est sélectionnée dans la table dans la vue de ViewController. Dans cette méthode, j'accède au tableau de "Dream" stocké dans un champ d'instance dreamsArray, qui contient NSManagedObjects de ma base de données. Je peux accéder aux objets de ce tableau dans d'autres méthodes, mais il semble que chaque fois que j'essaie de récupérer ou de modifier des objets récupérés à partir de ce tableau dans cette méthode particulière, le programme se bloque.L'application se bloque lors de l'accès à NSManagedObjects dans une certaine méthode
Voici comment dreamsArray est créé:
dreamsArray = [[NSMutableArray alloc] init];
[self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Dream" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release]; [sortDescriptor release];
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil)
NSLog(@"oh noes! no fetch results DreamsTabController:45");
dreamsArray = [mutableFetchResults mutableCopy];
[mutableFetchResults release];
[request release];
Une instance dans laquelle l'interrogation dreamsArray et ses objets fonctionne:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID] autorelease];
Dream *dream = (Dream *)[dreamsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [dream title];
cell.detailTextLabel.text = @"foo!";
[dream release];
return cell;
}
Et la méthode qui a tous les problèmes:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Dream *dream = (Dream *)[dreamsArray objectAtIndex:indexPath.row];
// BOOM - crashes right here
EditDreamController *edit = [[EditDreamController alloc] initWithNibName:@"EditDream" bundle:nil];
edit.dream = [[NSArray alloc] initWithObjects:dream.dreamContent, nil];
[navigationController pushViewController:edit animated:YES];
[dream release];
[edit release];
}
L'application se bloque immédiatement après l'appel de dreamsArray.
Même l'appel d'un NSLog(@"%@", dream.title)
simple dans cette méthode provoque un blocage. Qu'est-ce qui pourrait mal tourner ici?
Point secondaire: J'utiliserais personnellement [[fetchResults mutableCopy] autorelease] plutôt que [NSMutableArray arrayWithArray: fetchResults] car, en théorie, fetchResults pourrait avoir une méthode mutableCopy optimisée (à l'avenir, même si ce n'est pas le cas actuellement). –
Je n'utilise jamais -mutableCopy, car je ne lui fais pas confiance. Une raison est que je ne peux presque jamais me rappeler si 'mutableCopy' est profond ou pas (et ne devrait pas l'être), et si * I * ne me souviens pas, comment puis-je m'attendre à ce que d'autres personnes lisent mon code? Un autre est parce que s'il a été optimisé de cette manière, l'utiliser pour sécuriser l'énumération rapide (parce que je modifie le tableau de base) serait encore dangereux. En outre, si le tableau de base était une sous-classe de NSArray foutue, maintenant je sais que c'est juste un normal. –
L'argument selon lequel vous ne pouvez pas vous souvenir si c'est une copie profonde est faible, car vous pouvez en dire autant de arrayWithArray. Cela ne veut rien enlever à votre point plus général: si vous ne pouvez pas facilement vous rappeler quelque chose, vous ne devriez pas le faire (par exemple, j'oublie l'ordre de priorité entre && et || et j'utilise donc des parenthèses). Personnellement, je ne pense pas que se rappeler si mutableCopy fait une copie profonde tombe dans cette catégorie; c'est quelque chose que tu devrais savoir. –