iOS核心数据:对象未在sqlite中持久保存

时间:2014-05-14 10:22:43

标签: core-data

我尝试做的是解析json,并从解析的Arrays创建managedObject并将它们保存到数据库中。稍后,使用生成的sqlite数据库作为预加载数据库。

这是我预加载数据的方式,self.busstops,self.addresses,self.busroutes和self.busservice是从json文件解析的数组。

- (void)preloadData
{
    [self.busstops enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        BusStop *busstop = [NSEntityDescription insertNewObjectForEntityForName:@"BusStop"
                                                     inManagedObjectContext:[self managedObjectContext_busstop]];
        busstop.bus_stop_id = [obj objectForKey:@"bus_stop_id"];
        busstop.road = [obj objectForKey:@"road"];
        busstop.desc = [obj objectForKey:@"description"];
        busstop.lat = [obj objectForKey:@"lat"];
        busstop.lng = [obj objectForKey:@"lng"];
        busstop.index = (busstop.desc && busstop.desc.length > 0) ? [busstop.desc substringToIndex:1] : @"-";

        NSError *error;
        if (![[self managedObjectContext_busstop] save:&error])
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }];

    [self.addresses enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        Address *address = [NSEntityDescription insertNewObjectForEntityForName:@"Address"
                                                     inManagedObjectContext:[self managedObjectContext_address]];
        address.address_id = @(idx);
        address.block = [obj objectForKey:@"block"];
        address.road = [obj objectForKey:@"road"];
        address.postal_code = [obj objectForKey:@"postal_code"];
        address.building = [obj objectForKey:@"building"];
        address.lat = [obj objectForKey:@"lat"];
        address.lng = [obj objectForKey:@"lng"];
        address.full_road = (address.block && address.block.length > 0) ?
        [NSString stringWithFormat:@"%@, %@", address.block, address.road] :
        [NSString stringWithFormat:@"%@", address.road];
        address.index = (address.building && address.building.length > 0) ? [address.building substringToIndex:1] : @"-";

        NSError *error;
        if (![[self managedObjectContext_address] save:&error])
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }];

    [self.busroutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSString *bus_service_num = [obj objectForKey:@"bus_service"];
        NSString *bus_type = [obj objectForKey:@"bus_type"];
        NSArray *routes = [obj objectForKey:@"routes"];

        [routes enumerateObjectsUsingBlock:^(id route, NSUInteger route_idx, BOOL  *route_stop) {
            NSNumber *bus_dir = [route objectForKey:@"direction"];
            NSArray *bus_routes = [route objectForKey:@"bus_route"];

            [bus_routes enumerateObjectsUsingBlock:^(id busstop, NSUInteger busstop_idx, BOOL *busstop_stop) {
                NSString *bus_stop_id = [busstop objectForKey:@"bus_stop_id"];
                NSNumber *route_seq = [busstop objectForKey:@"route_seq"];
                NSString *stop_distance = [busstop objectForKey:@"stop_distance"];
                NSDictionary *first_bus = [[busstop objectForKey:@"first_bus"] firstObject];
                NSDictionary *last_bus = [[busstop objectForKey:@"last_bus"] firstObject];

                BusRoute *busroute = [NSEntityDescription insertNewObjectForEntityForName:@"BusRoute"
                                                               inManagedObjectContext:    [self managedObjectContext_busroutes]];
                busroute.bus_service_num = bus_service_num;
                busroute.bus_dir = bus_dir;
                busroute.route_seq = route_seq;
                busroute.stop_distance = stop_distance;
                busroute.first_wd = [first_bus objectForKey:@"weekday"];
                busroute.last_wd = [last_bus objectForKey:@"weekday"];
                busroute.first_sat = [first_bus objectForKey:@"sat"];
                busroute.last_sat = [last_bus objectForKey:@"sat"];
                busroute.first_sun = [first_bus objectForKey:@"sun"];
                busroute.last_sun = [last_bus objectForKey:@"sun"];
                busroute.bus_stop_id = bus_stop_id;
                busroute.bus_type = bus_type;

                NSError *error;
                if (![[self managedObjectContext_busroutes] save:&error])
                    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
            }];
        }];
    }];

    [self.busservice enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        BusService *bus_service = [NSEntityDescription insertNewObjectForEntityForName:@"BusService"
                                                            inManagedObjectContext:[self managedObjectContext_busservice]];
        bus_service.bus_service_num = obj[@"bus_service"];
        bus_service.bus_type = obj[@"bus_type"];

        NSError *error;
        if (![[self managedObjectContext_busservice] save:&error])
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }];
}

这就是我的managedObject_context的编码方式:

- (NSManagedObjectContext *)managedObjectContext_busstop
{
    if (_managedObjectContext_busstop != nil)
        return _managedObjectContext_busstop;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        _managedObjectContext_busstop = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_managedObjectContext_busstop setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext_busstop;
}

- (NSManagedObjectContext *)managedObjectContext_address
{
    if (_managedObjectContext_address != nil)
        return _managedObjectContext_address;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        _managedObjectContext_address = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_managedObjectContext_address setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext_address;
}

- (NSManagedObjectContext *)managedObjectContext_busroutes
{
    if (_managedObjectContext_busroutes != nil)
        return _managedObjectContext_busroutes;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        _managedObjectContext_busroutes = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_managedObjectContext_busroutes setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext_busroutes;
}

- (NSManagedObjectContext *)managedObjectContext_busservice
{
    if (_managedObjectContext_busservice != nil)
        return _managedObjectContext_busservice;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        _managedObjectContext_busservice = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_managedObjectContext_busservice setPersistentStoreCoordinator:coordinator];
    }
   return _managedObjectContext_busservice;
}

- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil)
       return _managedObjectModel;

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"SMRTConnectCD" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil)
        return _persistentStoreCoordinator;

    NSURL *applicationDocumentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *storeURL = [applicationDocumentsDirectory URLByAppendingPathComponent:@"SMRTConnectCD.sqlite"];

    NSLog(@"store: %@", storeURL);

    if (!self.preloadEnabled)
    {
        if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]])
        {
            NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"SMRTConnect_preload" ofType:@"sqlite"]];

            NSError* err = nil;

            if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err])
                NSLog(@"Oops, could not copy preloaded data");
        }
    }

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

在所有这些处理之后,当我转到我的应用程序的另一部分时,我可以看到表中列出的所有总线服务。但是,当我复制生成的sqlite文件并使用firefox的sqlitemanager打开它时,总线服务表是空的或不完整的(缺少一些条目)。

我已仔细检查过我的代码,老实说我不知道​​代码出了什么问题。

1 个答案:

答案 0 :(得分:0)

在iOS 7上,Core Data使用wal模式日记与SQLite,因此任何商店文件foo.sqlite都有两个名为foo.sqlite-walfoo.sqlite-shm的关联文件。如果你不复制这三个,你就无法获得数据。