目标 c - 核心数据:无法调用 NSManagedObject 子类的私有方法
Posted
技术标签:
【中文标题】目标 c - 核心数据:无法调用 NSManagedObject 子类的私有方法【英文标题】:objective c - Core Data: Unable to call private method on a NSManagedObject subclass 【发布时间】:2012-07-23 13:06:35 【问题描述】:我对 Core Data 和 NSManagedObject
类有疑问。我有一个带有实体“UserProfile
”的数据模型,其中包含几个属性,包括“userId
”、“username
”和“clientId
”,这些属性是必不可少的。所有这三个属性在核心数据模型中都被标记为“字符串”。
UserProfile
源包含以下内容:
// UserProfile.h
#import <Foundation/Foundation.h>
@interface UserProfile : NSManagedObject
@property (nonatomic, retain) NSString* userId;
@property (nonatomic, retain) NSString* clientId;
@property (nonatomic, retain) NSString* userName;
// simple routine to display essential information about the user in the user table row
- (NSString*) obtainUserInfo;
// UserProfile.m
@implementation UserProfile
@dynamic userId;
@dynamic userName;
@dynamic clientId;
- (NSString*) obtainUserInfo
return [NSString stringWithFormat:@"%@ - %@", [self valueForKey:@"clientId"], [self valueForKey:@"userName"]];
当用户用一些文本字段填写表单并按下提交按钮时,我创建了 UserProfile 类的新实例。回调方法中的相关代码块如下:
Q3AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *desc = [NSEntityDescription entityForName:@"UserProfile" inManagedObjectContext:context];
// this line creates the managed object instance and stores it!
UserProfile *newProfile = [[UserProfile alloc]initWithEntity:desc insertIntoManagedObjectContext:context];
// editing properties now causes the object's state to switch to "isChanged". Changes only persist if they're explicitely saved
[newProfile setUserId: [UUIDCreater generateUUID]];
[newProfile setClientId: clientField.text];
[newProfile setUserName: userNameField.text];
NSError *error = nil;
[context save:&error];
if (!error)
// now send the result data to the other controller (via the delegate object)
[delegate newProfileCreated];
// dismiss this view
[self dismissModalViewControllerAnimated:YES];
else
NSLog(@"Error: %@", error);
接下来,表格视图控制器从 Core Data 存储中提取所有 UserProfile,并使用原型单元格显示它们。
好的,到目前为止一切正常,但我的问题始于 UserProfilesTable
类的代码,它是 UserProfile 表视图的 ViewController。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"userProfileEntry";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
UserProfile *obj = [_userProfileList objectAtIndex:indexPath.row];
NSLog(@"ClientId: %@", [obj valueForKey:@"clientId"]);
NSLog(@"UserName: %@", [obj valueForKey:@"userName"]);
// !!CRASH!!
NSLog(@"From Method: %@", [obj obtainUserInfo]);
cell.textLabel.text = [NSString stringWithFormat:@"%@ - %@", [obj valueForKey:@"clientId"], [obj valueForKey:@"userName"]];
return cell;
前两个NSLog
s 打印我刚刚在表单中输入的正确值以创建新的用户配置文件(因此,崩溃下方的命令也可以按预期工作)。
所以.. 使用基本的 KVC,我从 UserProfile 实例中获取了 clientId 和 userName 的值,但是为什么应用程序会崩溃并...
NSInvalidArgumentException
(原因:-[NSManagedObject gainUserInfo]:无法识别的选择器发送到实例 0x6c40b90)[0x6c40b90 在这种情况下是我的 UserProfile 实例]
...如果我尝试从 UserProfile
类中访问几乎相同的方法,只是封装到一个单独的方法中以提高可变性和其他东西?
似乎仅仅因为我将NSManagedObject
子类化,它就不再让我访问我的私有类方法了。我在obtainUserInfo
方法处设置了一个断点,它没有被触发,这对我来说意味着应用程序甚至没有进入该方法。
我发现another thread和这个基本是一样的问题,但是threadstarter自己回答了,通过重新创建核心数据实体解决了。我做了同样的事情,但没有解决我的问题。
我的提示已经用完了,因此欢迎提出任何建议。
提前致谢。
编辑:已修复。忘记将我的 UserProfile 类的类名分配给 XCode 的数据模型检查器中的核心数据实体。感谢您的帮助!
【问题讨论】:
如果您自己记录obj
,它会打印什么? (...并且记录 obj.userName
会崩溃吗?)
对我来说,通过-valueForKey:
方法访问UserProfile
的属性似乎很奇怪...
...我更喜欢这种方式来创建一个新实体:UserProfile * newProfile = [NSEntityDescription insertNewObjectForEntityForName:@"UserProfile" inManagedObjectContext:context];
但是您的代码中还有其他问题,因为这个方案非常适合我......
【参考方案1】:
原因:-[NSManagedObject gainUserInfo]:无法识别的选择器发送到实例 0x6c40b90
此消息意味着正在接收(但未能处理)obtainUserInfo
消息的对象是NSManagedObject
的一个实例。
[0x6c40b90 在这种情况下是我的 UserProfile 实例]
不,不是。它是您的UserProfile
实体 的一个实例,但它仍然属于NSManagedObject
类。 valueForKey:
访问的基本属性在这种情况下仍然有效。
这可能意味着您的数据模型没有为 UserProfile 实体指定特定的托管对象子类,因此新实例将作为 NSManagedObjects 返回。
【讨论】:
感谢您指出这一点。我真的忘记将类分配给实体..它现在可以工作了。完美的。谢谢!【参考方案2】:在我看来,您没有将实体的自定义子类设置为UserProfile
。您需要在数据模型检查器中设置实体的类。否则在从 store 中获取时将使用NSManagedObject
s。
【讨论】:
是的,我完全忘记了 coredata 实体和我的自定义类之间缺少的关系。它应该将我指向 xcode 检查器。感谢您的回复!以上是关于目标 c - 核心数据:无法调用 NSManagedObject 子类的私有方法的主要内容,如果未能解决你的问题,请参考以下文章
Magical Record 不会保存到 SQLite 文件
无法在目标 C 中调用 swift 函数。获取 NSObject 的错误接口声明