上海网站制作技术,友情链接只有链接,做数学题赚钱的网站,wordpress微信图片深入浅出Cocoa之Core Data#xff08;2#xff09;- 手动编写代码 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议前面详细讲解了 Core Data 的框架以及设计的类#xff0c;下面我们来讲解一个完全手动编写代码使用这些类的示…深入浅出Cocoa之Core Data2- 手动编写代码 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议 前面详细讲解了 Core Data 的框架以及设计的类下面我们来讲解一个完全手动编写代码使用这些类的示例这个例子来自苹果官方示例。在这个例子里面我们打算做这样一件事情记录程序运行记录时间与 process id并保存到xml文件中。我们使用 Core Data 来做这个事情。 示例代码下载点击这里 一新建工程 建立一个新的 Mac command-line tool application 工程命名为 CoreDataTutorial。为支持垃圾主动回收机制点击项目名称在右边的 Build Setting 中查找 garbage 关键字将找到的 Objective-C Garbage Collection 设置为 Required [-fobj-gc-only]。并将 main.m 中 的 main() 方法修改为如下 int main (int argc, const char * argv[]){ NSLog( Core Data Tutorial );// Enable GC// objc_startCollectorThread();return 0;} 二创建并设置模型类 在 main() 之前添加如下方法 NSManagedObjectModel *managedObjectModel(){static NSManagedObjectModel *moModel nil;if (moModel ! nil) {return moModel; } moModel [[NSManagedObjectModel alloc] init];// Create the entity// NSEntityDescription *runEntity [[NSEntityDescription alloc] init]; [runEntity setName:Run]; [runEntity setManagedObjectClassName:Run]; [moModel setEntities:[NSArray arrayWithObject:runEntity]];// Add the Attributes// NSAttributeDescription *dateAttribute [[NSAttributeDescription alloc] init]; [dateAttribute setName:date]; [dateAttribute setAttributeType:NSDateAttributeType]; [dateAttribute setOptional:NO]; NSAttributeDescription *idAttribute [[NSAttributeDescription alloc] init]; [idAttribute setName:processID]; [idAttribute setAttributeType:NSInteger32AttributeType]; [idAttribute setOptional:NO]; [idAttribute setDefaultValue:[NSNumber numberWithInteger:-1]];// Create the validation predicate for the process ID.// The following code is equivalent to validationPredicate [NSPredicate predicateWithFormat:SELF 0]// NSExpression *lhs [NSExpression expressionForEvaluatedObject]; NSExpression *rhs [NSExpression expressionForConstantValue:[NSNumber numberWithInteger:0]]; NSPredicate *validationPredicate [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:rhs modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:0]; NSString *validationWarning Process ID 1; [idAttribute setValidationPredicates:[NSArray arrayWithObject:validationPredicate] withValidationWarnings:[NSArray arrayWithObject:validationWarning]];// set the properties for the entity.// NSArray *properties [NSArray arrayWithObjects: dateAttribute, idAttribute, nil]; [runEntity setProperties:properties];// Add a Localization Dictionary// NSMutableDictionary *localizationDictionary [NSMutableDictionary dictionary]; [localizationDictionary setObject:Date forKey:Property/date/Entity/Run]; [localizationDictionary setObject:Process ID forKey:Property/processID/Entity/Run]; [localizationDictionary setObject:Process ID must not be less than 1 forKey:ErrorString/Process ID 1]; [moModel setLocalizationDictionary:localizationDictionary];return moModel;} 在上面的代码中 1我们创建了一个全局模型 moModel2并在其中创建一个名为 Run 的 Entity这个 Entity 对应的 ManagedObject 类名为 Run很快我们将创建这样一个类3给 Run Entity 添加了两个必须的 Propertydate 和 processID分别表示运行时间以及进程 ID并设置默认的进程 ID 为 -14给 processID 特性设置检验条件必须大于 05给模型设置本地化描述词典 本地化描述提供对 EntityPropertyError信息等的便于理解的描述其可用的键值对如下表 Key Value Entity/NonLocalizedEntityName LocalizedEntityName Property/NonLocalizedPropertyName/Entity/EntityName LocalizedPropertyName Property/NonLocalizedPropertyName LocalizedPropertyName ErrorString/NonLocalizedErrorString LocalizedErrorString 三创建并设置运行时类和对象 由于要用到存储功能所以我们必须定义持久化数据的存储路径。我们在 main() 之前添加如下方法设置存储路径 NSURL *applicationLogDirectory(){ NSString *LOG_DIRECTORY CoreDataTutorial;static NSURL *ald nil;if (ald nil) { NSFileManager *fileManager [[NSFileManager alloc] init]; NSError *error nil; NSURL *libraryURL [fileManager URLForDirectory:NSLibraryDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:error];if (libraryURL nil) { NSLog(Could not access Library directory\n%, [error localizedDescription]); }else { ald [libraryURL URLByAppendingPathComponent:Logs]; ald [ald URLByAppendingPathComponent:LOG_DIRECTORY]; NSLog( log path %, [ald path]); NSDictionary *properties [ald resourceValuesForKeys:[NSArray arrayWithObject:NSURLIsDirectoryKey] error:error];if (properties nil) {if (![fileManager createDirectoryAtPath:[ald path] withIntermediateDirectories:YES attributes:nil error:error]) { NSLog(Could not create directory %\n%, [ald path], [error localizedDescription]); ald nil; } } } }return ald;} 在上面的代码中我们将持久化数据文件保存到路径/Users/kesalin/Library/Logs/CoreDataTutorial 下。 下面我们来创建运行时对象ManagedObjectContext 和 PersistentStoreCoordinator。 NSManagedObjectContext *managedObjectContext(){static NSManagedObjectContext *moContext nil;if (moContext ! nil) {return moContext; } moContext [[NSManagedObjectContext alloc] init];// Create a persistent store coordinator, then set the coordinator for the context.// NSManagedObjectModel *moModel managedObjectModel(); NSPersistentStoreCoordinator *coordinator [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:moModel]; [moContext setPersistentStoreCoordinator: coordinator];// Create a new persistent store of the appropriate type. // NSString *STORE_TYPE NSXMLStoreType; NSString *STORE_FILENAME CoreDataTutorial.xml; NSError *error nil; NSURL *url [applicationLogDirectory() URLByAppendingPathComponent:STORE_FILENAME]; NSPersistentStore *newStore [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:error];if (newStore nil) { NSLog(Store Configuration Failure\n%, ([error localizedDescription] ! nil) ? [error localizedDescription] : Unknown Error); }return moContext;} 在上面的代码中 1我们创建了一个全局 ManagedObjectContext 对象 moContext2并在设置其 persistent store coordinator存储类型为 xml保存文件名为CoreDataTutorial.xml并将其放到前面定义的存储路径下。 好至此万事具备只欠 ManagedObject 了下面我们就来定义这个数据对象类。向工程添加 Core Data-NSManagedObject subclass 的类名为 Run (模型中 Entity 定义的类名) 。 Run.h #import CoreData/NSManagedObject.hinterface Run : NSManagedObject{ NSInteger processID;}property (retain) NSDate *date;property (retain) NSDate *primitiveDate;property NSInteger processID;end Run.m //// Run.m// CoreDataTutorial//// Created by kesalin on 8/29/11.// Copyright 2011 kesalingmail.com. All rights reserved.//#import Run.himplementation Rundynamic date;dynamic primitiveDate;- (void) awakeFromInsert{ [super awakeFromInsert]; self.primitiveDate [NSDate date];}#pragma mark -#pragma mark Getter and setter- (NSInteger)processID { [self willAccessValueForKey:processID]; NSInteger pid processID; [self didAccessValueForKey:processID];return pid;}- (void)setProcessID:(NSInteger)newProcessID{ [self willChangeValueForKey:processID]; processID newProcessID; [self didChangeValueForKey:processID];}// Implement a setNilValueForKey: method. If the key is “processID” then set processID to 0.//- (void)setNilValueForKey:(NSString *)key {if ([key isEqualToString:processID]) { self.processID 0; }else { [super setNilValueForKey:key]; }}end 注意 1这个类中的 date 和 primitiveDate 的访问属性为 dynamic这表明在运行期会动态生成对应的 setter 和 getter2在这里我们演示了如何正确地手动实现 processID 的 setter 和 getter为了让 ManagedObjecContext 能够检测 processID的变化以及自动支持 undo/redo我们需要在访问和更改数据对象时告之系统will/didAccessValueForKey 以及 will/didChangeValueForKey 就是起这个作用的。3当我们设置 nil 给数据对象 processID 时我们可以在 setNilValueForKey 捕获这个情况并将 processID 置 04当数据对象被插入到 ManagedObjectContext 时我们在 awakeFromInsert 将时间设置为当前时间。 四创建或读取数据对象设置其值保存 好至此真正的万事具备我们可以创建或从持久化文件中读取数据对象设置其值并将其保存到持久化文件中。本例中持久化文件为 xml 文件。修改 main() 中代码如下 int main (int argc, const char * argv[]){ NSLog( Core Data Tutorial );// Enable GC// objc_startCollectorThread(); NSError *error nil; NSManagedObjectModel *moModel managedObjectModel(); NSLog(The managed object model is defined as follows:\n%, moModel);if (applicationLogDirectory() nil) { exit(1); } NSManagedObjectContext *moContext managedObjectContext();// Create an Instance of the Run Entity// NSEntityDescription *runEntity [[moModel entitiesByName] objectForKey:Run]; Run *run [[Run alloc] initWithEntity:runEntity insertIntoManagedObjectContext:moContext]; NSProcessInfo *processInfo [NSProcessInfo processInfo]; run.processID [processInfo processIdentifier];if (![moContext save: error]) { NSLog(Error while saving\n%, ([error localizedDescription] ! nil) ? [error localizedDescription] : Unknown Error); exit(1); }// Fetching Run Objects// NSFetchRequest *request [[NSFetchRequest alloc] init]; [request setEntity:runEntity]; NSSortDescriptor *sortDescriptor [[NSSortDescriptor alloc] initWithKey:date ascending:YES]; [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; error nil; NSArray *array [moContext executeFetchRequest:request error:error];if ((error ! nil) || (array nil)) { NSLog(Error while fetching\n%, ([error localizedDescription] ! nil) ? [error localizedDescription] : Unknown Error); exit(1); }// Display the Results// NSDateFormatter *formatter [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterMediumStyle]; NSLog(% run history:, [processInfo processName]);for (run in array) { NSLog(On % as process ID %ld, [formatter stringForObjectValue:run.date], run.processID); }return 0;} 在上面的代码中 1我们先获得全局的 NSManagedObjectModel 和 NSManagedObjectContext 对象moModel 和 moContext2并创建一个Run Entity设置其 Property processID 为当前进程的 ID3将该数据对象保存到持久化文件中[moContext save: error]。我们无需与 PersistentStoreCoordinator 打交道只需要给 ManagedObjectContext 发送 save 消息即可NSManagedObjectContext 会透明地在后面处理对持久化数据文件的读写4然后我们创建一个 FetchRequest 来查询持久化数据文件中保存的数据记录并将结果按照日期升序排列。查询操作也是由 ManagedObjectContext 来处理的[moContext executeFetchRequest:request error:error];5将查询结果打印输出 大功告成编译运行我们可以得到如下显示 CoreDataTutorial[992:903] On 2011-9-3 下午09:41:56 as process ID 9402011-09-03 21:42:47.557 CoreDataTutorial[992:903] On 2011-9-3 下午09:42:16 as process ID 9552011-09-03 21:42:47.558 CoreDataTutorial[992:903] On 2011-9-3 下午09:42:20 as process ID 9652011-09-03 21:42:47.558 CoreDataTutorial[992:903] On 2011-9-3 下午09:42:24 as process ID 9782011-09-03 21:42:47.559 CoreDataTutorial[992:903] On 2011-9-3 下午09:42:47 as process ID 992 通过这个例子我们可以更好理解 Core Data 的运作机制。在 Core Data 中我们最常用的就是 ManagedObjectContext它几乎参与对数据对象的所有操作包括对 undo/redo 的支持而 Entity 对应的运行时类为 ManagedObject我们可以理解为抽象数据结构 Entity 在内存中由 ManagedObject 来体现而 Perproty 数据类型在内存中则由 ManagedObject 类的成员属性来体现。一般我们不需要与 PersistentStoreCoordinator 打交道对数据文件的读写操作都由 ManagedObjectContext 为我们代劳了。转载于:https://www.cnblogs.com/kesalin/archive/2011/09/03/core_data_tutorial_02.html