一个用于常见 CoreData 任务的开源辅助库,其数据访问模式灵感来源于 Active Record、LINQ 和函数式编程。即使该库没有您需要的功能,您也可以总是回退到标准 CoreData,但提供了线程安全上下文的额外功能。
特性
在您的代码中包含头文件
#import <MMPCoreDataHelper/MMPCoreDataHelper.h>
通常,不需要数据库初始化,您可以直接使用模型对象来创建和查询记录。有关在开始使用库之前需要显式设置名称的情况,请参见 下方。
直接使用您的 CoreData 模型对象(扩展自 NSManagedObject)并简单地使用 创建
、更新
和 保存
来创建记录
// Create record
MMPArtist *artist = [[[MMPArtist create]
update:@{@"id" : @"1", @"name" : @"Daft Punk"}]
save];
// delete record
[[artist delete] save];
// saving several records once is more efficient, use MMPCoreDataHelper shared instance to do bulk saving.
[[MMPArtist create] update:@{@"id" : @"1", @"name" : @"Daft Punk"}];
[[MMPArtist create] update:@{@"id" : @"2", @"name" : @"Pink Floyd"}];
[[MMPArtist create] update:@{@"id" : @"3", @"name" : @"Porcupine Tree"}];
[MMPCoreDataHelper save];
使用 清除
删除实体中的所有记录
[MMPAlbum clear];
要检索数据,您需要首先构建查询(定义约束),然后执行它以生成结果。通过调用 查询
开始构建,然后使用 where
函数指定筛选器,使用 order
定义排序规范,使用 limit
限制结果数量,使用 offset
指定起始记录号,以及使用 error
指定代码块以在发生错误时执行。对于构建 NSFetchedResultsController
,有两个附加函数:sectionNameKeyPath
和 cacheName
。
构建查询后,有几种函数来生成结果。使用all
获取符合指定约束的全部记录数组,first
获取第一个记录,count
仅统计记录数而不实际获取任何内容,使用each
通过代码块遍历每条记录,以及使用fetchedResultsController
返回NSFetchedResultsController
。
以下代码展示了如何将这些函数结合起来构建查询并执行。
// fetch all artists
NSArray *artists = [[MMPArtist query] all];
// print all artists that starts with 'P' ordered by id using block
[[[[MMPArtist query]
where:@"name LIKE %@", @"P*"]
order:@"id"]
each:^(MMPArtist *artist) {
NSLog(@"%@", artist.name);
}];
// or just get the first record of the query
// note that you can also pass NSDictionary of key = value constraint to where function
MMPArtist *artist = [[[MMPArtist query]
where:@{@"name" : @"Pink Floyd"}]
first];
// many ways to construct where constraint
artist = [[[MMPArtist query]
where:@{@"name == 'Pink Floyd'"}]
first];
artists = [[[MMPArtist query]
where:@{@"name == 'Pink Floyd' OR name == 'Led Zeppelin'"}]
all];
// or even use NSPredicate if you feel like it
NSPredicate *predicate = ...
artists = [[[MMPArtist query]
where:predicate
all];
// use fetchedResultsController to create NSFetchedResultsController from a query
self.fetchedResultsController = [[[[MMPAlbum query]
order:@"artist.name"]
sectionNameKeyPath:@"artist.name"]
fetchedResultsController];
以下是一些构建更复杂排序的示例。
artists = [[[MMPArtist query]
order:@"name ASC, members DESC"
all];
// same ordering different way
artists = [[[MMPArtist query]
order:@{@"name" : @"ASC", @"members" : @"DESC"}
all];
SQL中的count
、min
、max
和sum
的等价函数也可用,如以下示例所示。
// counting all records
NSLog(@"Database initialized, %lu artists created", [[MMPArtist query] count]);
// getting minimum, maximum, and sum of attribute "members"
NSLog(@"### unfiltered artists' members aggregate: min = %@, max = %@, sum = %@",
[[MMPArtist query] min:@"members"],
[[MMPArtist query] max:@"members"],
[[MMPArtist query] sum:@"members"]);
// getting minimum, maximum, and sum of attribute "members" for artists with name that starts with "D"
MMPCoreDataQueryable *artistsD =[[MMPArtist query] where:@"name LIKE %@", @"D*"];
NSLog(@"### D artists' members aggregate: min = %@, max = %@, sum = %@",
[artistsD min:@"members"],
[artistsD max:@"members"],
[artistsD sum:@"members"]);
要从CSV文件导入数据,调用importer
开始构建导入程序,使用sourceURL
指定CSV源URL,error
指定在发生错误时要执行的代码块,使用each
来观察新导入的记录,最后调用import
开始执行。
// source CSV (with first line header/field names):
// id,name
// 100,Yes
[[[[[[MMPArtist importer]
sourceType:MMPCoreDataSourceTypeCSV]
sourceURL:[[NSBundle mainBundle] URLForResource: @"artists" withExtension:@"csv"]]
error:^(NSError *error) {
NSLog(@"[ERROR] error importing from artists CSV: %@", error);
}]
each:^(MMPArtist *importedArtist) {
NSLog(@"artist %@ imported", importedArtist.name);
}]
import];
您还可以使用filter:using:
方法过滤不必要的字段值,这样它就不会被添加到记录中。
// CSV format:
// id,name,genre
// 100,Yes,"Progressive Rock"
// "genre" field will be ignored
[[[[[[[MMPArtist importer]
sourceType:MMPCoreDataSourceTypeCSV]
sourceURL:[[NSBundle mainBundle] URLForResource: @"artists" withExtension:@"csv"]]
error:^(NSError *error) {
NSLog(@"[ERROR] error importing from artists CSV: %@", error);
}]
filter:@"genre" using:^BOOL(id record) {
return NO;
}]
each:^(MMPArtist *importedArtist) {
NSLog(@"artist %@ imported", importedArtist.name);
}]
import];
对于字段级转换和自定义数据转换(例如,填充关系对象),使用map:using:
。对于记录级转换,如以下示例所示,使用map
。
// source CSV (with first line header/field names):
// name,artist
// "The Yes Album",Yes
[[[[[[[[MMPAlbum importer]
sourceType:MMPCoreDataSourceTypeCSV]
sourceURL:[[NSBundle mainBundle] URLForResource: @"albums" withExtension:@"csv"]]
error:^(NSError *error) {
NSLog(@"[ERROR] error importing from albums CSV: %@", error);
}]
// map field "artist" from artist's name to NSManagedObject so that it can be set as relationship
map:@"artist" using:^MMPArtist *(NSString *value, NSUInteger index) {
return [[[MMPArtist query]
where:@{@"name" : value}]
first];
}]
// map record (populates ID)
map:^id(MMPAlbum *importedAlbum, NSUInteger index) {
// generate album ID based on artist ID and record index (line on the csv file)
importedAlbum.id = [NSString stringWithFormat:@"%@-%lu", importedAlbum.artist.id, (unsigned long)index];
return importedAlbum;
}]
each:^(MMPAlbum *importedAlbum) {
NSLog(@"album %@(id = %@) imported for artist %@",
importedAlbum.name,
importedAlbum.id,
importedAlbum.artist.name);
}]
import];
假设数据模型(momd)的名称与应用程序名称完全相同,则不需要进行初始化或配置。否则,必须在调用单例的任何其他函数之前设置数据模型名称。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Set singleton's data model name
[MMPCoreDataHelper instance].modelName = @"MyDataModel";
// Do other application initialization...
return YES;
}
如果您需要直接使用CoreData,只需使用由单例实例提供的线程安全MOC,例如。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity"
inManagedObjectContext:[MMPCoreDataHelper instance].managedObjectContext];
目前不可用,但我会随着库的更新编写文档。如果您有任何问题或功能请求,请随时联系我或创建问题。
MMPCoreDataHelper由Mamad Purbo维护。
MMPCoreDataHelper可根据MIT许可证获得。有关更多信息,请参阅LICENSE文件。
此库使用了从ObjectiveRecord (https://github.com/supermarin/ObjectiveRecord) 调整的代码。版权所有(c)2014 Marin Usalj http://supermar.in