我是Core Data的新手。我把所有模型要求(关于MVC)放在一个NSFetchedResultsController类中,如下所示:
标题文件:
#import <CoreData/CoreData.h>
@interface GeneralModel : NSFetchedResultsController
@property (nonatomic, strong) NSManagedObjectContext *context;
@property (nonatomic, strong) NSManagedObjectModel *model;
- (NSString *)storagePath;
- (void)removeStorage;
- (void)truncateAllEntity;
- (void)truncateEntity:(NSString *)entityName;
- (void)addGroups:(NSDictionary *)insertData;
- (NSArray *)getEntity:(NSString *)entityName sortBy:(NSString *)sortAttribute;
- (id)getMaxValue:(NSString *)entityName forProperty:(NSString *)propertyName;
- (NSArray *)getEntity:(NSString *)entityName predicateBy:(NSPredicate *)predicate sortBy:( NSString * )sortAttribute;
@end
主档案:
#import "GeneralModel.h"
#import "GeneralHelper.h"
@implementation GeneralModel
- (instancetype)init
{
self = [super init];
if (self) {
// Read in Model.xcdatamodeld
_model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *psc =
[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];
// Where does the SQLite file go?
NSString *path = self.storagePath;
NSURL *storeURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&error]) {
@throw [NSException exceptionWithName:@"OpenFailure"
reason:[error localizedDescription]
userInfo:nil];
}
// Create the managed object context
_context = [[NSManagedObjectContext alloc] init];
_context.persistentStoreCoordinator = psc;
}
return self;
}
- (NSString *)storagePath
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
// Get one and only document directory from that list
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:@"model.sqlite"];
}
- (void)removeStorage {
// NSError *error2;
// NSString *storagePath = [self storagePath];
//
// NSDictionary *options = @{NSPersistentStoreUbiquitousContentNameKey: @"model"};
// bool removeResult = [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:[NSURL URLWithString:storagePath] options:options error:&error2];
// if (removeResult == NO) {
// NSLog(@"Could not remove Storage. Reason: %@", error2.localizedFailureReason);
// }
NSPersistentStore *store = [self.context.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
BOOL isRemovePersistentStore = [self.context.persistentStoreCoordinator removePersistentStore:store error:&error];
if (isRemovePersistentStore == NO) {
NSLog(@"NO RemovePersistentStore. Reason: %@", error.localizedFailureReason);
}
BOOL isRemoveItemAtURL = [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
if (isRemoveItemAtURL == NO) {
NSLog(@"NO RemoveItemAtURL. Reason: %@", error.localizedFailureReason);
}
}
- (void)truncateAllEntity {
NSArray *entities = self.model.entities;
for (NSEntityDescription *entityDescription in entities) {
[self truncateEntity:entityDescription.name];
}
}
- (void)truncateEntity:(NSString *)entityName {
// delete all database
if (IOS_VERSION >= 9) {
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:entityName];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *deleteError = nil;
[self.context.persistentStoreCoordinator executeRequest:delete withContext:self.context error:&deleteError];
} else {
NSFetchRequest *allItems = [[NSFetchRequest alloc] init];
[allItems setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:self.context]];
[allItems setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error = nil;
NSArray *items = [self.context executeFetchRequest:allItems error:&error];
//error handling goes here
for (NSManagedObject *item in items) {
[self.context deleteObject:item];
}
NSError *saveError = nil;
[self.context save:&saveError];
//more error handling here
}
[self.context rollback];
}
- (void)addGroups:(NSDictionary *)insertData {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
for (NSDictionary *response in insertData) {
NSManagedObject *existingGroup = [self getEntity:@"Group" AtValue:response[@"groupId"] forProperty:@"group_id" ];
if (existingGroup) {
NSLog(@"existingGroup");
continue;
}
// for (int i; i<=20; i++) {
// set bullet
NSManagedObject *object_bullet = [NSEntityDescription insertNewObjectForEntityForName:@"Group_bullet"
inManagedObjectContext:self.context];
NSData *bulletData = [[NSData alloc] initWithBase64EncodedString:response[@"bullet"] options:NSDataBase64DecodingIgnoreUnknownCharacters];
[object_bullet setValue:bulletData forKey:@"bullet"];
[object_bullet setValue:response[@"groupId"] forKey:@"group_id"];
// set group
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"Group"
inManagedObjectContext:self.context];
[object setValue:object_bullet forKey:@"relatedBullet"];
// NSDate *createDate = [dateFormatter dateFromString:response[@"createDate"]];
// [object setValue:createDate forKey:@"group_created_date"];
NSNumber *createDate = response[@"createDate"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[createDate doubleValue]] forKey:@"group_created_date"];
[object setValue:response[@"groupId"] forKey:@"group_id"];
[object setValue:[GeneralHelper getInteger:response[@"memberNumber"]] forKey:@"group_members_count"];
[object setValue:response[@"name"] forKey:@"group_name"];
[object setValue:[GeneralHelper getInteger:response[@"privacy"]] forKey:@"group_privacy"];
[object setValue:@1 forKey:@"group_status"];
[object setValue:response[@"imageName"] forKey:@"image_name"];
[object setValue:response[@"lastMessageId"] forKey:@"last_message_id"];
[object setValue:response[@"lastMessageText"] forKey:@"last_message_text"];
//
// NSDate *lastMessageDate = [dateFormatter dateFromString:response[@"lastMessageDate"]];
// [object setValue:lastMessageDate forKey:@"last_time"];
NSNumber *lastMessageDate = response[@"lastMessageDate"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[lastMessageDate doubleValue]] forKey:@"last_time"];
[object setValue:response[@"machineId"] forKey:@"machine_id"];
NSNumber *timestamp = response[@"timestamp"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[timestamp doubleValue]] forKey:@"timestamp"];
[object setValue:[GeneralHelper getInteger:response[@"unreadCount"]] forKey:@"unread_count"];
// }
}
NSError *errorInsert;
if (![self.context save:&errorInsert]) {
NSLog(@"Failed to save - error: %@", [errorInsert localizedDescription]);
}
[self.context rollback];
}
- (id)getMaxValue:(NSString *)entityName forProperty:(NSString *)propertyName {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName];
fetchRequest.fetchLimit = 1;
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:propertyName ascending:NO]];
NSError *error = nil;
id maxValue = [self.context executeFetchRequest:fetchRequest error:&error].firstObject;
if (maxValue == nil) {
maxValue = @{propertyName : @0};
}
[self.context rollback];
return [maxValue valueForKey:propertyName];
}
- (id)getEntity:(NSString *)entityName AtValue:(NSString *)indexValue forProperty:(NSString *)propertyName {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.context];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", propertyName, indexValue];
// NSLog(@"predicate: %@", predicate);
[request setEntity:entity];
[request setPredicate:predicate];
[request setFetchLimit:1];
NSError *error;
NSArray *results = [self.context executeFetchRequest:request error:&error];
NSManagedObject *object = [results firstObject];
// if (object) {
// // there is at least one object matching you predicate
// } else {
// // there is no object matching your predicate in the moc
// }
// NSLog(@"results member %@", results);
// [self.context rollback];
return object;
}
然后我在UITableViewController中使用这个通用模型。
有没有更好的方法呢?或者我的实施是错误的和没用的?
答案 0 :(得分:0)
它认为这是一个很好的方法,但它有一些缺点。 NSFetchedResultsController负责,顾名思义用于控制获取的结果。如果添加删除和修改内容等功能,则会产生一个责任太多的对象。 想象一下,有一个viewController在tableview中显示结果。它只需要fetchedresultscontroller功能,仅此而已。如果通过点击单元格进入可以进行编辑的新视图控制器,则不需要fetchedresultscontroller:您需要使用managedObject进行编辑。这个editViewController可以使用tableViewController的子上下文,这样在取消时,只需丢弃子上下文就可以丢弃所有编辑。
我建议没有NSFetchedResultsController的子类,而是实现NSObject的子类,您可以使用NSNMagedObjectContext进行初始化,该NSNMagedObjectContext可以执行适用于整个上下文的操作。像添加组一样,删除所有数据等。 然后使用composition:这个NSObject子类可以是viewController的一个属性,所以viewCOntroller有一种方法可以做这些事情而不需要特定于这个viewController的这个操作。
通常,首先考虑组合而不是子类化。这是因为将组合对象的小组件转换为某个子类的对象通常比较容易。
随意不同意:),但这是我从很多人在很长的代码库上工作的经验中学到的。