1

我有一个简单的核心数据对象,每当我在 Xcode 中EXC_BAD_ACCESS尝试它的内容时,它都会给我一个。NSLog

托管对象如下所示:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class ChatFriend, ChatMessage;

@interface ChatThread : NSManagedObject

@property (nonatomic, retain) NSString * threadId;
@property (nonatomic, retain) NSDate * timestamp;
@property (nonatomic, retain) NSSet *friends;
@property (nonatomic, retain) NSSet *messages;
@end

@interface ChatThread (CoreDataGeneratedAccessors)

- (void)addFriendsObject:(ChatFriend *)value;
- (void)removeFriendsObject:(ChatFriend *)value;
- (void)addFriends:(NSSet *)values;
- (void)removeFriends:(NSSet *)values;

- (void)addMessagesObject:(ChatMessage *)value;
- (void)removeMessagesObject:(ChatMessage *)value;
- (void)addMessages:(NSSet *)values;
- (void)removeMessages:(NSSet *)values;

@end

这是.m文件:

#import "ChatThread.h"
#import "ChatFriend.h"
#import "ChatMessage.h"


@implementation ChatThread

@dynamic threadId;
@dynamic timestamp;
@dynamic friends;
@dynamic messages;

- (NSString*) description
{

    /* This can print out the contents of self.messages correctly
    for(ChatMessage *message in self.messages)
    {
        Log(@"ChatMessage - %@", message);
    }
    */

    // using %@ to print out self.messages directly, will fail:
    return [NSString stringWithFormat:@"ChatThread - threadId:%@, messages count:%d, messages:%@", self.threadId, self.messages.count, self.messages];
}

@end

我注意到,如果我尝试打印出该stringWithFormat行中 self.messages 的内容,EXC_BAD_ACCESS将会发生。如果我删除 self.messages,只打印出self.messages.count,它可以工作。如果我手动执行 for 循环以打印出 messages 中的每条消息NSSet,它就可以工作并且证明那里有一些值。

那么,为什么直接打印 self.messages 会触发EXC_BAD_ACCESS呢?

4

1 回答 1

4

description在 NSManagedObject中覆盖时,文档非常明确:

您可以安全地在故障上调用以下方法而不会触发它:isEqual:、hash、superclass、class、self、isProxy、isKindOfClass:、isMemberOfClass:、conformsToProtocol:、responsToSelector:、description、managedObjectContext、entity、objectID、isInserted 、isUpdated、isDeleted、faultingState 和 isFault。由于 isEqual 和 hash 不会导致触发故障,因此托管对象通常可以放置在集合中而不会触发故障。但是请注意,在集合对象上调用键值编码方法可能会反过来导致在托管对象上调用 valueForKey:,这将引发错误。

虽然描述方法不会导致故障触发,但如果您实现访问对象持久属性的自定义描述方法,这将导致故障触发。强烈建议您不要以这种方式覆盖描述。

您似乎违反了最后一段中的警告。使您的 NSManagedObjectContext 不将对象作为故障返回,或用于valueForKey:显式触发故障并在尝试访问它的描述之前加载结果属性。自行触发的故障对象会导致未定义的行为。

于 2013-03-10T10:24:14.627 回答