尝试在托管对象中NSLOG NSSET时的EXC_BAD_ACCESS

时间:2013-03-10 10:12:55

标签: objective-c cocoa nsstring

我有一个简单的核心数据对象,只要我在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循环打印消息NSSet中的每条消息,它就可以工作,并证明那里有一些值。

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

1 个答案:

答案 0 :(得分:4)

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

  

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

     

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

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