一、基础概念深入 1.NSManagedObjectContext 被管理数据上下文就像便笺簿 当从数据持久层获取数据时,相当于把这些临时的数据拷贝写在便笺簿上,然后就可以随心所欲的修改这些值。 通过上下文,可以对数据记录NSManagedObject进行添加删除更改,记录更改后支持撤销和重做。 除非你保存这些数据变化,否则持久层的东西是不会变化。 通常我们将 controller 类或其子类与 Managed Object Context NSManagedObjectContext绑定,这样就方便我们动态地生成,获取数据对象等。 常用的方法:
2.NSManagedObject 被管理的数据记录,相当于数据库中的一条记录 每一个NSManagedObject对象,都有一个全局 ID(类型为:NSManagedObjectID)。每个在NSManagedObjectContext注册过 的NSManagedObject,可以通过这个全局 ID 在上下文中查询到。 每个在持久存储层中的对象,都对应一个与上下文相关的NSManagedObject 常用的方法: -entity 获取实体 -objectID 获取NSManagedObjectID -valueForKey: 获取指定 Property 的值 -setValue: forKey: 设定指定 Property 的值 3.NSFetchRequest 获取数据的请求,通过被管理数据的上下文来执行查询,比如 NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 查询时,必须指定查询实体或实体名称,以 NSArray 形式返回查询结果,如果我们没有设置任何查询条件,则返回该 Entity 的所有数据对象。 我们可以使用谓词来设置查询条件,通常会将常用的 Fetch Requests 保存到 dictionary 以重复利用。 NSFetchRequest包括以下部分: (1)实体(Entity)的名称 (2)NSPredicate谓词(搜索关键字或限定条件) (3)排序方式(NSArray *)sortDescriptors 所有的被管理对象(managed object)都必须在上下文中注册,而通过NSFetchRequest获得的对象自动被注册。 如果在上下文中已经存在了要获取的对象,那么这个被管理NSManagedObject将被返回。否则上下文就会从相关的数据源中查找(也可能找不到) 例如,以下代码是查询在指定日期之后创建的ContactInfo,并将查询结果按照name排序 NSManagedObjectContext * context = [self managedObjectContext]; NSManagedObjectModel * model = [self managedObjectModel]; NSDictionary * entities = [model entitiesByName]; NSEntityDescription * entity = [entities valueForKey:@"ContactInfo"]; NSPredicate * predicate; predicate = [NSPredicate predicateWithFormat:@"creationDate > %@", date]; NSSortDescriptor * sort = [[NSortDescriptor alloc] initWithKey:@"name"]; NSArray * sortDescriptors = [NSArray arrayWithObject: sort]; NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; [fetch setEntity: entity]; [fetch setPredicate: predicate]; [fetch setSortDescriptors: sortDescriptors]; NSArray * results = [context executeFetchRequest:fetch error:nil]; [sort release]; [fetch release]; 常用方法:
4.NSPersistentStoreCoordinator 持久化数据助理 Core Data定义了一个栈,持久化存储助理在中间,栈顶是被管理数据的上下文,栈底是持久化存储层,结构如图 通常从磁盘上的数据文件中读取或存储数据,这些底层的读写就由它来处理。一般我们无需与它直接打交道,上下文已经封装了对它的调用 常用方法:
5.NSManagedObjectModel 被管理的数据模型,用来描述程序的实体、其属性、关系的模型图 包括以下几个部分: (1)实体(Entity) 对应NSEntityDescription对象 相当于数据库中的一个表 实体名称(name) 实体类名:NSManagedObject子类的名称 实体实例:NSManagedObject对象或其子类的实例 NSEntityDescription 常用方法: +insertNewObjectForEntityForName:inManagedObjectContext: 工厂方法, 根据给定的 Entity 描述,生成相应的 NSManagedObject 对象,并插入 ManagedObjectContext 中。 -managedObjectClassName返回映射到 Entity 的 NSManagedObject 类名 -attributesByName以名字为 key, 返回 Entity 中对应的 Attributes -relationshipsByName以名字为 key, 返回 Entity 中对应的 Relationships (2)属性(Property) 对应NSPropertyDescription对象 Property 为 Entity 的特性,它相当于数据库表中的一列,或者 XML 文件中的 value-key 对中的 key。 它可以描述实体基本属性(Attribute),实体之间的关系(RelationShip),或查询属性(Fetched Property)。 <1> 实体的基本属性(Attributes) 对应NSAttributeDescription对象 存储基本数据,数据类型包括: string,date,integer(NSString, NSDate, NSNumber) <2> 实体间的关系(Relationships) 对应NSRelationshipDescription对象 支持对一、对多的关系 <3> 查询属性(Fetched Property) 对应NSFetchedPropertyDescription对象 根据查询谓词返回指定实体的符合条件的数据对象 表示了一种“弱”的、单项的关系(相当于数据库中的查询语句) 6.持久化存储层(Persistent Stores) 持久化存储层是和文件或外部数据库关联的,大多数访问持久化存储层的动作都由上下文来完成。 7.NSFetchedResultsController 用于在表视图table view中加载部分数据
二、用代码创建数据模型 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]]; 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; 本地化描述提供对 Entity,Property,Error信息等的便于理解的描述,其可用的键值对如下表:
三、存储数据到xml文件 存储类型为NSXMLStoreType 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 = [applicationDocmentDirectory() 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; } 四、自定义NSManagedObject子类 比如,Run.h文件 #import <CoreData/NSManagedObject.h> @interface Run : NSManagedObject { NSInteger processID; } @property (retain) NSDate *date; @property (retain) NSDate *primitiveDate; @property NSInteger processID; @end Run.m文件 #import "Run.h" @implementation Run @dynamic 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. 1)这个类中的 date 和 primitiveDate 的访问属性为 @dynamic,这表明在运行期会动态生成对应的 setter 和 getter;
|
|