在模型类中保存数据,在viewController,init方法,NSCoder,NSArchiver中加载

时间:2014-05-26 15:13:09

标签: ios objective-c nsmutablearray init

我是Xcode的新手,请帮忙。

我有三个viewControllers(子类UIViewController)和一个Model类(Sub class NSObject)。 当应用启动时 - >>“ViewController.h”加载然后导航到
- > “DetailsViewController.h” - > “AddHoursViewController.h”
使用navigationButtons调用相关的prepareForSegueUnwindToSeque方法,我使用xcode版本并使用“ARC”更新。

我的问题是应用程序启动正常。它的负载是“monthArray”,而不是“grossMutableArray”(希望它能加载0000.00对象)。一旦我导航到“AddHoursViewController.h”(堆栈中的第三个)并尝试返回(unwindToSegue调用哪个调用[dataModel saveDataToDisk];应用程序崩溃。如果我评论[dataModel saveDataToDisk];方法输出,app导航很好没有加载任何数据。

有趣的事情是在“重置iOS模拟器并删除所有模拟器数据”之后,如果我在发布之前在self.grossPayArray = [rootObject objectForKey:kGrossPayArrayKey];中注释-(void)loadDataFromDisk,则应用启动比 - >停止模拟器 - >删除评论 - >重新启动,一切正常。

我在谷歌之后尝试了各种各样的事情,似乎没有什么对我有用。我认为init方法需要修改,但我无法理解它,请帮忙。

相关代码崩溃日志

#import "DataModel.h"
#import "ViewController.h"
#import "DetailsViewController.h"
#import "AddHoursViewController.h"
NSString *const kMonthArrayKey = @"MonthArray";
NSString *const kGrossPayArrayKey = @"GrossPayArray";
NSUInteger indexNumber;
ViewController *viewController;

@implementation DataModel
- (id)init
{
    self = [super init];
    if (self) {
self.monthArray = [NSArray arrayWithObjects:@"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec", @"Jan", @"Feb", @"Mar", nil];

self.grossPayArray = [NSMutableArray arrayWithObjects:@"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", @"0000.00", nil];

[self loadDataFromDisk];
        //NSLog(@"init method called");     
    }
    return self;
}

//NSCODING
-(void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.monthArray forKey:kMonthArrayKey];
[encoder encodeObject:self.grossPayArray forKey:kGrossPayArrayKey];

    NSLog(@"-(void)encodeWithCoder:(NSCoder *)encoder method called");
}

//decoding data from file
-(id)initWithCoder:(NSCoder *)decoder
{
    self = [super init];
    if (!self){

        return nil;
}

self.grossPayArray = [decoder decodeObjectForKey:kGrossPayArrayKey];
        return self;
}   


#pragma mark Methods associated with saving data on the disk for this class
//file path where data resides
-(NSString*)pathForDataFile
{
    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSArray *pathToDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *fileFolder = [pathToDirectory objectAtIndex:0];
    NSString *fileName = @"MyAppfileName";
    if ( [fileManager fileExistsAtPath:fileFolder] == NO)
    {
       // NSLog(@"pathForDataFile does not exist %@", filePath);
        [fileManager createDirectoryAtPath:fileFolder withIntermediateDirectories:NO attributes:nil error:nil];
        NSLog(@"%@ documentDirectory", fileName);
    }

return [fileFolder stringByAppendingPathComponent:fileName];
}

//Method to save data
-(void)saveDataToDisk
{
    NSString *path = [self pathForDataFile];

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSUInteger indexNumber = [defaults integerForKey:@"Index number"];

    self.rootObject = [NSMutableDictionary dictionary];//dictionary creation


    [self.grossPayArray replaceObjectAtIndex:indexNumber withObject:basicPayString];

    [self.rootObject setObject:[self grossPayArray] forKey:kGrossPayArrayKey];
    [NSKeyedArchiver archiveRootObject:self.rootObject toFile:path];}

//method to load data
- (void)loadDataFromDisk
//comment out eg grossArray array, loads it from -init, after first launch and invoking (self saveDataToDisk] --> stop app --> remove double slashed --> relaunch,  will than replace object at index
//putting arrays under this code replaces object at index for chosen month and keeps one added before. if remove array from here replaces object at index but puts values from init methods in other objects.
    {
    NSString *path = [self pathForDataFile];
    //NSLog(@"path in loadDataFromDisk %@", path);
    NSDictionary *rootObject;
    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

    self.grossPayArray = [rootObject objectForKey:kGrossPayArrayKey];   
}



-(id)initWithDocPath:(NSString *)docPath
{
    if ((self = [super init])) {

        _docPath = [docPath copy];
}
    _docPath = [self pathForDataFile];
    //NSLog(@"doc path init %@", _docPath);
    return self;

}

@end

/////////////////解除调用时调用[dataModel saveDataToDisk]的错误日志/崩溃日志如果调用saveDataToDisk注释掉,那么应用导航就可以不加载任何数据./////////

2014-05-26 15:25:27.596 CollectionFromNSObject[1179:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: grossPayArray)'
*** First throw call stack:
(
    0   CoreFoundation                      0x018de1e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x0165d8e5 objc_exception_throw + 44
    2   CoreFoundation                      0x01967eb8 -[__NSDictionaryM setObject:forKey:] + 888
    3   CollectionFromNSObject              0x0000868f -[DataModel saveDataToDisk] + 2927
    4   CollectionFromNSObject              0x00063b13 -[DetailsViewController unwindToDetailsViewController:] + 19203
    5   libobjc.A.dylib                     0x0166f82b -[NSObject performSelector:withObject:] + 70
    6   UIKit                               0x009f6a91 -[UIStoryboardUnwindSegueTemplate _perform:] + 536
    7   UIKit                               0x00881f87 -[UIStoryboardSegueTemplate perform:] + 115
    8   libobjc.A.dylib                     0x0166f880 -[NSObject performSelector:withObject:withObject:] + 77
    9   UIKit                               0x0031f3b9 -[UIApplication sendAction:to:from:forEvent:] + 108
    10  UIKit                               0x0060c8df -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 139
Continues...................

1 个答案:

答案 0 :(得分:0)

1)您需要将字典写入磁盘,然后才能从磁盘中获取它。

否则会有很多问题,但有你的关键。我相信随着时间的推移你会养成良好的习惯,所以我会忽略其余的。尝试寻找导师并分离责任。例如,保存,加载,查看是不同的部分