尝试在 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)。虽然这不是问题,但它违反了标准命名约定,应该避免。
错误处理
您应该产生错误或正确处理它。我选择在我的实现中将错误传回给调用者【讨论】:
alloc
、copy
、mutableCopy
和 new
系列中的方法 [...] 隐式返回一个保留对象,就好像它们被 @987654337 注释一样@ 属性。这可以通过使用ns_returns_autoreleased
或ns_returns_not_retained
属性注释方法来覆盖。 (Source)
这是正确的,但 ARC 编译器将确保 newEntity
返回一个 (+1) 保留对象,必要时在方法中添加一个 retain
调用。 - 如果您混合使用 ARC 和非 ARC 代码,则命名约定非常重要。
“当从这样的函数或方法返回时,ARC 保留返回语句计算点的值,然后离开所有本地范围。”,来自同一个来源。以上是关于尝试在 iOS 中基于 NSString 值动态创建 NSManagedObject 子类的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS react-native-config 和 AsyncStorage 中修复 NSNull 类型的 JSON 值“<null>”无法转换为 NSString?