目标 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;

前两个NSLogs 打印我刚刚在表单中输入的正确值以创建新的用户配置文件(因此,崩溃下方的命令也可以按预期工作)。 所以.. 使用基本的 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 中获取时将使用NSManagedObjects。

【讨论】:

是的,我完全忘记了 coredata 实体和我的自定义类之间缺少的关系。它应该将我指向 xcode 检查器。感谢您的回复!

以上是关于目标 c - 核心数据:无法调用 NSManagedObject 子类的私有方法的主要内容,如果未能解决你的问题,请参考以下文章

无法在目标 c 中调用方法

Magical Record 不会保存到 SQLite 文件

无法在目标 C 中调用 swift 函数。获取 NSObject 的错误接口声明

无法从 CDVPlugin 类目标 c 和 phonegap 调用 MainViewController 的静态方法

目标 c - 获取数据(核心数据)

获取结果崩溃(使用 persistentContainer) - 核心数据目标 C