CoreData使用笔记 之 增删改查

来源:互联网 发布:管家婆数据库搬移工具 编辑:程序博客网 时间:2024/04/24 06:38

用惯了FMDB,好多小伙伴问我为什么不用CoreData,说实话,习惯了一个技术如果没有太大的bug,想去换另外一个技术,心里一时接受不了,嘻嘻.....

废话不说了,先来说说coredata中常用的几个方法和类:

先来看一张图:


主要类介绍

1.托管对象---NSManagedObjectModel

  a.相当于实体,不过它包含 了实体间的关系。

  b.一个托管对象代表你想要保存到数据存储中的一个对象。这在概念上类似于SQL中的一条记录, 并且通常也包含一些域,这些域对应于你想要保存的对象的属性。

2.托管对象上下文---NSManagedObjectContext

   托管对象上下文类似于应用程序和数据存储之间的一块缓冲区。这块缓冲区包含所有未被写入数据存储的托管对象。你可以添加、删除、更改缓冲区内的托管对象。在很多时候,当你需要读、插入、删除对象时,你将会调用托管对象上下文的方法。

3.NSPersistentStoreCoordinator(持久化存储助理), 相当于数据库的连接器

  持久化存储协调器处理到数据存储的连接,并且包含一些底层信息,像用到数据存储的名字和位置。这个类通常被托管对象上下文用到。
4.NSFetchRequest(获取数据的请求) , 相当于查询语句
5.NSPredicate(相当于查询条件)
6.NSEntityDescription(实体结构)

7.数据存储

Core Data支持4中类型的数据存储:SQLiteStore, XMLStore, BinaryStore, InMemoryStore。

使用过程

1.在你可以读或写模型对象到当前数据存储之前,你需要实例化托管对象模型、托管对象上下文、持久化存储协调器。
托管对象模型由NSManagedObjectModel类的一个实例表示。在一个工程中我们只需要为所有的.xcdatamodeld文件实例化一个对象。
NSManagedObjectModel* managedObjectModel = [NSManagedObjectModel
        mergedModelFromBundles:nil];
mergedModelFromBundles: 搜索工程中所有的.xcdatamodeld文件,并加载所有的实体到一个NSManagedObjectModel  实例中。
这样托管对象模型知道所有当前工程中用到的托管对象的定义。
2.有了托管对象模型实例之后,我们就可以创建一个持久化协调器实例了。持久化协调器处理到数据存储的连接。大概是处理怎么把对象写到数据存储或怎么从数据存储读对象吧。
3.有了持久化协调器实例之后,我们需要提供一个数据存储给它管理。你可以通过发送addPersistentStoreWithType:configuration:URL:options:error:消息来实现。
4.最后一步就是实例化托管对象上下文。有了托管对象上下文,你就可以方便的管理对象了。

代码实现

1.创建一个sigleApplication项目,在创建过程中选择UserCoreData。
2.finish之后,我们会看到在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 *)applicationDocumentsDirectory;@end

在appdelegate.m中有

#import "AppDelegate.h"@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    // Override point for customization after application launch.    return YES;}- (void)applicationWillResignActive:(UIApplication *)application {    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.}- (void)applicationDidEnterBackground:(UIApplication *)application {    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.}- (void)applicationWillEnterForeground:(UIApplication *)application {    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.}- (void)applicationDidBecomeActive:(UIApplication *)application {    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.}- (void)applicationWillTerminate:(UIApplication *)application {    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.    // Saves changes in the application's managed object context before the application terminates.    [self saveContext];}#pragma mark - Core Data stack@synthesize managedObjectContext = _managedObjectContext;@synthesize managedObjectModel = _managedObjectModel;@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;- (NSURL *)applicationDocumentsDirectory {    // The directory the application uses to store the Core Data store file. This code uses a directory named "gg.TestCoreData" in the application's documents directory.    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}- (NSManagedObjectModel *)managedObjectModel {    // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.    if (_managedObjectModel != nil) {        return _managedObjectModel;    }    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestCoreData" withExtension:@"momd"];    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    return _managedObjectModel;}- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.    if (_persistentStoreCoordinator != nil) {        return _persistentStoreCoordinator;    }        // Create the coordinator and store        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestCoreData.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]) {        // Report any error we got.        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];        // Replace this 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();    }        return _persistentStoreCoordinator;}- (NSManagedObjectContext *)managedObjectContext {    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)    if (_managedObjectContext != nil) {        return _managedObjectContext;    }        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];    if (!coordinator) {        return nil;    }    _managedObjectContext = [[NSManagedObjectContext alloc] init];    [_managedObjectContext setPersistentStoreCoordinator:coordinator];    return _managedObjectContext;}#pragma mark - Core Data Saving support- (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();        }    }}@end

