一个完整 CoreData 存储 demo

自己负责一个项目走过来, 遇到很多需求, 印象最深且最让自己引以为豪的还是 CoreData 的使用了, 公司其他人都不会用, 我选择了这个作为存储数据的杀手锏, 说实话使用的过程遇到很多问题, 也挺让人头疼的, 但还是一步一步走过来了......也让我相信很多时候觉得不可能解决的问题, 再研究研究是可以解决的!

开始正题:

现在说的是 项目中 创建CoreData Model

1.创建 CoreData Model

一个完整 CoreData 存储 demo_第1张图片
1.png
一个完整 CoreData 存储 demo_第2张图片
2.png
一个完整 CoreData 存储 demo_第3张图片
3.png

这里说一下创建好的类文件默认显示的路径会在项目名路径下, 如果你在创建之前已经指定好路径, 其实是在你指定的路径的, 我们可以将位置移一下; 但就全局来看, 当你想保存多个模型时, 放在默认位置就好

这里编译一下

出现报错, 来到这个文件中


一个完整 CoreData 存储 demo_第4张图片
4.png
一个完整 CoreData 存储 demo_第5张图片
5.png

到这里就可以CoreData 模型也就创建完成了, 编译成功

2.创建 CoreDataManager 管理文件

#import 
#import 

#define kCoreDataManager [CoreDataManager shareInstane]

#define kFilePathName @"Announce" 

@interface CoreDataManager : NSObject

+(CoreDataManager *)shareInstane;



#pragma mark CoreData Stack

// 管理对象上下文
@property(nonatomic,strong)NSManagedObjectContext *managedObjectContext;
// 对象模型
@property(nonatomic,strong)NSManagedObjectModel *managedObjectModel;
// 存储调度器
@property(nonatomic,strong)NSPersistentStoreCoordinator *persistentStoreCoordinator;

#pragma mark -Funcation

// 保存到数据库
- (void)save;

// 清空数据库
- (void)deletAllEntities;

// 插入数据
- (void)insertCoreData:(NSMutableArray*)dataArray;

/**
 查询并返回数据

 @param pageSize 一个查询多少条
 @param currentPage 当前页数(多少条算一页)
 @param predicate 查询谓词条件
 @param entityName 查询的实体模型名称
 @param sortKey 排序条件(根据哪个 key 排序)
 @return 返回查询到的数据
 */
- (NSArray *)selectData:(int)pageSize andOffset:(int)currentPage andPredicate:(NSPredicate *)predicate entityName:(NSString *)entityName sortKey:(NSString *)sortKey;

// 判断将要保存的数据是否已经存在于 coreData 中
- (BOOL)fetchAllObjectsWithSaveDataArr:(NSMutableArray *)array;

// 更新coreData 中的字段(需要更新的字段参数可自定义)
- (void)updateData:(NSString*)newsId  withIsLook:(NSString*)islook;

.m 文件中

#import "CoreDataManager.h"
#import "Announcement+CoreDataClass.h"
#import "Contact+CoreDataClass.h"

@implementation CoreDataManager
// 管理模型上下文
@synthesize managedObjectContext = _managedObjectContext;
// 管理对象模型
@synthesize managedObjectModel = _managedObjectModel;
// 存储调度器
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

+(CoreDataManager *)shareInstane
{
    static CoreDataManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[CoreDataManager alloc] init];
    });
    return manager;
}


// 懒加载
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
    return _managedObjectContext;
    }

    //1.创建管理对象上下文 参数是指定上下文的线程环境  建议使用:NSMainQueueConcurrencyType主线操作(主线程操作没有延迟)   NSPrivateQueueConcurrencyType(子线程操作数据存储会有一定延迟)
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    //2.设置存储调度器(存储数据时 对象上下文负责给存储调度器发送指令)
    [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];

    //3.返回
    return _managedObjectContext;
}


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

    //1.创建对象模型(参数:值得是模型文件  xcdatamodeld路径)
    //注意:模型文件的后缀不能使用xcdatamodeld,否则会崩溃。 只能用momd
    //这个是保存单个模型时使用
//    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"IAAnnounce" withExtension:@"momd"]];

    //2.使用合并的方式创建对象模型(上面的操作创建模型此时只能保存一个固定的数据库xc文件,用该方法则可以同时管理多个模型xc文件)
    //参数是一个bundle路径的数组  如果设为nil,则会自动帮你寻找整个项目中所有的路径下的cx模型文件
    _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

    //2.返回
    return _managedObjectModel;
}


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

    NSString *storeType = NSSQLiteStoreType;

    NSError *error = NULL;
 //    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"IAAnnounce.db"];

//    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
//                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
//                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];

//    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
//        NSLog(@"Error : %@\n", [error localizedDescription]);
//        NSAssert1(YES, @"Failed to create store %@ with NSSQLiteStoreType", [storeURL path]);
//    }

    //1.创建存储调度器 参数:对象模型
//    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
    //2.给存储调度器添加存储器(存储调度器的作用是调度存储器)
    /**storeType
     NSSQLiteStoreType 数据库形式存储
     NSXMLStoreType XML形式存储
     NSBinaryStoreType 二进制存储
     NSInMemoryStoreType 内存形式存储
     */
    /**
     type:
 
     configuration:配置 一般为nil,默认设置
     URL:数据库文件保存的路径
     options:参数信息  一般为nil,默认设置
     error:报错
     */

     NSURL *fileURL = [[self getDocumentUrl] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.db",kFileName]];
    [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:fileURL options:nil error:nil];
    //3.返回
    return _persistentStoreCoordinator;
}


