前面详细讲解了 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 expressionForeva luatedObject];
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)我们创建了一个全局模型 moModel;
2)并在其中创建一个名为 Run 的 Entity,这个 Entity 对应的 ManagedObject 类名为 Run(很快我们将创建这样一个类);
3)给 Run Entity 添加了两个必须的 Property:date 和 processID,分别表示运行时间以及进程 ID;并设置默认的进程 ID 为 -1;
4)给 processID 特性设置检验条件:必须大于 0;
5)给模型设置本地化描述词典;
本地化描述提供对 Entity,Property,Error信息等的便于理解的描述,其可用的键值对如下表:
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 resourceva luesForKeys:[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 = [[NSManagedObje