ios10.3之CoreData的详细教程
2017-07-31 22:07
351 查看
首先如果要使用CoreData可以选择在初创项目时选择添加coredata,也可以选择自己添加coredata文件
系统添加coredata后会在Appdelegate类中自动添加一个persistentContainer属性,和一个saveContext方法。在.m中还为persistentContainer写了getter
然后可以找到.xcdatamodeld文件,开始添加模型,在我的demo中添加了Person和Card两个模型,详情如下
Person中添加了两个属性name和age,类型分别为String和int32_t,card中也添加了两个属性color和size,类型均为NSObject(截图时我想尝试下Decimal数据类型尝试了下,后来改成Transformable,即NSObject类型)
需要注意的是一般我们都会选择手动生成继承自NSManagedObject的Person和Card的类方便我们查看等,而.xcdatamodeld文件在编译时会自动生成同样的Person和Card类,所以我们可以选择禁用模型的自动生成功能,如下图所示,我们可以选择模型,然后找到Class中Codegen将其改成Manul/None,即可禁止其自动生成模型子类。
然后我们还可以在文件中设置两个模型的关系,如下图所示,我们可以点击relationship中的+,添加关系,
需要注意的是添加单相关系的时候inverse是不会有值的,只有双向关系,或者有其他模型引用这个模型时才会有值。
其中relationship中的值即为生成类时系统会自动生成的属性,可以看到选择属性时右方可以选择ToOne或者ToMany,即一个Person模型可以对应几个Card,如果选择一对多
那么系统会自动生成一个集合属性,并且会生成相关的添加值的方法。然后我们可以按照下图选择生成Person和Card的类文件。
生成后项目文件如下所示
最后附上使用过程
系统添加coredata后会在Appdelegate类中自动添加一个persistentContainer属性,和一个saveContext方法。在.m中还为persistentContainer写了getter
- (NSPersistentContainer *)persistentContainer { // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it. @synchronized (self) { if (_persistentContainer == nil) { _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"XWMyCoreDataDemo"]; [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { if (error != nil) { NSLog(@"Unresolved error %@, %@", error, error.userInfo); abort(); } }]; } } return _persistentContainer; }
- (void)saveContext { NSManagedObjectContext *context = self.persistentContainer.viewContext; NSError *error = nil; if ([context hasChanges] && ![context 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(); } }需要特别注意的是两个方法实现中都有abort()函数,这个函数会造成程序崩溃,如果是开发模式,可以利于调试,如果是已上架模式最好移除这个函数,以免影响用户体验。
然后可以找到.xcdatamodeld文件,开始添加模型,在我的demo中添加了Person和Card两个模型,详情如下
Person中添加了两个属性name和age,类型分别为String和int32_t,card中也添加了两个属性color和size,类型均为NSObject(截图时我想尝试下Decimal数据类型尝试了下,后来改成Transformable,即NSObject类型)
需要注意的是一般我们都会选择手动生成继承自NSManagedObject的Person和Card的类方便我们查看等,而.xcdatamodeld文件在编译时会自动生成同样的Person和Card类,所以我们可以选择禁用模型的自动生成功能,如下图所示,我们可以选择模型,然后找到Class中Codegen将其改成Manul/None,即可禁止其自动生成模型子类。
然后我们还可以在文件中设置两个模型的关系,如下图所示,我们可以点击relationship中的+,添加关系,
需要注意的是添加单相关系的时候inverse是不会有值的,只有双向关系,或者有其他模型引用这个模型时才会有值。
其中relationship中的值即为生成类时系统会自动生成的属性,可以看到选择属性时右方可以选择ToOne或者ToMany,即一个Person模型可以对应几个Card,如果选择一对多
那么系统会自动生成一个集合属性,并且会生成相关的添加值的方法。然后我们可以按照下图选择生成Person和Card的类文件。
生成后项目文件如下所示
#import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @class Card; NS_ASSUME_NONNULL_BEGIN @interface Person : NSManagedObject @end NS_ASSUME_NONNULL_END #import "Person+CoreDataProperties.h"
#import "Person+CoreDataClass.h" #import "Card+CoreDataClass.h" @implementation Person @end
#import "Person+CoreDataClass.h" NS_ASSUME_NONNULL_BEGIN @interface Person (CoreDataProperties) + (NSFetchRequest<Person *> *)fetchRequest; @property (nullable, nonatomic, copy) NSString *name; @property (nonatomic) int32_t age; @property (nullable, nonatomic, retain) NSSet<Card *> *cards; @end
@interface Person (CoreDataGeneratedAccessors) //用于添加属性值的方法 - (void)addCardsObject:(Card *)value; - (void)removeCardsObject:(Card *)value; - (void)addCards:(NSSet<Card *> *)values; - (void)removeCards:(NSSet<Card *> *)values; @end NS_ASSUME_NONNULL_END #import "Person+CoreDataProperties.h"
@implementation Person (CoreDataProperties) + (NSFetchRequest<Person *> *)fetchRequest { return [[NSFetchRequest alloc] initWithEntityName:@"Person"]; } @dynamic name; @dynamic age; @dynamic cards; @end
#import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @class NSObject, Person; NS_ASSUME_NONNULL_BEGIN @interface Card : NSManagedObject @end NS_ASSUME_NONNULL_END #import "Card+CoreDataProperties.h"
#import "Card+CoreDataClass.h" #import "Person+CoreDataClass.h" @implementation Card @end
#import "Card+CoreDataClass.h" NS_ASSUME_NONNULL_BEGIN @interface Card (CoreDataProperties) + (NSFetchRequest<Card *> *)fetchRequest; @property (nullable, nonatomic, retain) NSObject *color; @property (nullable, nonatomic, copy) NSObject *size; @property (nullable, nonatomic, retain) Person *owner; @end
NS_ASSUME_NONNULL_END
#import "Card+CoreDataProperties.h" @implementation Card (CoreDataProperties) + (NSFetchRequest<Card *> *)fetchRequest { return [[NSFetchRequest alloc] initWithEntityName:@"Card"]; } @dynamic color; @dynamic size; @dynamic owner; @end可以发现模型生成的类都是继承自NSManagedObject,且相关属性都使用了@dynamic,也就是系统不会自动生成getter和setter,且在使用的过程中可以发现如果使用alloc初始化模型的时候是会报错的!
最后附上使用过程
#import "ViewController.h" #import "Card+CoreDataClass.h" #import "Person+CoreDataClass.h" #import "AppDelegate.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate; NSManagedObjectContext *context = delegate.persistentContainer.viewContext; //context常用 //创建一个Person模型对象 模型对象初始化必须有一个NSEntityDescription Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context]; p.name = @"Will"; p.age = 24; //创建一个Card模型对象 Card *card = [NSEntityDescription insertNewObjectForEntityForName:@"Card" inManagedObjectContext:context]; card.color = [UIColor redColor]; card.size = NSStringFromCGSize(CGSizeMake(70, 100)); [p addCardsObject:card]; NSError *error = nil; [context save:&error]; //保存操作 if (error) { NSLog(@"%@",error.userInfo); } /** 下面是查询操作,可以删除上面代码,重新运行 */ // NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; //初始化一个Person的查询请求 NSFetchRequest *request = [Person fetchRequest]; //系统自动生成了获取查询请求的方法 NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//为请求设置排序实例 request.sortDescriptors = @[descriptor]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '?il?'"];//为请求设置过滤条件 request.predicate = predicate; NSArray *array = [context executeFetchRequest:request error:&error]; //根据请求执行查找,结果存于一个数组。 for (Person *p in array) { NSLog(@"%@,%d,%@",p.name,p.age,p.cards); } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end如果对sqlite熟悉的话,可以发现查找的工作很熟悉,就相当于数据库执行"select * from Person order by name where name like '?il?'"的操作,以前系统为我们提供的context查找操作是同步的(现在默认的查找操作默认的是异步的),所以当时如果查询操作是很耗时的话,会影响性能,当时的解决办法是进行异步查询操作
NSAsynchronousFetchRequest *request = [[NSAsynchronousFetchRequest alloc]initWithFetchRequest:[Person fetchRequest] completionBlock:^(NSAsynchronousFetchResult * _Nonnull result) { if (result) { NSLog(@"%@",result.finalResult); NSLog(@"%@",[NSThread currentThread]); NSLog(@"%@",@(context.concurrencyType)); } }]; [context executeRequest:request error:&error];但是不管是同步还是异步的查询操作都是在主线程进行的,如果想要放在子线程的话需要更改context的concurrencyType,因为concurrencyType是readonly,且没有找到相关设置方法,所以目前我采用的重新构建一个context。
NSManagedObjectContext *backContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [backContext setPersistentStoreCoordinator:context.persistentStoreCoordinator]; NSAsynchronousFetchRequest *request = [[NSAsynchronousFetchRequest alloc]initWithFetchRequest:[Person fetchRequest] completionBlock:^(NSAsynchronousFetchResult * _Nonnull result) { if (result) { NSLog(@"%@",result.finalResult); NSLog(@"%@",[NSThread currentThread]); NSLog(@"%@",@(context.concurrencyType)); } }]; [backContext executeRequest:request error:&error];如果想要删除存储的模型的话
NSFetchRequest *request = [Person fetchRequest]; NSArray *array = [context executeFetchRequest:request error:&error]; for (Person *p in array) { if ([p.name isEqualToString:@"will"]) { [context deleteObject:p]; [context save:&error]; } }很重要的一点是,每次进行操作后需要保存才能生效!
相关文章推荐
- ios开发中是CoreData的一些详细介绍。
- iOS应用开发视频教程笔记(十四)Core Data Demo
- [ios开发基础之 Core Data [1] ]Core Data数据持久性存储基础教程
- iOS Core Data的增删改查详细使用
- iOS教程:Core Data数据持久性存储基础教程
- iOS应用开发视频教程笔记(十四)Core Data Demo
- iOS基础教程:在建好的项目中加入CoreData[转]
- 转:ios coredata 教程 详解
- iOS教程:Core Data数据持久性存储基础教程
- iOS Swift教程 Core Data (一)Hello Core Data
- iOS教程:Core Data数据持久性存储基础教程
- IOS成长之路-CoreData详细介绍
- iOS教程:Core Data数据持久性存储基础教程
- iOS教程:Core Data数据持久性存储基础教程
- ios开发中是CoreData的一些详细介绍。
- ios开发中是CoreData的一些详细介绍。
- iOS App中数据管理框架Core Data的基本数据操作教程
- IOS CoreData 多表查询(上)
- IOS之分析网易新闻存储数据(CoreData的使用,增删改查)
- IOS数据管理工具CoreData入门之双向关系操作