Objective C 属性与 Core Data 的 ivar 问题

发布于 2024-11-04 10:06:23 字数 1507 浏览 0 评论 0原文

我花了几个小时试图解决这个问题,我认为这取决于我对 Objective C 的基本理解,尽管它是通过处理 Core Data 表现出来的。我并不感到惊讶——我使用 Objective C 和 Cocoa Touch 才两个月。

我的情况是,我有一系列模型,它们在 CD 中都连接良好。我的应用程序运行得很好,直到我昨天尝试扩展它。我的主模型作业位于视图控制器中,作为 .h 文件中的类属性。在我的 viewWillAppear 方法中,我必须通过另一个对象查找关系,所以我做了类似的事情:

/** project as an ivar **/
NSManagedObject *project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do something with divisions --> crash

...

/** project as a property **/
project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do someting, anything ---> A-OK!

那么,为什么当我尝试使用 [project valueForKey:] 的结果执行操作时,我的应用程序会崩溃,除非我创建项目阶级财产?

编辑

似乎只是在其中包含 if(!divisions) 条件(当视图首次加载时它应该为空),它不喜欢我上面提供的语句并生成 EXC_BAD_ACCESS。但是,当忽略它时,我的代码工作正常。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if(!divisions){

        NSManagedObject *project = [[job valueForKey:@"project"] retain];
        NSArray *divs = [[project valueForKey:@"divisions"] allObjects];

        NSSortDescriptor *alphaSort = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
        divisions = [[divs sortedArrayUsingDescriptors:[NSArray arrayWithObject:alphaSort]] mutableCopy];

    }
    [[self tableView] reloadData];
}

我承认存在更大的内存管理问题。我是否应该回去重新阅读一些关于 Obj-C 的书籍章节并回溯我的变量,以便它有意义?

I spent several hours trying to figure out this problem, and I think it comes down to my fundamental understanding of Objective C, though it manifested through working on Core Data. I'm not surprised - I've only been working with Objective C and Cocoa Touch for just two months now.

My situation is that I have a series of models that are all connected fine in the CD. My app works just fine until I tried extending it yesterday. I have my main model Job in a view controller as a class property in the .h file. In my viewWillAppear method I have to look up a relationship through another object, so I do something like:

/** project as an ivar **/
NSManagedObject *project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do something with divisions --> crash

...

/** project as a property **/
project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do someting, anything ---> A-OK!

So, why does my app crash when I try to do things with the results of [project valueForKey:] unless I make project a class property?

EDIT

It appears that simply including the if(!divisions) conditional in there (which it should be null when the view first loads), it doesn't like the statements I provided above and produces the EXC_BAD_ACCESS. However, when leaving it out, my code works fine.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if(!divisions){

        NSManagedObject *project = [[job valueForKey:@"project"] retain];
        NSArray *divs = [[project valueForKey:@"divisions"] allObjects];

        NSSortDescriptor *alphaSort = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
        divisions = [[divs sortedArrayUsingDescriptors:[NSArray arrayWithObject:alphaSort]] mutableCopy];

    }
    [[self tableView] reloadData];
}

I'll accept that there's a bigger memory management problem going on. Should I probably go back and re-read some book chapters on Obj-C and retrace my variables so it makes sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱果果 2024-11-11 10:06:23

根据提供的有限代码,我无法确定,但崩溃的最简单解释是您不检查 divsdivisions 数组是否为空在对它们执行任何操作之前。

如果 Project.divisions 关系为空,则此:

NSArray *divs = [[project valueForKey:@"divisions"] allObjects];

...将返回一个空数组。任何尝试寻址数组的任何元素(例如 [divs objectAtIndex:0])都会产生错误。

此外,divisions 似乎是控制器对象的 iVar,但您既不使用首选的 self.divisions 引用形式,也不使用 [divisions keep]< /code> 将 'divs' 数组分配给它时。由于 divs 数组将自动释放返回,因此当池下次耗尽时它将被清除,并且 divisions 中的数组即使不为空也会消失。

只需将 divisions 更改为 self.divisions 即可修复。

I can't tell for certain based on the limited code provided but the simplest explaination for the crash is that you don't check if the divs or the divisions arrays are empty before performing any operations on them.

If the Project.divisions relationship is empty this:

NSArray *divs = [[project valueForKey:@"divisions"] allObjects];

... will return an empty array. Any attempt to address any element of the array e.g. [divs objectAtIndex:0] will produce an error.

Also, divisions appears to be an iVar of the controller object but you don't use either the preferred self.divisions reference form nor a [divisions retain] when assigning the 'divs' array to it. Since the divs array will be returned autoreleased, it will be purged when the pool next drains and the array in divisions will disappear even if it is not empty.

Simply change divisions to self.divisions to fix.

为你拒绝所有暧昧 2024-11-11 10:06:23

除了 ivar 混乱之外,您的代码还有两个其他问题。当访问 NSManagedObject 上的属性时,您应该使用 PrimitiveValueForKey: 就像在

[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveValueForKey:@"project"];
[job didAccessValueForKey:@"project"];

任何时候您获取或设置现有托管对象的属性一样,您应该始终在调用之前使用 willAccessValueForKey: 并使用 didAccessValueForKey: 关闭,以便模型和存储保持不变同步。

更好的是

[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveProject];
[job didAccessValueForKey:@"project"];

,但不幸的是 Xcode 调试器无法理解这一点,你必须忍受那些烦人的黄色警告。

此外, NSManagedObject 关系返回 NSSet 而不是数组:

[project willAccessValueForKey:@"divisions"];
NSSet *divisions = [project primitiveValueForKey:@"divisions"];
[project didAccessValueForKey:@"divisions"];

请阅读 Apple 的 模型对象实现指南

最后,如果您执行所有这些操作来填充表,那么最好实例化一个 NSFetchedResultsController ,该控制器针对精确优化进行了优化那个任务。

Apart from the ivar confusion your code has two other problems. When accessing an attribute on an NSManagedObject you should use primitiveValueForKey: as in

[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveValueForKey:@"project"];
[job didAccessValueForKey:@"project"];

Any time you get or set a property of an existing managed object, you should always precede the call with willAccessValueForKey: and close with didAccessValueForKey: so that the model and the store stay in sync.

Even better would be

[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveProject];
[job didAccessValueForKey:@"project"];

but unfortunately the Xcode debugger doesn't grok that and you have to put up with those annoying yellow warnings.

Furthermore, an NSManagedObject relationship returns an NSSet not an array:

[project willAccessValueForKey:@"divisions"];
NSSet *divisions = [project primitiveValueForKey:@"divisions"];
[project didAccessValueForKey:@"divisions"];

Read more in Apple's Model Object Implementation Guide

Lastly, if you're doing all this to populate a table, you're much better off instantiating an NSFetchedResultsController which is optimized for precisely that task.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文