尝试在 iOS 中基于 NSString 值动态创建 NSManagedObject 子类

Posted

技术标签:

【中文标题】尝试在 iOS 中基于 NSString 值动态创建 NSManagedObject 子类【英文标题】:Trying to dynamically create an NSManagedObject subclass based on NSString value in iOS 【发布时间】:2013-10-23 18:02:27 【问题描述】:

我正在构建一个利用 Core Data 的应用程序,它在数据模型中有多个实体。我想做的是创建一个方法,该方法能够根据它接收到的方法的名称创建适当的 NSManagedObject 子类,这将是一个 NSString。

我的方法是这样的:

- (NSManagedObject *) addEntity:(NSString *)name 

  NSManagedObjectContext *context = [self managedObjectContext];
  NSError *error;

  //need to add a line here that casts EntityType to of type "name" which is passed into the method.
  EntityType *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];

  [context save:&error];

   return testEntity;


其中“EntityType”是“name”类型,这样如果我将名称“Manager”传递给方法,我将创建一个“Manager”类型的对象。因此上面的行:

EntityType *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];

应该是:

Manager *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];

为了根据传递给方法的类型动态创建实体,我需要做什么?请注意,我这样做是因为我的应用程序中有超过 20 个实体,并且希望只有一种方法可以用于其中任何一个。

【问题讨论】:

你当前的实现有什么问题? 方法名也不要以new开头,否则ARC会尝试释放你通过这个方法创建的对象 最后你忽略了这个错误。您应该放弃它或正确处理它。 @syedfa:为什么不简单地NSManagedObject *testEntity = [NSEntityDescription insertNewObjectForEntityForName:...] @syedfa:testEntity 的声明方式无关紧要(作为 NSManagedObject、EntityType 或 Manager)。 insertNewObjectForEntityForName 将始终创建给定子类的实例。 【参考方案1】:

如果您的问题是 testEntity 的类型,只需使用通用的 NSManagedObject

无论如何,一个不错的解决方案是在NSManagedObject 上添加一个类别。这是一个基本上复制了 MagicalRecord 提供的相同功能的实现。

NSManagedObject+Utilities.h

@interface NSManagedObject (Utilities)
+ (instancetype)my_createAndSave:(NSError **)error;
@end

NSManagedObject+Utilities.m

@implementation NSManagedObject (Utilities)
+ (instancetype)my_createAndSave:(NSError **)error 
    NSString *entityName = NSStringFromClass(self);
    if ([self respondsToSelector:@selector(entityName)]) 
        entityName = [self performSelector:@selector(entityName)];
    
    NSManagedObject *entity = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext];
    [self.managedObjectContext save:error];
    return entity;

@end

几点说明:

命名

作为一个类别总是最好添加一个自定义前缀,而不是与 Apple 的 API 冲突。我在这里使用了my_,但是你可以添加任何你喜欢的东西。 以new 开头的方法名称应保留给返回非自动释放对象的方法。由于entity 是自动释放的,ARC 将在返回对象之前添加一个额外的retain(稍后由release 平衡)(reference)。虽然这不是问题,但它违反了标准命名约定,应该避免。

错误处理

您应该产生错误或正确处理它。我选择在我的实现中将错误传回给调用者

【讨论】:

alloccopymutableCopynew 系列中的方法 [...] 隐式返回一个保留对象,就好像它们被 @987654337 注释一样@ 属性。这可以通过使用ns_returns_autoreleasedns_returns_not_retained 属性注释方法来覆盖。 (Source) 这是正确的,但 ARC 编译器将确保 newEntity 返回一个 (+1) 保留对象,必要时在方法中添加一个 retain 调用。 - 如果您混合使用 ARC 和非 ARC 代码,则命名约定非常重要。 “当从这样的函数或方法返回时,ARC 保留返回语句计算点的值,然后离开所有本地范围。”,来自同一个来源。

以上是关于尝试在 iOS 中基于 NSString 值动态创建 NSManagedObject 子类的主要内容,如果未能解决你的问题,请参考以下文章

如何在ios中动态生成多页pdf时处理分页

如何在 iOS 中限制浮点值

iOS动态的创建类

如何在 iOS react-native-config 和 AsyncStorage 中修复 NSNull 类型的 JSON 值“<null>”无法转换为 NSString?

iOS向数组添加动态值

Oracle/SQL - 基于参数的动态列