一般模型实现由Core Data和NSFetchedResultsController [英] general model implementation by Core Data and NSFetchedResultsController

查看:177
本文介绍了一般模型实现由Core Data和NSFetchedResultsController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Core Data的新手。我把所有的模型要求(关于MVC)在一个类NSFetchedResultsController如下:

I am newbie in Core Data. I put all model requirements (in respect of MVC) in a class of NSFetchedResultsController as below:

头文件:

#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中使用这个通用模型。

Then I use this general model in my UITableViewController.

有更好的方法吗?

推荐答案

它认为这是一个不错的方法,但它有一些缺点。
NSFetchedResultsController是负责的,顾名思义,用于控制获取的结果。如果您添加了删除和修改某些功能的功能,那么您将创建一个具有太多责任的对象。
想象一下,有一个viewController在tableview中显示结果。它只需要fetchedresultscontroller功能,没有更多。如果通过点击一个单元格进入一个新的视图控制器可以编辑,你不需要一个fetchedresultscontroller:你需要一个managedObject来编辑。这个editViewController可以使用tableViewController的子上下文,所以在取消时,通过简单的丢弃子上下文来丢弃所有的修改。

It think this is a nice approach, but it has some drawbacks. An NSFetchedResultsController is responsible, as the name implies for controlling results that were fetched. If you add functionality like deleting and modifying things, you are making an object with too many responsibilities. Imagine there is one viewController showing results in a tableview. It would only need the fetchedresultscontroller functionality, nothing more. If by tapping on a cell you go into a new view controller where edits are possible, you don't need a fetchedresultscontroller: you need a managedObject to edit. This editViewController could use a child context of the tableViewController so that on cancel, all edits are discarded by simply discarding the child context.

我建议没有子类NSFetchedResultsController,而是实现一个NSObject子类,您可以使用NSNMagedObjectContext初始化,该NSNMagedObjectContext可以执行适用于整个上下文的事情。像添加组,删除所有数据等
然后使用组合:这个NSObject子类可以是一个viewController的属性,因此viewCOntroller有一个方法来做这些事情,而没有这个操作是特定于这个viewController。

I would suggest to no subclass the NSFetchedResultsController, but instead implement a subclass of NSObject that you initialize with an NSNMagedObjectContext that can do the things that apply to the entire context. Like adding groups, removing all data etc. Then use composition: this NSObject subclass can be a property of a viewController so the viewCOntroller has a way to do those things without having this operation being specific to this viewController.

一般来说,而不是子类化,首先考虑合成。这是因为将一个组成对象的小组件转换为某个子类的对象通常更容易,反之亦然。

In general, instead of subclassing, consider composition first. This is because transforming a small components of a composed object to an object that is a certain subclass is usually easier then the other way around.

感觉自由不同意:),但这是我从一个很长的时间在一个非常大的代码库与许多人的工作经验中学到的。

Feel free to disagree :), but this is what I've learned from experience of working with many people for a long time on a very large codebase.

这篇关于一般模型实现由Core Data和NSFetchedResultsController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