0

J'ai fait une classe. C'est le fichier h.Pourquoi mon application crash

// MyClass.h 
#import <Foundation/Foundation.h> 


@interface MyClass : NSObject <NSCoding> { 
    NSString *string1; 
    NSString *string2; 

} 
@property (nonatomic, retain) NSString *string1; 
@property (nonatomic, retain) NSString *string2; 

@end 

C'est le fichier m

// MyClass.m 
#import "MyClass.h" 


@implementation MyClass 
@synthesize string1, string2; 

- (void)encodeWithCoder:(NSCoder *)coder; 
{ 
    NSLog(@"encodeWithCoder"); 

     [coder encodeObject:string1 forKey:@"string1"]; 
     [coder encodeObject:string2 forKey:@"string2"]; 


} 

- (id)initWithCoder:(NSCoder *)coder; 
{ 
    NSLog(@"initWithCoder"); 
    self = [super init]; 

     self.string1 = [coder decodeObjectForKey:@"string1"]; 
     self.string2 = [coder decodeObjectForKey:@"string2"]; 


    return self; 
} 


- (void)dealloc { 

    [string1 release]; 
    [string2 release]; 
    [super dealloc]; 
} 


@end 

J'ai créé un tableau de ces objets comme celui-ci

MyClass *object1 = [[MyClass alloc] init]; 
object1.string1 = @"object1 string1"; 
object1.string2 = @"string1 string2"; 
MyClass *object2 = [[MyClass alloc] init]; 
object2.string1 = @"object2 string1"; 
object2.string2 = @"object2 string2"; 
theArray = [[NSMutableArray alloc] initWithObjects:object1, object2, nil]; 

Je sauvé le tableau comme celui-ci

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:theArray] forKey:@"savedArray"]; 

Ensuite, J'ai chargé le tableau à partir du disque comme celui-ci .

NSData *theData = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedArray"]; 
if (theData != nil) { 
    NSLog(@"found something"); 
    theArray = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]]; 
} 

Le programme se déroule normalement sans erreur jusqu'à ce qu'il soit à ce

DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 
    // ... 
    // Pass the selected object to the new view controller. 
    detailViewController.myObject = [theArray objectAtIndex:indexPath.row]; 

Il se bloque sur cette dernière ligne. Il se bloque uniquement si je charge le tableau à l'aide de NSUserDefaults, mais je ne remarque rien de ce que j'ai fait de mal avec cette partie.

Quand il se bloque c'est ce que le débogueur dit

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x5955e50' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x02395919 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x024e35de objc_exception_throw + 47 
    2 CoreFoundation      0x0239742b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 
    3 CoreFoundation      0x02307116 ___forwarding___ + 966 
    4 CoreFoundation      0x02306cd2 _CF_forwarding_prep_0 + 50 
    5 custom object array save test  0x00002872 -[RootViewController tableView:didSelectRowAtIndexPath:] + 156 
    6 UIKit        0x0032b718 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140 
    7 UIKit        0x00321ffe -[UITableView _userSelectRowAtIndexPath:] + 219 
    8 Foundation       0x00038cea __NSFireDelayedPerform + 441 
    9 CoreFoundation      0x02376d43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19 
    10 CoreFoundation      0x02378384 __CFRunLoopDoTimer + 1364 
    11 CoreFoundation      0x022d4d09 __CFRunLoopRun + 1817 
    12 CoreFoundation      0x022d4280 CFRunLoopRunSpecific + 208 
    13 CoreFoundation      0x022d41a1 CFRunLoopRunInMode + 97 
    14 GraphicsServices     0x02bfa2c8 GSEventRunModal + 217 
    15 GraphicsServices     0x02bfa38d GSEventRun + 115 
    16 UIKit        0x002c7b58 UIApplicationMain + 1160 
    17 custom object array save test  0x00002160 main + 102 
    18 custom object array save test  0x000020f1 start + 53 
    19 ???         0x00000001 0x0 + 1 
) 
terminate called after throwing an instance of 'NSException' 

Edit:

j'ai pu résoudre le problème en remplaçant cette ligne

theArray = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]]; 

avec ce Liine

theArray = [[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]]; 

alors je suppose que la question est maintenant pourquoi est-ce que cela a résolu le problème?

+0

Quel est le crash exactement? Y a-t-il une sortie significative dans la console? Lorsque vous obtenez le tableau à partir des valeurs par défaut de l'utilisateur, est-ce la taille que vous attendez? – imaginaryboy

+0

J'ai modifié mon message pour afficher les messages d'erreur. Quoi qu'il en soit, j'ai été capable de corriger le code, mais je ne comprends pas complètement la solution.Devrais-je répondre à ma propre question en montrant la solution, ou attendre que quelqu'un d'autre le comprenne et peut-être donner une meilleure explication? –

Répondre

2

Je ne vois rien de mal avec votre archivage/code désarchivage. Je soupçonne que indexPath.row est hors de portée.

EDIT après OP modifié question:

Le message d'erreur dit: -[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x5955e50

Vous remarquerez que cela signifie que 'theArray' pointe en fait à un NSString. Quelque part vous avez attribué la mauvaise chose à votre variable 'theArray'.

EDIT à nouveau après une autre édition OP:

Dans votre code d'origine, vous avait utilisé alloc/initWithArray: au lieu de arrayWithArray:.

L'utilisation arrayWithArray: ne fonctionne pas pour vous car cette méthode retourne un objet autoreleased. Donc, au moment où vous l'avez utilisé plus tard cette référence aurait pu pointer à peu près tout, et donc dans un cas, il est arrivé à pointer à une chaîne.

+0

Non, ce n'était pas ça. Quand vous l'avez regardé, il n'y avait pas d'erreurs. J'ai corrigé le code ci-dessus afin qu'il montre l'erreur. Je n'ai pu le réparer que parce que j'avais un code de travail à copier, mais je ne comprends pas complètement la solution. Je me demande si je devrais répondre à ma propre question ou attendre de voir si quelqu'un d'autre peut le comprendre et peut-être expliquer quelque chose que je ne comprends pas. –

+0

@awakeFromNib: Si votre solution a fonctionné, affichez-la au moins dans l'OP afin que les autres puissent au moins voir la solution à l'avenir même si une explication ne se présente jamais. – AndyG

Questions connexes