iOS CoreData

首先在创建项目的时候最好可以直接勾上 use 

 

如果没勾上的话,可以新建一个带Coredata的新项目,看看都多了些什么东西

首先多了一个

这玩意可以自己新建,它是一个DataModel

 

然后就是AppDelegate多了一些CoreData要用到的一些函数,我大概截个图,Xcode都自动加上了pragma,非常容易分辨

 

如果不想重新建项目的话,自己复制粘贴一下就好。

另外,如果不是预设的名字,在AppDelegate中声明的保存数据等函数中,有以名字实体名作为函数参数的,一定要仔细看一下AppDelegate中的函数参数,避免因为不是预设而连不上数据库。

这些属性是NSURL类型的,是指向数据库地址的,可以通过查NSURL类型的数据来看看有没有错。

同时也可以在查到NSURL后将它打印出来,或者通过其他方式获取,这样就可以通过SQLite的一些软件去管理数据库,例如

 NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoredataDemo.sqlite"];
     NSLog(@"%@",storeURL);

 

在我们存数据时就可以得到输出

2016-01-31 22:42:51.995 CoredataDemo[4597:804629] file:///Users/suntian/Library/Developer/CoreSimulator/Devices/81AE7359-7F19-4634-BBF2-CBA057017373/data/Containers/Data/Application/38AD61EF-493F-4E67-915E-E6940D23E5B7/Documents/CoredataDemo.sqlite

这地址就是数据库的地址了

 

 

接下来是如何使用数据库

首先,打开DataModel,这是一个要用到的数据库

在这里 可以新建Entity(实体),接着在实体中继续添加想要的数据类型

 

接着添加一个用以控制一个Entity的Model,同样新建文件,选CoreData类中的NSManagedObjectSubclass,图就不上了

Xcode会两次问你,要控制哪个数据库的哪个Entity,选中即可,生成了四个文件

接着,在你要用的地方添加model,活动在Viewcontroller中,所以在Viewcontroller中添加

@property Entity *entity;

 

entity的构造可以采用延时构造,并且这样也的确方便

构造时,将不采用init,因为,entity是一个Entity属性的值,它要连接数据库中定义的Entity,而不是去初始化这个属性,所以这里的构造要去连接之前在DataModel中定义的Entity

-(Entity *)entity
{
    if(!_entity)
    {
        _entity = [NSEntityDescription
                   insertNewObjectForEntityForName:@"Entity"
                   inManagedObjectContext:self.context];
    }
    return _entity;
}

 

这里用到了一个  self.context ,context是一个在AppDelegate中定义的属性,它是NSManagedObjectContext类型,在保存数据至数据库时候我们会用到它,具体类型的详细解释可以看一下文档,下面贴出AppDelegate中为CoreData写好的保存函数,就可以看出context的用处

