iOS Core Data框架使用

什么是Core Data

简单来说,Core Data就是一个面向对象的持久化数据管理框架。使用Core Data可以将数据持久化的保存在存储设备中,也可以在适当的时候将其取出来。

Core Data底层的存储方式既可以是SQLite数据库也可以是XML文档甚至都可以将数据保存在内存中。

使用Core Data的好处是可以以面向对象的方式进行数据操作避免了直接与SQL语句接触,简化了操作步骤,提升程序开发效率。

Core Data的构成

1. NSManagedObject

Core Data 所管理的实体。

实体是Core Data的核心概念,其为Core Data所管理的对象。其中,实体必须为NSManagedObject或其子类。

实体有自己的属性,例如一个书籍的实体就可以有书名、价格、作者等属性。一个作者的实体就可以有姓名、出生年月、写过的书籍等属性。

实体之间的关系有1-1,1-N,N-N,例如一个书籍可以对应一个作者,这就是1-1关系,一个作者可以对应多本书籍,这就是N-N关系。

2. NSManagedObjectContext

托管对象上下文对象是Core Data中的核心对象,要对Core Data所管理的实体进行增、删、改、查都要通过此对象进行。

3. NSPersistentStoreCoordinator

持久化存储协调器对象负责Core Data的底层存储结构,对Core Data的底层的存储方式的初始化就要经过这个对象。例如,要使用SQLite方式存储NSManagedObject或其子类,就要经过这个对象来进行设置。

4. NSManagedObjectModel

托管对象模型对象包含了Core Data中的所有的NSManagedObject以及实体之间的关系。

它对应于项目中的.xcdatamodeld文件(编译后为.momd文件),可以用来以可视化的方式编辑Core Data中的各种实体以及关系。

5. NSEntityDescription

实体描述是对Core Data 中的实体进行抽象。

相当于数据库中的表结构。

6. NSFetchRequest

实体获取请求用来按特定条件获取Core Data中的数据。

可以想象成数据库中的查询语句。

应用实例

估计看了上面的一大堆也很难理解Core Data的组成及使用,下面通过一个小的应用实例来近距离感受下Core Data。

Core Data 中有两个实体,分别是LXYBookLXYAuthor
其中LXYBooknameprice两个属性,LXYAuthor
nameauthorDesc两个属性。

应用的界面架构如下:

storyboard1

第一行,从左到右依次是

Navigation Controller ->LXYAuthorListTableViewController->LXYBooksListTableViewController

第二行从左到右依次是

LXYUserAddNavigationController->LXYBooksAddNavigationController

storyboard2

第一行从左到右依次是
LXYUserAddNavigationController->LXYBooksAddNavigationController

第二行从左到右依次是

LXYAuthorAddViewController->LXYBookAddViewController

所有文件结构如下

file

其中,LXYBooksListTableViewController用于显示某个作者的书籍列表,LXYAuthorListTableViewController用于显示所有的作者。点击某个作者进入LXYBooksListTableViewControllerLXYAuthorAddViewController用于添加作者,LXYBookAddViewController用于添加指定作者的书籍。

1. 新建应用

新建一个iOS的Single View Application没什么好说的。

step1

2. 添加Core Data支持

在Xcode中点击File->new file 点击左侧的Core Data,再选Data Model,如下图所示

step3

点击Next,填好相应信息,如下图

step3

我起的名字是 LXYBooksModel,现在应该出现在项目的文件列表里面,我的情况如下图

step4

3. 配置实体及关系

点击LXYBooksModel.scdatamodeld文件,点击Add Entity 将Entity命名为LXYBook,再点击Attributes栏里的+按钮,添加name、price属性并分别将属性类型配置为StringDouble。再按相同步骤添加并配置好LXYAuthor实体及其属性,配置好如下图所示

step5

step5.5

再在LXYBook的RelationShip栏中添加一个author关系,并按下图配置好

step6

同样的方式在LXYAuthor中添加books关系,并按下图配置好

step7

最后点击Editor->Create NSManagedObject subclass 并勾选相应地实体生成与实体同名的子类。

4. 初始化Core Data框架

如下编辑AppDelegate.h文件

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (readonly, strong, nonatomic) NSManagedObjectContext * managedObjectContext;
@property (readonly ,strong, nonatomic) NSManagedObjectModel * managedObjectModel;
@property (readonly , strong, nonatomic) NSPersistentStoreCoordinator * persistentStoreCoordinator;

- (void) saveContext;
- (NSURL *) applicationDocumentDirectory;

@end

AppDelegate.m文件中首先将与Core Date有关的三个属性设置为@synsize,再分别设置他们的get方法,实现Lazy Loading

@synthesize managedObjectContext = _managedObjectContext;
@synthesize  managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

