前端之家收集整理的这篇文章主要介绍了
Core Data,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
- 我们点击“Create a new Xcode project”来开始我们的Core Data程序工程吧!
-
- 屏幕快照 2009-09-01 下午12.06.52
-
- 在这里,XCode已经给我们准备好了一个几乎可以直接去用的程序模板,直接选择“基于导航的应用程序”,然后记得点选“Use Core Data for storage”
-
- 屏幕快照 2009-09-01 下午12.14.03
-
- 建立好的程序名为XCDtest01,我们尝试编译运行,看看得到的程序是什么样的:
-
- 屏幕快照 2009-09-01 下午12.16.47
-
- 基本上来说,这个程序把什么都给我们弄好了,一个程序,在点击添加按钮之后添加现在的时间标签,如果点击“Edit”编辑按钮,就进入编辑模式,可以删除任意条信息。
-
- 如果点开xcdatamodel文件,我们可以看到,其中的实体为Event,有一个参数,名为“时间标签”。也就是说,如果我们想对这个列表视图中的数据作更改,只需要适当更改这个实体的参数,并配置- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 代理条目就可以显示适当的内容了。
-
- 屏幕快照 2009-09-01 下午12.20.19
-
- 这个预置程序与我们之前讨论的程序不同的,在于这个程序中并没有配置一个可变数组(NSMutableArray)来作数据副本,以达到高速存储的目的。因为Core Data在向磁盘和内存操作,NSMutableArray是内存操作,速度上比较有优势。但是我们有的这个小程序太小了,再者苹果有可能认为那种方法是非标准的。所以在这里才没有那么作
-
- NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = [[managedObject valueForKey:@"timeStamp"] description];
-
- 在这个程序的cell配置代理里面,仅仅是从“获取操作控制器”中得到了“被管理对象”,然后再读取其中的内容到cell的text中。
-
- 希望大家也使用这个模板,自己创建一个Core Data程序,然后简单的理解一下代码。下次我们聊只使用基于Window的程序模板+Core Data来创建程序
- CoreData实例分析学习(1)转自 http://c.gzl.name/archives/393
-
- 屏幕快照 2009-08-26 下午04.05.29
-
- Core Data是个好东西,在数据储存操作上速度快,容易操作,是一种类似关系数据库的东西。但是有些不那么好学,那到底Core Data是怎么操作的呢?怎么用呢?怎么来编程呢?我们一起来学习吧,接下来使用苹果提供的实例程序Locations来作分析:
-
- >程序介绍:
-
- 右侧是改程序的截图,基本上来说就是通过使用Core Location来得到当时的位置,然后在点击“+”的时候记录下当时的经纬度。通过UITableViewController的功能来添加,编辑,删除等功能。整体程序使用Core Data来储存数据,实体(Entity)为一个位置,包括以下参数:1,时间(收集数据的时间)2,纬度,3,经度
-
- 首先我们看看该程序的AppDelegate.h
-
- @interface LocationsAppDelegate : NSObject
-
- {
-
- UIWindow *window;
-
- UINavigationController *navigationController; //导航栏
-
- //以下定义了Core Data的三个决定性组建,等后面m文件里面再多介绍
-
- NSPersistentStoreCoordinator *persistentStoreCoordinator;
-
- NSManagedObjectModel *managedObjectModel;
-
- NSManagedObjectContext *managedObjectContext;
-
- }
-
- @property (nonatomic,retain) IBOutlet UIWindow *window;
-
- @property (nonatomic,retain) UINavigationController *navigationController;
-
- - (IBAction)saveAction:sender; //这个没找到作用...根本就没用到IB
-
- //还记得吧,nonatomic是因为这个程序是单线程
-
- @property (nonatomic,retain,readonly) NSManagedObjectModel *managedObjectModel;
-
- @property (nonatomic,readonly) NSManagedObjectContext *managedObjectContext;
-
- @property (nonatomic,readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
-
- @property (nonatomic,readonly) NSString *applicationDocumentsDirectory; //程序文档目录是主要为了给NSPersistentStoreCoordinator找个存sqlite文件的地方
-
- @end
-
- 从上面的我们能看出来,该程序是通过一个根Core Data数据管理来管理整个程序的CoreData数据的,接下来看m文件也会对此作更多的理解。
-
- #import "LocationsAppDelegate.h"
-
- #import "RootViewController.h"
-
- @implementation LocationsAppDelegate
-
- @synthesize window;
-
- @synthesize navigationController;
-
- - (void)applicationDidFinishLaunching:(UIApplication *)application
-
- {
-
- //初始化根视图控制器,它是一个列表视图控制器
-
- RootViewController *rootViewController = [[RootViewController alloc]
-
- initWithStyle:UITableViewStylePlain];
-
- //通过下面的自定义getter得到CoreData的“被管理对象内容器”
-
- NSManagedObjectContext *context = [self managedObjectContext];
-
- if (!context)
-
- {
-
- // 如果getter出错,在这里来排错
-
- }
-
- rootViewController.managedObjectContext = context; //rootViewController有一个本地“被管理对象内容器”,在这里赋值过去
-
- UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
-
- self.navigationController = aNavigationController; //初始化导航栏,根视图为rootViewController,并指定该导航栏为程序导航栏
-
- [window addSubview:[navigationController view]];
-
- [window makeKeyAndVisible];
-
- //由于导航栏retain了根视图,所以在这里可以release掉它了
-
- [rootViewController release];
-
- //由于self已经retain了导航栏,所以导航栏可以release
-
- [aNavigationController release]; }
-
- //applicationWillTerminate: 在程序结束前,Core Data会保存任何对其的更改
-
- - (void)applicationWillTerminate:(UIApplication *)application
-
- {
-
- NSError *error;
-
- if (managedObjectContext != nil)
-
- {
-
- if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
-
- { // Handle the error. }
-
- }
-
- }
-
- //在得到点击事件后,保存更改
-
- - (IBAction)saveAction:(id)sender
-
- {
-
- NSError *error;
-
- if (![[self managedObjectContext] save:&error])
-
- { // Handle error }
-
- }
-
- //自定义的managedObjectContext的getter,它其实是真正在使用的时候的被操作对象
-
- - (NSManagedObjectContext *) managedObjectContext
-
- {
-
- //如果已经有这个对象,就直接返回,否则继续
-
- if (managedObjectContext != nil)
-
- { return managedObjectContext; }
-
- NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
-
- if (coordinator != nil)
-
- {
-
- managedObjectContext = [[NSManagedObjectContext alloc] init];
-
- [managedObjectContext setPersistentStoreCoordinator: coordinator];
-
- //这里可以看到,“内容管理器”和“数据一致性存储器”的关系,
-
- //managedObjectContext需要得到这个“数据一致性存储器”
-
- }
-
- return managedObjectContext;
-
- }
-
- //自定义的CoreData数据模板的getter,数据模板其实就是一个描述实体与实体的关系,类似于关系型数据库的关系描述文件
-
- - (NSManagedObjectModel *)managedObjectModel
-
- {
-
- if (managedObjectModel != nil)
-
- { return managedObjectModel; }
-
- managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
-
- //从本地所有xcdatamodel文件得到这个CoreData数据模板
-
- return managedObjectModel;
-
- }
-
- //自定义“数据一致性存储器” persistentStoreCoordinator的getter
-
- - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
-
- {
-
- if (persistentStoreCoordinator != nil)
-
- { return persistentStoreCoordinator; }
-
- //定义一个本地地址到NSURL,用来存储那个sqlite文件
-
- NSURL *storeUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"]];
-
- NSError *error;
-
- persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
-
- initWithManagedObjectModel: [self managedObjectModel]];
-
- //从这里可以看出,其实persistentStoreCoordinator需要的不过是一个
-
- //存储数据的位置,它是负责管理CoreData如何储存数据的
-
- if (![persistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:storeUrl options:nil error:&error])
-
- { // Handle the error.}
-
- return persistentStoreCoordinator;
-
- }
-
- //返回该程序的档案目录,用来简单使用
-
- - (NSString *)applicationDocumentsDirectory
-
- {
-
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
-
- NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
-
- return basePath;
-
- }
-
- - (void)dealloc
-
- {
-
- //释放内存
-
- [managedObjectContext release];
-
- [managedObjectModel release];
-
- [persistentStoreCoordinator release];
-
- [navigationController release];
-
- [window release];
-
- [super dealloc];
-
- } @end
-
- 从上面的程序主代理文件可以看出,CoreData的简单使用不过是通过三个组建。
-
- NSManagedObjectModel来描述实体与实体的关系,也就是类似于表和表的关系。
- NSManagedObjectContext来得到被储存内容的文件管理器,对数据作直接操作
- NSPersistentStoreCoordinator来管理数据的储存位置,储存方法(sqlite)
-
- 你对Core Data理解更多了么?
-
- 补一下“实体”的概念,实体也就是Entity,在打开xcdatamodel文件的时候,我们可以看到
-
- 屏幕快照 2009-08-26 下午05.08.29
-
- 在这里,这个实体叫“Event”,而实体的参数有“创建日期”,“纬度”,“经度”。也就是说,其实这个实体被使用后,我们可以这样理解,实体就是表名,而参数就是列名,然后整个实体就是一张表。当这个Model描述多个实体的关系的时候,就像是一个关系型数据库一样,虽然苹果说“不是!”
- CoreData实例分析学习(2)转自 http://c.gzl.name/archives/412
-
- 在我们分析了程序主代理文件(AppDelegate)之后,我们先来看看一对自动生成的文件Event.h/.m
-
- @interface Event : NSManagedObject
-
- {
-
- }
-
- @property (nonatomic,retain) NSDate *creationDate;
-
- @property (nonatomic,retain) NSNumber *latitude;
-
- @property (nonatomic,retain) NSNumber *longitude;
-
- @end
-
-
-
- #import "Event.h"
-
- @implementation Event
-
- @dynamic creationDate;
-
- @dynamic latitude;
-
- @dynamic longitude;
-
- @end
-
- 从上面我们能看出来,一个实体Event也就会被生成一个NSManagedObject(被管理对象),然后任何accessor和getter都是被动态生成的,我们其实完全不用操任何的心,只需要在xcdatamodel文件里面配置后,点击添加文件,添加NSManagedObject文件,就会看到自动感知的类对象,然后生成就可以了。
-
- 下面是根视图控制器,是一个列表视图(UITableViewController)
-
- #import <CoreLocation/CoreLocation.h>
-
- @interface RootViewController : UITableViewController <CLLocationManagerDelegate>
-
- {
-
- //看到是UITableViewController的子类,由于需要使用Core Location,
-
- //所以在后面履行其protocal
-
- NSMutableArray *eventsArray;
-
- NSManagedObjectContext *managedObjectContext; //这个被管理对象内容器就是我们真正对Core Data数据的操作对象
-
- CLLocationManager *locationManager; //用来得到地理位置的Core Location对象
-
- UIBarButtonItem *addButton; //右上角的添加键
-
- }
-
- @property (nonatomic,retain) NSMutableArray *eventsArray;
-
- @property (nonatomic,retain) NSManagedObjectContext *managedObjectContext;
-
- @property (nonatomic,retain) CLLocationManager *locationManager;
-
- @property (nonatomic,retain) UIBarButtonItem *addButton;
-
-
- - (void)addEvent;
-
- @end
-
-
- #import "RootViewController.h"
-
- #import "LocationsAppDelegate.h"
-
- #import "Event.h"
-
- @implementation RootViewController
-
- @synthesize eventsArray,managedObjectContext,addButton,locationManager;
-
- - (void)viewDidLoad
-
- {
-
- [super viewDidLoad];
-
- self.title = @"Locations"; //设置列表视图的标题
-
- self.navigationItem.leftBarButtonItem = self.editButtonItem; //导航栏左边的编辑按钮
-
- addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addEvent)]; //初始化添加按钮,
-
- addButton.enabled = NO; //在Core Location初始化之前将其关闭
-
- self.navigationItem.rightBarButtonItem = addButton; //把这个添加按钮添加到导航栏右侧
-
- // 启动CLocation
-
- [[self locationManager] startUpdatingLocation];
-
- //初始化一个“获取请求”到我们的实体“Event”
-
- NSFetchRequest *request = [[NSFetchRequest alloc] init];
-
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];
-
- [request setEntity:entity];
-
- // 将时间以建立时间排序,最新的在最上
-
- NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
-
- NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,nil];
-
- [request setSortDescriptors:sortDescriptors];
-
- [sortDescriptor release];
-
- [sortDescriptors release];
-
- // 执行“获取”操作,得到一个“可变数组”的拷贝
-
- NSError *error = nil;
-
- NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
-
- if (mutableFetchResults == nil)
-
- { //如果结果为空,在这作错误响应 }
-
- // 将得到的本地数组赋值到本类的全局数组,然后清理无用的对象
-
- [self setEventsArray:mutableFetchResults];
-
- [mutableFetchResults release];
-
- [request release];
-
- }
-
-
- - (void)viewDidUnload
-
- {
-
- // 当视图被卸载后,将以下指针置空
-
- self.eventsArray = nil;
-
- self.locationManager = nil;
-
- self.addButton = nil;
-
- }
-
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-
- { // 只有一个章节 return 1; }
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-
- {
-
- // 在数组里面有多少个对象,在列表视图就有多少行
-
- return [eventsArray count];
-
- }
-
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-
- // 一个“日期格式化器”(凑合明白就好...)用来以特定的格式创建得到的日期
-
- static NSDateFormatter *dateFormatter = nil;
-
- if (dateFormatter == nil)
-
- {
-
- dateFormatter = [[NSDateFormatter alloc] init];
-
- [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
-
- [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
-
- }
-
- static NSNumberFormatter *numberFormatter = nil;
-
- if (numberFormatter == nil)
-
- {
-
- numberFormatter = [[NSNumberFormatter alloc] init];
-
- [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
-
- [numberFormatter setMaximumFractionDigits:3];
-
- }
-
-
-
- static NSString *CellIdentifier = @"Cell";
-
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if (cell == nil)
-
- {
-
- cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
-
- UITableViewCellStyleSubtitle;
-
- }
-
- // 从数组中得到这个Event对象
-
- Event *event = (Event *)[eventsArray objectAtIndex:indexPath.row];
-
- cell.textLabel.text = [dateFormatter stringFromDate:[event creationDate]];
-
- NSString *string = [NSString stringWithFormat:@"%@,%@",[numberFormatter stringFromNumber:[event latitude]],[numberFormatter stringFromNumber:[event longitude]]];
-
- cell.detailTextLabel.text = string;
-
- return cell;
-
- }
-
- - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
-
- {
-
- if (editingStyle == UITableViewCellEditingStyleDelete)
-
- { // 删除被惯例对象在索引路径(index path)
-
- NSManagedObject *eventToDelete = [eventsArray objectAtIndex:indexPath.row];
-
- [managedObjectContext deleteObject:eventToDelete];
-
- // 更新数组和列表视图
-
- [eventsArray removeObjectAtIndex:indexPath.row];
-
- [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
-
- // 提交更改到Core Data
-
- NSError *error;
-
- if (![managedObjectContext save:&error])
-
- { // Handle the error. }
-
- }
-
- }
-
- - (void)addEvent
-
- {
-
- //如果得不到位置,就返回.
-
- CLLocation *location = [locationManager location];
-
- if (!location)
-
- { return; }
-
- //建立一个Event实体对象
-
- Event *event = (Event *)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectContext];
-
- //得到经纬度,然后赋值到event对象去
-
- CLLocationCoordinate2D coordinate = [location coordinate];
-
- [event setLatitude:[NSNumber numberWithDouble:coordinate.latitude]];
-
- [event setLongitude:[NSNumber numberWithDouble:coordinate.longitude]];
-
- // 实例里面并没有使用CL的时间标签,因为在模拟器中会是一样的
-
- // [event setCreationDate:[location timestamp]];
-
- [event setCreationDate:[NSDate date]];
-
- //所以现在使用的是现在的时间,而不是得到位置的时候的时间
-
- // 保存更改
-
- NSError *error;
-
- if (![managedObjectContext save:&error])
-
- { // Handle the error. }
-
- // 将新Event放到最上面,所以添加到0的位置
-
- // 然后滚动列表视图到最上面,如果没有那么多的数据是看不出来区别的
-
- [eventsArray insertObject:event atIndex:0];
-
- NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
-
- [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
-
- [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
-
- }
-
- - (CLLocationManager *)locationManager
-
- {
-
- //自定义的CLocation的getter,方便初始化
-
- if (locationManager != nil)
-
- { return locationManager; }
-
- //初始化CL对象,然后设置精准度,然后将代理对象设为本地
-
- locationManager = [[CLLocationManager alloc] init];
-
- [locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
-
- [locationManager setDelegate:self]; return locationManager;
-
- }
-
- //CLocation的一个代理方法,如果成功就开启右侧添加按钮
-
- - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
-
- {
-
- addButton.enabled = YES;
-
- }
-
- //CLocation的一个代理方法,如果失败了就关闭(disable)右侧添加按钮
-
- - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
-
- {
-
- addButton.enabled = NO;
-
- }
-
- - (void)dealloc
-
- {
-
- //释放对象
-
- [managedObjectContext release];
-
- [eventsArray release];
-
- [locationManager release];
-
- [addButton release];
-
- [super dealloc];
-
- }
-
- @end
-
- 从上面的源代码,我们可以看出,
- 1,在这里数据并不是每次都由NSManagedContext对象得到,而是由一个数组得出。
- 2,数组是一个可变数组,由第一次载入的视图的时候从NSManagedContext中得到
- 3,从NSManagedContext对象中得到数据需要使用NSFetchRequest来初始化一个“获取”
- 4,每次获得新的数据的时候,同时保存到数组和NSManagedContext中,添加后需要对更改进行提交