- (void)saveContext {
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        NSError *error = nil;
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

 

所以我们需要在Viewcontroller中引入AppDelegate,它为CoreData定义了很多预设的东西我们都要用到,引入头文件以后,我们就需要再定义

@property NSManagedObjectContext *context;
@property AppDelegate *appdelegate;

 

context我们保存数据要用到 ,通过定义这个appdelegate来调用函数

 

当我们想保存数据时,就先赋值,再save即可

//伪代码
_entity.data = mydata; [self.appdelegate savecontext];

 

当然context和appdelegate别忘了定义,同样采用延时构造比较好

-(NSManagedObjectContext *)context
{
    return self.appdelegate.managedObjectContext;
}

-(AppDelegate *)appdelegate
{
    if (!_appdelegate) {
        _appdelegate = [UIApplication sharedApplication].delegate;
    }
    return _appdelegate;
}

 

appdelegate的构造是返回当前进程的delegate

 

具体什么时候进行这个操作,就看你什么时候获取到了数据,是获取到数据时存数据库或者其他时候,都是自己来决定了。

举个栗子,我有两个按钮,想在按下的时候存点东西进去

-(IBAction)InButtonPressed:(UIButton*)sender
{
    if(sender == _inview.BTIn0)
    {
        NSLog(@"0");
        NSNumber *numb;
        numb = [NSNumber numberWithInt:0];
        _entity.date = [NSDate date];
        _entity.attribute = numb;
        [self.appdelegate saveContext];
    }
    else if(sender == _inview.BTIn1)
    {
        NSLog(@"1");
        NSNumber *numb;
        numb = [NSNumber numberWithInt:1];
        _entity.date = [NSDate date];
        _entity.attribute = numb;
        [self.appdelegate saveContext];
    }
}

 

这样就完成了写库的操作。

但是这个时候,数据库里只会有一条数据发生改变,即entity实际指向的就是那一条数据,不论我按0或者1,都只会保存我上一次按下的数,比如按0,数据中只会有1个0,我再按1,这个0就会变成1而不是添加一条新的1。

后来做如下修改

-(IBAction)InButtonPressed:(UIButton*)sender
{
    Entity *addentity;
    addentity = [NSEntityDescription
                insertNewObjectForEntityForName:@"Entity"
                inManagedObjectContext:self.context];
    if(sender == _inview.BTIn0)
    {
        NSLog(@"0");
        NSNumber *numb;
        numb = [NSNumber numberWithInt:0];
        addentity.date = [NSDate date];
        addentity.attribute = numb;
        [self.appdelegate saveContext];
    }
    else if(sender == _inview.BTIn1)
    {
        NSLog(@"1");
        NSNumber *numb;
        numb = [NSNumber numberWithInt:1];
        addentity.date = [NSDate date];
        addentity.attribute = numb;
        [self.appdelegate saveContext];
    }

//    if(sender == _inview.BTIn0)
//    {
//        NSLog(@"0");
//        NSNumber *numb;
//        numb = [NSNumber numberWithInt:0];
//        self.entity.date = [NSDate date];
//        self.entity.attribute = numb;
//        [self.appdelegate saveContext];
//    }
//    else if(sender == _inview.BTIn1)
//    {
//        NSLog(@"1");
//        NSNumber *numb;
//        numb = [NSNumber numberWithInt:1];
//        self.entity.date = [NSDate date];
//        self.entity.attribute = numb;
//        [self.appdelegate saveContext];
//    }
}

 

在这种情况下,把之前用到的entity所有相关的定义删除也可,因为已经没在用到了,这个时候的savecontext也会把数据存下了,至于为什么savecontext能存下数据并且建立了一条新的?

在http://blog.csdn.net/swj6125/article/details/9969591 中,这篇博文打算存数条数据,而这个作者罗列了相当多的数据来赋值,而最后只用了一条saveContext。

所以我猜测,saveContext可以将所有指向了数据库的指针内容进行保存,而我在按键事件内进行的定义,相当于每次都是一个新的Entity,所以每次都会给我一条新的数据。

saveContext的代码如下

- (void)saveContext {
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        NSError *error = nil;
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

目前还没有在文档中发现有关说明,发现后会补上。

 

 

存完数据以后我们还需要的就是读数据

读数据比较简单

    NSError *error;
    NSFetchRequest *request=[[NSFetchRequest alloc] init];
    NSEntityDescription *entity=[NSEntityDescription entityForName:@"Entity" inManagedObjectContext:self.context];
    [request setEntity:entity];
    NSArray *results=[[self.context executeFetchRequest:request error:&error] copy];

得到的数组results就是返回的所有数据,进行处理就可以了

栗子

    for (Entity *temptntity in results)
    {
        NSLog(@"%@ %@",temptntity.date,temptntity.attribute);
    }

 

SSH git@github.com:kakinuma4ko/iOSDmo.git

posted @ 2016-01-31 22:45  柿沼  阅读(145)  评论(0编辑  收藏  举报