- (NSManagedObjectContext *)managedObjectContext
{
    if(_managedObjectContext != nil)
    {
        return _managedObjectContext;
    }

    //获取NSPersistentStoreCoordinator对象
    NSPersistentStoreCoordinator * persistentStoreCoordinator = self.persistentStoreCoordinator;
    if(persistentStoreCoordinator != nil)
    {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        //根据NSPersistentStoreCoordinator设置
        //NSManagedObjectContext的底层存储方式
        [_managedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinator];
    }

    return _managedObjectContext;
}

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

    //根据LXYBooksModel.xcdatamodeld文件
    //(编译后为LXYBooksModel.momd文件)
    //初始化NSManagedObjectModel
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"LXYBooksModel" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

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

    //初始化并设置为SQLLite数据库方式存储数据
    NSURL *storeURL = [[self applicationDocumentDirectory] URLByAppendingPathComponent:@"LXYBooks.sqlite"];
    NSError *error = nil;
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";

    //如果不能正确初始化
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
        dict[NSLocalizedFailureReasonErrorKey] = failureReason;
        dict[NSUnderlyingErrorKey] = error;
        error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

//保存数据
- (void)saveContext
{
    NSError * error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if(managedObjectContext != nil)
    {
        //检测是否有数据变化并且还未保存
        //如果有就保存
        //保存失败报告原因
        if([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
            NSLog(@"saved failed: %@,%@",error,[error userInfo]);
            abort();
        }
    }
}

//获取用户沙箱路径用于创建数据库文件
- (NSURL *)applicationDocumentDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

//应用将要结束时调用saveContext方法保存数据
- (void)applicationWillTerminate:(UIApplication *)application {

    [self saveContext];
}

5. 其他文件代码

LXYAuthorListTableViewController中获取全部作者

- (NSMutableArray *)fetchAuthorsFromDataSource
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    //设置实体描述
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"LXYAuthor" inManagedObjectContext:self.appDelegate.managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;

    //执行获取语句
    NSMutableArray *authors = [[self.appDelegate.managedObjectContext
                     executeFetchRequest:request error:&error] mutableCopy];

    if(authors == nil)
    {
        NSLog(@"Error when fetch authors from data source:%@,%@",error,[error userInfo]);
    }

    return authors;
}

从Core Data中删除作者

//从Core Data中删除传入的LXYAuthor
- (void)removeAuthorFromDataSource:(LXYAuthor *)author
{
    [self.appDelegate.managedObjectContext deleteObject:author];

    NSError *error = nil;
    if(![self.appDelegate.managedObjectContext save:&error])
    {
        NSLog(@"Error when remove author form data source:%@,%@",error,[error userInfo]);
    }
}

LXYAuthorAddViewController中添加作者

- (void)addAuthor
{
    NSString *name = self.nameTextField.text;
    NSString *authorDesc = self.descTextField.text;

    //在Core Data中创建LXYAuthor对象
    LXYAuthor *author = [NSEntityDescription insertNewObjectForEntityForName:@"LXYAuthor" inManagedObjectContext:self.appDelegate.managedObjectContext];

    //设置属性
    author.name = name;
    author.authorDesc = authorDesc;

    NSError *error = nil;
    //执行保存并验证是否保存成功
    if([self.appDelegate.managedObjectContext save:&error])
    {
        NSLog(@"Error when add author:%@,%@",error,[error userInfo]);
    }

}

LXYBooksListTableViewController中获取指定作者的书籍

- (NSMutableArray *)fetchBooksForAuthor:(LXYAuthor *)author
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"LXYBook" inManagedObjectContext:self.appDelegate.managedObjectContext];
    [request setEntity:entity];

    //设置request的谓词,相当于SQL语句中的
    //WHERE author = ? 子句
    //用于获取指定作者的书籍
    //这里就是根据在Core Data中的LXYBook实体的author关系来抓取
    request.predicate = [NSPredicate predicateWithFormat:@"author=%@",author];

    NSError *error = nil;
    NSMutableArray *books = [[self.appDelegate.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

    if(books == nil)
    {
        NSLog(@"Error when fetch books for author:%@,%@",error,[error userInfo]);
    }

    return books;
}

LXYBookAddViewController中添加指定作者的书籍

- (void)addBookForAuthor:(LXYAuthor *)author
{
    LXYBook *book = [NSEntityDescription insertNewObjectForEntityForName:@"LXYBook" inManagedObjectContext:self.appDelegate.managedObjectContext];

    book.name = self.nameTextField.text;
    double price = [self.priceTextField.text doubleValue];
    book.price = [NSNumber numberWithDouble:price];

    //这里直接设置即可
    //关系也可以当做属性使用
    book.author = self.author;

    NSLog(@"In books add ,author name:%@",book.author);

    NSError *error = nil;
    if(![self.appDelegate.managedObjectContext save:&error])
    {
        NSLog(@"Error when add book for author:%@,%@",error,[error userInfo]);
    }
    else
    {
        NSLog(@"Add book successed");
    }
}

完整程序见 我的GitHub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值