Question

Je vais avoir un « doesNotRecognizeSelector » exception et je pense que peut-être mon retour Unarchiver tableau immuable intstead de mutable. Ai-je raison ? comment dois-je faire l'archivage et l'archivage correctement? (Lieu d'exception est de montrer vers le bas)

Merci !!!

NSMutableArray* arr;

- (void) write
{
         NSMutableData *data = [[NSMutableData alloc] init];
         NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

 NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] copy];
        [archiver encodeObject:copy forKey:@"Key"];
        [archiver finishEncoding];
        [data writeToFile:[Util DataPath] atomically:YES];
        [archiver release];
        [data release];
        [copyOfPaidPacks release];
}




-(NSMutableArray*) read
{
    NSString* DataPath = [Util FilePath];
    NSData *data = [[NSMutableData alloc] initWithContentsOfFile:DataPath];
    NSKeyedUnarchiver *unarchiver = nil;
    if (data != nil)
    {
            unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];

    if([self.Arr count] <= 0)
    {
        self.Arr = [unarchiver decodeObjectForKey:@"Key"];  
    }
}

[unarchiver finishDecoding];
[unarchiver release];
[data release];
    return self.arr
}

-(void)B
{
     [self write];
     NSMutableArray* SecondArr = [self read];
     [SecondArr sortUsingSelector:@selector(CompareDate:)]; - > `****THIS IS WHERE I GET THE EXCEPTION`
}
  • Modifier

Ajout de la méthode comparative:

- (NSComparisonResult)CompareDate:(T*)p
{
    NSComparisonResult result = [self.changeDate compare:p.changeDate];
    if(result == NSOrderedDescending)
        result = NSOrderedAscending;
    else if(result == NSOrderedAscending)
        result = NSOrderedDescending;

    if(result == NSOrderedSame)
    {
        result = [self CompareName:p];
    }

    return result;
}
Était-ce utile?

La solution

NSKeyedUnarchiver ne retourne en effet un NSArray immuable. Si vous voulez vraiment obtenir un NSMutableArray, vous auriez besoin d'appeler -mutableCopy sur la valeur de retour de decodeObjectForKey:.

Cet extrait de code me demande si vous avez vraiment besoin d'un même tableau mutable cependant. On dirait que vous êtes juste trier le tableau que vous obtenez de -read. Pourquoi ne pas simplement appeler sortedArrayUsingSelector: sur le NSArray immuable à la place?

Autres conseils

Vous passez déjà un tableau immuable au archiveur, alors pourquoi pensez-vous que le Unarchiver pour revenir un mutable alors?

Si vous voulez une copie être mutable, vous devez utiliser

NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] mutableCopy];

NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] copy];

crée une copie immuable (au moins aussi loin, que vous devriez vous inquiéter. En réalité, le cadre utilise souvent une représentation interne mutable pour les instances immuables, mais cela est un détail de mise en œuvre et vous ne devriez pas compter là-dessus, comme ces représentations ont changé dans le passé et la documentation Cocoa vous dire explicitement, de ne pas vérifier la représentation interne).

EDIT: juste testé avec NSKeyedArchiver moi-même sur simulateur iOS 5.0:

// this returns a mutable instance at runtime!
NSMutableArray* test0 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:[NSMutableArray array]]];
// this returns an immutable instance at runtime!
NSArray* test1 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:[NSArray array]]];

Donc, votre problème est vraiment causé exclusivement en utilisant la copie au lieu de mutableCopy, lors de l'archivage et désarchivage conserve les attributs de mutabilité correcte des cas!

J'ai eu un problème où l'archivage d'un tableau mutable 3 dimensions (par exemple un tableau mutable de tableaux mutables de tableaux mutables) serait désarchiver comme un tableau mutable de tableaux immuables de tableaux immuables.

La clé de la fixation de ce sous-classe était NSKeyedUnarchiver et écrasez

- (Class)classForClassName:(NSString *)codedName
{
    Class theClass = [super classForClassName: codeName];

    if ([codeName isEqualToString: NSStringFromClass(NSArray.class))
    {
        theClass = NSMutableArray.class;
    }
    //... more here like NSDictionary
    return theClass;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top