子类 NSManagedObject 以轻松初始化

Posted

技术标签:

【中文标题】子类 NSManagedObject 以轻松初始化【英文标题】:Subclass NSManagedObject to easy initialize 【发布时间】:2017-01-04 14:48:32 【问题描述】:

对于来自服务器 API 的模型,我使用这样的构造函数:

@implementation MenuAPIModel

-(instancetype)initWithServerData:(id)data

    self = [super initWithServerData:data];
    return self;


-(void)performMapping

    _basketId = self.serverData[@"basket_id"];
    _orderId = self.serverData[@"order_id"];
    _itemId = self.serverData[@"id"];
    _name = self.serverData[@"name"] == [NSNull null] ? @"" : self.serverData[@"persons"];
    _payedFrom = [self.dfDetail dateFromString:self.serverData[@"payed_from"]] == nil ? [self.dfBasic dateFromString:self.serverData[@"payed_from"]] : [self.dfDetail dateFromString:self.serverData[@"payed_from"]];
    _payedTill = [self.dfBasic dateFromString:self.serverData[@"payed_till"]] == nil ? [self.dfBasic dateFromString:self.serverData[@"payed_till"]] : [self.dfDetail dateFromString:self.serverData[@"payed_till"]];
    _persons = self.serverData[@"persons"] == [NSNull null] ? @"2-3" : self.serverData[@"persons"];
    _price = self.serverData[@"price"] == [NSNull null] ? @(0) : self.serverData[@"price"];
    _price3 = self.serverData[@"price3"] == [NSNull null] ? @(0) : self.serverData[@"price3"];
    _price12 = self.serverData[@"price12"] == [NSNull null] ? @(0) : self.serverData[@"price12"];
    _status = self.serverData[@"status"] == [NSNull null] ? @"not_payed" : self.serverData[@"persons"];

所以,我可以用简单的方式创建对象:[MenuAPIModel initWithServerData:data];

现在我继承了 NSManagedObject 并且想知道,我怎样才能继承 XCode 为我创建的这 4 个文件,以制作像上面那样的构造函数?

【问题讨论】:

【参考方案1】:

您可以创建一种可以具有以下实现的助手(这只是示例,所以我使用了 Swift):

static open func createObject <T : NSManagedObject> (_ objectType : T.Type, record : Dictionary<String, Any>? = nil, context : NSManagedObjectContext) -> (T)

    let newObject = NSEntityDescription.insertNewObject(forEntityName: String(describing: objectType), into: context)

    // Error never occured

    var typedNewObject = newObject as! T

    guard let trueRecord = record
    else
    
        return typedNewObject
    

    typedNewObject = updateObject(typedNewObject, record: trueRecord, context: context)

    return typedNewObject


static open func updateObject <T : NSManagedObject> (_ object : T, record : Dictionary<String, Any>, context : NSManagedObjectContext) -> (T)

    for (key, value) in record
    
        setValue(value, key: key, object: object)
    

    return object


static public func setValue (_ value : Any, key : String, object : NSManagedObject) -> (Void)

    object.setValue(value, forKey: key)

使用这些方法,您可以输入:

let myNewObject = Helper.createObject(YourClassName.self, record: yourDictionary, context: yourContext) // Helper, or any other class name you give it.

我希望它足够接近您的需求。

【讨论】:

【参考方案2】:

我不完全理解你想要子类化什么,但为了使用CoreData,你的模型必须子类化NSManagedObject,所以如果你想子类化你编写的自定义模型类,该类必须子类化NSManagedObject.

现在,NSManagedObject 的新 XCode 模板为您在 xcdatamodel 中声明的每个模型创建一个类和一个类别。你会有这样的东西。

MenuAPIModel+CoreDataProperties.h

@interface MenuAPIModel (CoreDataProperties) 

@property(nonatomic, strong) NSNumber *basketId
.....other properties that you have
@end

MenuAPIModel+CoreDataProperties.m

@implementation MenuAPIModel (CoreDataProperties)
@dynamic basketId
@dynamic ....other properties ...
@end

MenuAPIModel.h

@interface MenuAPIModel : NSManagedObject
+(instancetype)initWithServerData:(id)serverData;
@end

MenuAPIModel.m

@implementation MenuAPIModel

 +(instancetype)initWithServerData:(id)serverData 
     NSManagedObjectContext *context = ...get the current context...
     MenuAPIModel *model = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MenuAPIModel class])inManagedObjectContext:context];
     model.basketId = serverData[@"basket_id"];
     ...other parsing....
     return model;
 

如您所见,您可以使用 XCode 默认创建的那些类和类别,只需添加一个额外的方法。提醒一下,NSManagedObject 不能使用 alloc] init]; 创建,必须使用 NSManagedObjectContext 创建。

【讨论】:

我明白了,您将所有逻辑都放在 API 模型中。但我想做相反的事情——基于完整的 API 模型类创建和填充核心数据模型。例如,如何创建类似 [model initWithData:MenuAPIModell instance]; ? @EvgeniyKleban 你可以随意填写核心数据模型,重要的是你如何初始化代码数据模型(就像我一样)。

以上是关于子类 NSManagedObject 以轻松初始化的主要内容,如果未能解决你的问题,请参考以下文章

NSManagedObject 子类在 swift 中初始化失败

如何为子类 NSManagedObject 正确实现自定义初始化程序

swift NSManagedObject 子类初始化问题

NSManagedObject 子类问题

如何在Swift中初始化iOS 10和iOS 9.3的NSManagedObject子类

NSManagedObject 子类的 Swift 链接器错误实现具有所需初始化的协议