Perché è solo attributo della mia oggetto che viene correttamente scritto in un file?

StackOverflow https://stackoverflow.com/questions/4385721

  •  10-10-2019
  •  | 
  •  

Domanda

Così sto cercando di scrivere un NSMutableArray di oggetti personalizzati (un "Corso" che rappresenta un corso universitario per un'applicazione Planner Corso) in un file quando i miei termina applicazione e poi leggere quella matrice dal file nel ViewController rilevante che si avvarrà dei dati quando l'applicazione si avvia.

Ecco il codice in questione:

CoursesAppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    // Override point for customization after application launch.
    coursesViewController = [[SampleHomeScreen alloc] initWithNibName:@"SampleHomeScreen" bundle:nil];

    NSString *filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        [coursesViewController setCourses:[NSKeyedUnarchiver unarchiveObjectWithFile: filePath]];
    }

    UIApplication *app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)name:UIApplicationWillTerminateNotification object:app];

    [window addSubview:coursesViewController.view];
    [window makeKeyAndVisible];

    return YES;
}

- (NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"data.plist"];
    NSLog(@"%@", path);
    return path;
}

/**
 applicationWillTerminate: saves changes in the application's managed object context before the application terminates.
 */
- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"%@", [coursesViewController courses]);
    [NSKeyedArchiver archiveRootObject:[coursesViewController courses] toFile:[self dataFilePath]];
}

Course.h:

@interface Course : NSObject <NSCoding> {
    NSString *name; //e.g. ECS 189H
    double grade, totalWeight; //course grade in %
    NSMutableArray *list;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic) double grade, totalWeight;
@property (nonatomic, retain) NSMutableArray *list;

-(Course *)initWithName:(NSString *)courseName;

@end

Course.m:

@implementation Course

@synthesize name, grade, totalWeight, list;

-(Course *)initWithName:(NSString *)courseName {
    name = [courseName retain];
    grade = -1.0;
    totalWeight = 0.0;
    list = [[NSMutableArray alloc] init];
    [super init];
    return self;
}

-(Course *)initWithCoder:(NSCoder *)aDecoder {
    self.name = [aDecoder decodeObjectForKey:@"name"];
    self.grade = [aDecoder decodeDoubleForKey:@"grade"];
    self.totalWeight = [aDecoder decodeDoubleForKey:@"totalWeight"];
    self.list = [aDecoder decodeObjectForKey:@"list"];
    [super init];
    return self;
}

- (void) encodeWithCoder: (NSCoder *)coder
{
    [coder encodeObject:name forKey:@"name"];   
    [coder encodeDouble:grade forKey:@"grade"];
    [coder encodeDouble:totalWeight forKey:@"totalWeight"];
    [coder encodeObject:list forKey:@"list"];
}

-(void)dealloc {
    [name release];
    [list release];
    [super dealloc];
}

@end

[corsi coursesViewController] è il NSMutableArray che contiene gli oggetti del corso. So per certo che esso contiene i dati validi.

Quindi i problemi sono, 1: L'applicazione salva data.plist SOLO quando l'eseguo da Xcode (cioè scegliere "Compila e fuggi" in Xcode). 2: carica i dati dal plist, ma tutto ciò che viene salvato sono (rispettivamente -1 e 0) i nomi dei corsi e i valori predefiniti per grado e pesoTotale. Quindi, in realtà essi vengono salvati come se initWithName stato chiamato su di loro prima.

Questa è la mia prima vera immergersi in un applicazione piuttosto avanzata iOS, così come io sono un novizio di questo, forse ho lasciato fuori alcune importanti informazioni. Se questo è il caso, per favore fatemelo sapere e vi aggiornerò la questione.

Grazie! -HT

P.S. Se è rilevante, ho doNotRunInBackground nel set Info.plist su true.

È stato utile?

Soluzione

Il vostro stanno cercando di valori impostati in oggetto prima che sia stato inizializzato. E inizializzazione quindi ripristinare i valori.

-(Course *)initWithName:(NSString *)courseName {
    name = [courseName retain];              // <- Accessing ivar before self is initialized
    grade = -1.0;                            // <- Accessing ivar before self is initialized
    totalWeight = 0.0;                       // <- Accessing ivar before self is initialized
    list = [[NSMutableArray alloc] init];    // <- Accessing ivar before self is initialized
    [super init];                            // initialization resets your values !!!!
    return self;
}

Inoltre si sta ignorando il valore di ritorno di init di eccellente, che funziona bene il 98% di tutti i casi, ma vi consiglio di sempre utilizzare uno schema di inizializzazione corretta:

- (id)init {
    if (self = [super init]) {
        // It's save to access ivars here
    }
    return self
}

In Cocoa un metodo init può restituire un oggetto diverso, poi quello che è stato assegnato. Così si deve di sé assegnare alla init del super-.

Così, il vostro init dovrebbe essere simile:

-(Course *)initWithName:(NSString *)courseName {
    if (self = [super init]) {
        name = [courseName retain];
        grade = -1.0;
        totalWeight = 0.0;
        list = [[NSMutableArray alloc] init];
    }
    return self;
}

Lo stesso vale per initWithCoder:(NSCoder *)coder.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top