我有一个简单的核心数据对象,只要我在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
?
答案 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:
显式触发错误并加载结果属性,然后再尝试访问它的描述。自行引发的故障对象会导致未定义的行为。