工程文件多了一个XX.xcdatamodeld这个带有后缀.xcdatamodeld文件,单击一下如:



1.如上图单击红色1 紧接着会在2的位置出现一个默认名字为Entity这个实体,双击它重命名User,然后单击红色3添加属性,在选择相应的字段的类型即可。
2.这个实体创建完了,换句话说,本地的保存"表"结构完了,给这个"表"对应一个实体:
在Xcode 菜单里 Editor->Create NSManagedObject SubClass...


单击Next,之后选择对应的实体,点击Next



之后点击Create,就可以窗机一个继承NSManagedObject的User代码实体。

user.h

#import <Foundation/Foundation.h>#import <CoreData/CoreData.h>@interface User : NSManagedObject@property (nonatomic, retain) NSString * name;@property (nonatomic, retain) NSNumber * age;@property (nonatomic, retain) NSString * sex;@end


user.m

#import "User.h"@implementation User@dynamic name;@dynamic age;@dynamic sex;@end

m文件里面已经告诉你不能自定义Setter 和 getter了。
上述代码是自动生成。

好了到了这里基本上我们把前面的准备工作已经做好了,接下来是对数据增删改改查了。


3.数据增删改查(viewcontroller.h文件什么都没有,主要是m文件中的)
#import "ViewController.h"#import "AppDelegate.h"#import "User.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];        AppDelegate *tmpDelegate = ((AppDelegate *)[UIApplication sharedApplication].delegate);         User *user = (User *)[NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:tmpDelegate.managedObjectContext];        //插入    NSInteger tmpIndex = arc4random()%100;        [user setName:[NSString stringWithFormat:@"cc-%ld",(long)tmpIndex]];    [user setAge:@13];    [user setSex:@"男"];        if ([tmpDelegate.managedObjectContext save:nil]) {        NSLog(@"Success");    };        //查询    NSFetchRequest *request = [[NSFetchRequest alloc] init];    NSEntityDescription *userEntity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:tmpDelegate.managedObjectContext];    [request setEntity:userEntity];        NSArray *tmpArr = [tmpDelegate.managedObjectContext executeFetchRequest:request error:nil];        for (User *tmpUser in tmpArr)    {        NSLog(@"%@ <----> %@",tmpUser.name,tmpUser.age);    }        //修改    NSPredicate  *predicate = [NSPredicate predicateWithFormat:@"name==%@",@"cc-73"];    [request setPredicate:predicate];    NSArray *tmpModify = [tmpDelegate.managedObjectContext executeFetchRequest:request error:nil];    for (User *tmpUser in tmpModify)    {        tmpUser.age = @10000;    }        if ([tmpDelegate.managedObjectContext save:nil]) {        NSLog(@"Success");    };    //查询    [request setPredicate:nil];    tmpArr = [tmpDelegate.managedObjectContext executeFetchRequest:request error:nil];    for (User *tmpUser in tmpArr)    {        NSLog(@"%@ <----> %@",tmpUser.name,tmpUser.age);    }        //删除    [request setPredicate:predicate];    tmpModify = [tmpDelegate.managedObjectContext executeFetchRequest:request error:nil];    for (User *tmpUser in tmpModify)    {        [tmpDelegate.managedObjectContext deleteObject:tmpUser];    }        if ([tmpDelegate.managedObjectContext save:nil]) {        NSLog(@"Success");    };        //查询    [request setPredicate:nil];    tmpArr = [tmpDelegate.managedObjectContext executeFetchRequest:request error:nil];    for (User *tmpUser in tmpArr)    {        NSLog(@"%@ <----> %@",tmpUser.name,tmpUser.age);    }    }- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end

结合上面的几个类的介绍相信小伙伴都能看得懂,我就不多说了。


线程安全


这个文件肯定存在线程安全问题,如果存在无非就是读和写的线程,这里我说一下思路:
写和写是不可以的、读写是不可以的、读读是可以的。
具体实现的伪代码可以参见我的另外一篇播客:关于多线程读和多线程写

demo下载





0 0
原创粉丝点击