#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

// 保存数据
- (void)save
{
    NSError *errol = nil;
    //数据库的增删改查保存等操作都是操作上下文
    [self.managedObjectContext save:&errol];
    if (errol == nil) {
        NSLog(@"保存到数据库成功");
    } else {
        NSLog(@"%@",errol.description);
    }
}

// 删除所有数据
- (void)deletAllEntities
{
    //清空数据库快捷方式可以直接删除数据库文件
    NSString *filePath1 = [NSString stringWithFormat:@"%@/Documents/%@.db",NSHomeDirectory(),kFilePathName];
    NSString *filePath2 = [NSString stringWithFormat:@"%@/Documents/%@.db-shm",NSHomeDirectory(),kFilePathName];
    NSString *filePath3 = [NSString stringWithFormat:@"%@/Documents/%@.db-wal",NSHomeDirectory(),kFilePathName];

    NSError *error;
    [[NSFileManager defaultManager] removeItemAtPath:filePath1 error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:filePath2 error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:filePath3 error:&error];

    if (error == nil) {
        NSLog(@"清除数据库成功");
    }  else {
        NSLog(@"%@",error.description);
    }
}


// 插入数据
- (void)insertCoreData:(NSMutableArray*)dataArray
{
    // 创建管理对象上下文
    NSManagedObjectContext *context = [self managedObjectContext];

    // 判断数据是否重复
    BOOL result = [self fetchAllObjectsWithSaveDataArr:dataArray];
    if (result) { return ; }

    // 将传进来的数据遍历, 保存到 coreData 模型中       
    for (AnnounceModel *info in dataArray) {
        // 实体描述器生成一个新的实体模型
        AnnounceMent *newsInfo = [NSEntityDescription insertNewObjectForEntityForName:announcement inManagedObjectContext:context];
        
        // ******注意: 传进来的数据保存时一定要与 coreData 实体中字段类型相对应否则很容易引起崩溃
        newsInfo.content = info.content;
        newsInfo.title = info.title;
        newsInfo.islook = info.islook;
        newsInfo.createDate = [NSString stringWithFormat:@"%@",info.createDate];
        newsInfo.notice_id = [NSString stringWithFormat:@"%@",info.notice_id];
        newsInfo.path = info.path;
        
        // 保存到数据库中
        [kCoreDataManager save];
    }
}


// 判断是否已存有相同数据
- (BOOL)fetchAllObjectsWithSaveDataArr:(NSMutableArray *)array
{
    NSManagedObjectContext *context = [self managedObjectContext];

    //首先你需要建立一个request查询条件  announcement: 是你创建的实体entity 名称(我这里使用的宏定义)
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:announcement inManagedObjectContext:context]];

    NSError *error = nil;
    //这里获取到的是一个数组,你需要取出你要更新的那个obj
    //在没有谓词查询条件下, 取出的是所有
    NSArray *result = [context executeFetchRequest:request error:&error];

    for (AnnounceModel *info in array) {
        for (AnnounceMent *obj in result) {
        //            NSLog(@"obj.notice_id: %@ / info.notice_id: %@",obj.notice_id, info.notice_id);
            if ([obj.notice_id.description isEqualToString: info.notice_id.description]) {
                //                NSLog(@"id 相同");
                return YES;
            }
        }
    }
    return NO;
}



// 根据查询条件查询数据
- (NSArray *)selectData:(int)pageSize andOffset:(int)currentPage andPredicate:(NSPredicate *)predicate entityName:(NSString *)entityName sortKey:(NSString *)sortKey
{
    NSManagedObjectContext *context = [self managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[fetchRequest setEntity:entity ];

    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:sortKey ascending:NO];
    fetchRequest.sortDescriptors = @[sort];

    // 限定查询结果的数量 setFetchLimit
    // 查询的偏移量 setFetchOffset
    if (pageSize != 0) {
        [fetchRequest setFetchLimit:pageSize];
        [fetchRequest setFetchOffset:currentPage*pageSize];
    }

    if (predicate != nil) {
        [fetchRequest setPredicate:predicate];
    }

    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

    return fetchedObjects;
}



// 更新数据
- (void)updateData:(NSString *)newsId withIsLook:(NSString*)islook
{
    NSManagedObjectContext *context = [self managedObjectContext];
    // 谓词
    NSPredicate *predicate = [NSPredicate
                          predicateWithFormat:@"notice_id==%@", newsId.description];

    //首先你需要建立一个request
    NSFetchRequest * request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:announcement inManagedObjectContext:context]];
    [request setPredicate:predicate];//这里相当于sqlite中的查询条件,具体格式参考苹果文档

    //https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pCreating.html

    NSError *error = nil;
    NSArray *result = [context executeFetchRequest:request error:&error];//这里获取到的是一个数组,你需要取出你要更新的那个obj

    for (AnnounceModel *info in result) {
        info.islook = islook;
    }

    //保存
    if ([context save:&error]) {
        //更新成功
        NSLog(@"更新成功");
    }
}

这些就是基本的 CoreData 操作

你可能感兴趣的:(一个完整 CoreData 存储 demo)