目录:
一、使用CoreData存储基本数据
二、使用CoreData存储自定义类型数据
简单介绍CoreData
CoreData是iOS编程中使用持久化数据存储的一种方式,我们知道CoreData并不是数据库本身,而是Apple提供的对象持久化技术——Object Persistent technology。CoreData框架为我们的数据变更、管理、对象存储、读取和恢复提供了支持。下面我们来尝试创建一个简单的CoreData Project。
操作
1. 打开x-code,为你的project添加一个新的文件,选择Core Data——>Data Nodel 。如下图:
2. 点击Next,命名后确认就会生成一个 .xcdatamodeld文件
3. 点击该文件就会出现如下界面,我们可以在该界面设置我们需要保存的字段及其类型
点击图片中的左下角 Add Entity按钮即可生成一个新的Entity,此时你就可以在你的Attribute那里添加字段并且设置类型。
我们这次给他添加了name与year,这两个是我们后面需要保存的值。
4. 点击editor,选择create NSManagedObject Subclass,你会发现他自动帮我们生成了对应的文件,方便我们后期对这些字段进行操作。
打开AppDelegate.h文件,你会发现这里面多了三个属性:
<span style="font-size:14px;">#import <UIKit/UIKit.h> #import <CoreData/CoreData.h> @class ViewController; @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong,nonatomic)ViewController *viewController; //上下文对象 @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; //数据模型对象 @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; //持久性存储区 @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; - (void)saveContext; - (NSURL *)applicationDocumentsDirectory; //初始化CoreData使用的数据库 -(NSPersistentStoreCoordinator *)persistentStoreCoordinator; //managedObjectModel的初始化赋值方法 -(NSManagedObjectModel *)managedObjectModel; //managedObjectContext的初始化赋值方法 -(NSManagedObjectContext *)managedObjectContext; @end </span>
这是x-code为我们生成好了的模板,我们在需要保存数据的地方调用他们进行操作即可。
下面我们开始操作:
viewController.h
<span style="font-size:14px;">#import <UIKit/UIKit.h> #import "AppDelegate.h" @interface ViewController : UIViewController @property (strong,nonatomic)AppDelegate *myDelegate; @property (strong,nonatomic)NSMutableArray *entries_array; @end </span>
AppDelegate *mydelegate可以让我们调用AppDelegate中新增的三个属性
ViewController.m
<span style="font-size:14px;">#import "ViewController.h" #import "Entity.h" @interface ViewController () @end @implementation ViewController @synthesize myDelegate ; @synthesize entries_array ; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //获取当前应用的委托(UIApplication sharedApplication为整个应用的上下文) self.myDelegate = [[UIApplication sharedApplication]delegate]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)saveData{ Entity *entity = [NSEntityDescription insertNewObjectForEntityForName:@"Entity" inManagedObjectContext:self.myDelegate.managedObjectContext]; NSNumber *number = [[NSNumber alloc]initWithInt:3]; [entity setName:@"Lion"]; [entity setYear:number]; NSError *error; if(![NSEntityDescription entityForName:@"Entity" inManagedObjectContext:self.myDelegate.managedObjectContext]){ NSLog(@"Error:%@,%@",error,[error userInfo]); }else{ NSLog(@"Save Success!"); } } -(void)queryData{ //设置请求实体 NSFetchRequest *request = [[NSFetchRequest alloc]init]; [request setEntity:[NSEntityDescription entityForName:@"Entity" inManagedObjectContext:self.myDelegate.managedObjectContext]]; //指定对结果的排序 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"year" ascending:NO]; NSArray *sortArray = [[NSArray alloc]initWithObjects:sortDescriptor, nil]; [request setSortDescriptors:sortArray]; //执行请求 NSError *error = nil; NSMutableArray *fetchResultArray = [[self.myDelegate.managedObjectContext executeFetchRequest:request error:&error]mutableCopy]; //判断,如果获取到的数据为空: if(fetchResultArray == nil){ NSLog(@"Error:%@,%@",error,[error userInfo]); } self.entries_array = fetchResultArray; NSLog(@"The count of the Data:%lu",[self.entries_array count]); for(Entity *entity in self.entries_array){ NSLog(@"leg: %@\nname: %@\n",entity.name,entity.year); } }</span>
二、使用CoreData存储自定义类型数据
当系统提供给我们的类型不能达到我们的使用要求时怎么办?比如我们想要在CoreData存储一个自定义类的对象可不可以呢?答案是可以的。
这时候你就会注意到在选择属性的时候会发现最后一行有一个Transformable类型,下面我们就会用上他。
我们建立一个简单的类叫做“Cat”,设置两个属性,一个是leg(int),一个name(NSString)(具体过程省略)
注意右边Name的填值。
现在根据我们的模型来生成数据模型,并且创建用于转换Cat的类,继承自NSValueTransform,注意这个转换类的名字要跟上面Name的名字一致
打开Cattransformer.m 要实现4个必须实现的方法:
<span style="font-size:14px;">//允许转换 +(BOOL)allowsReverseTransformation{ return YES; } //转换成什么类型 +(Class)transformedValueClass{ return [NSData class]; } //返回转换后的对象 -(id)transformedValue:(id)value{ Cat *cat = (Cat *)value; //将对象转换成NSData NSData *dataFromCat = [[NSData alloc]initWithBytes:(__bridge const void *)(cat) length:sizeof(cat)]; return dataFromCat; } //重新生成源对象 -(id)reverseTransformedValue:(id)value{ NSData *data = (NSData *)value; Cat *cat = [[Cat alloc]init]; [data getBytes:(__bridge void *)(cat) length:sizeof(cat)]; return cat; } </span>
到这里其实已经很明白了,整个过程与上面的存储并无大异,之时我们使用了NSData作为中间转换的值。
打开ViewController.m文件,在原来saveData方法里面插入:
<span style="font-size:14px;">Cat *cat = [[Cat alloc]init]; cat.leg = 4; cat.name = @"Holle"; [entity setCat:cat];</span>
就可以实现存储了。
至此,简单的Demo就算是完成了,需要注意的是在我们编译成功之后想要更改Entity中的字段,除了需要更改.xcdatamodeld文件以外,你还需要手动更改Entity.h与Entity.m文件,而不能像之前那样让他们自动生成,此时点击运行还是会发生错误,这时候需要注意,一是你的命名是否错误,其次可能是之前的旧的数据库文件现在需要存储的数据无法对应,你需要将模拟器上的工程删除然后重新运行即可。