CoreData:+entityForName: nil 不是合法的 NSManagedObjectContext 参数搜索实体名称 'XMPPUserCoreDataStorageObject
Posted
技术标签:
【中文标题】CoreData:+entityForName: nil 不是合法的 NSManagedObjectContext 参数搜索实体名称 \'XMPPUserCoreDataStorageObject【英文标题】:CoreData:+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'XMPPUserCoreDataStorageObjectCoreData:+entityForName: nil 不是合法的 NSManagedObjectContext 参数搜索实体名称 'XMPPUserCoreDataStorageObject 【发布时间】:2015-03-02 12:57:15 【问题描述】:我对 Core Data 很陌生,并且一直在尝试学习许多教程,但其中大多数都将所有 Core Data 方法都放入了 AppDelegate。所以请任何人帮助我提前谢谢
- (NSFetchedResultsController *)fetchedResultsController
// NSLog(@"Calling fetchedResultsController @ rootviewController");
if (is_Searching && [search_string length])
NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"sectionNum" ascending:YES];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSMutableArray * predicateArray = [[NSMutableArray alloc]init];
if (is_Searching && [search_string length])
NSPredicate *predecate = [NSPredicate predicateWithFormat:@"displayName CONTAINS [c] %@",search_string];
[predicateArray addObject:predecate];
if ([[AppDelegate get_update_privacy_Array] count])
for (NSString * jids in [AppDelegate get_update_privacy_Array])
NSPredicate *predecate_blocked = [NSPredicate predicateWithFormat:@"NOT(nickname CONTAINS [c] %@ OR jidStr CONTAINS %@)" ,jids, jids];
[predicateArray addObject:predecate_blocked];
NSPredicate *predicate_final = [NSCompoundPredicate andPredicateWithSubpredicates:
predicateArray];
[fetchRequest setPredicate:predicate_final];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController_search = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:@"sectionNum"
cacheName:nil];
[fetchedResultsController_search setDelegate:self];
NSError *error = nil;
if (![fetchedResultsController_search performFetch:&error])
//DDLogError(@"Error performing fetch: %@", error);
if (![[fetchedResultsController_search fetchedObjects]count] && ![groupChatArray count])
[AppDelegate alertWithTitle:@"Alert" message:@"No contact found!"];
return fetchedResultsController_search;
else
NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"sectionNum" ascending:YES];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSMutableArray *predicateArray = [[NSMutableArray alloc]init];
if ([[AppDelegate get_update_privacy_Array] count])
for (NSString * jids in [AppDelegate get_update_privacy_Array])
NSPredicate *predecate_blocked = [NSPredicate predicateWithFormat:@"NOT(nickname CONTAINS [c] %@ OR jidStr CONTAINS %@)" ,jids, jids];
[predicateArray addObject:predecate_blocked];
NSPredicate *predicate_final = [NSCompoundPredicate andPredicateWithSubpredicates:
predicateArray];
[fetchRequest setPredicate:predicate_final];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:@"sectionNum"
cacheName:nil];
[fetchedResultsController setDelegate:self];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error])
//DDLogError(@"Error performing fetch: %@", error);
return fetchedResultsController;
XMPPUserCoreDataStorageObject.m 类
#import "XMPP.h"
#import "XMPPRosterCoreDataStorage.h"
#import "XMPPUserCoreDataStorageObject.h"
#import "XMPPResourceCoreDataStorageObject.h"
#import "XMPPGroupCoreDataStorageObject.h"
#import "NSNumber+XMPP.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
@interface XMPPUserCoreDataStorageObject ()
@property(nonatomic,strong) XMPPJID *primitiveJid;
@property(nonatomic,strong) NSString *primitiveJidStr;
@property(nonatomic,strong) NSString *primitiveDisplayName;
@property(nonatomic,assign) NSInteger primitiveSection;
@property(nonatomic,strong) NSString *primitiveSectionName;
@property(nonatomic,strong) NSNumber *primitiveSectionNum;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@implementation XMPPUserCoreDataStorageObject
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Accessors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@dynamic jid, primitiveJid;
@dynamic jidStr, primitiveJidStr;
@dynamic streamBareJidStr;
@dynamic nickname;
@dynamic displayName, primitiveDisplayName;
@dynamic subscription;
@dynamic ask;
@dynamic unreadMessages;
@dynamic photo;
@dynamic section, primitiveSection;
@dynamic sectionName, primitiveSectionName;
@dynamic sectionNum, primitiveSectionNum;
@dynamic groups;
@dynamic primaryResource;
@dynamic resources;
@dynamic status;
- (XMPPJID *)jid
// Create and cache the jid on demand
[self willAccessValueForKey:@"jid"];
XMPPJID *tmp = [self primitiveJid];
[self didAccessValueForKey:@"jid"];
if (tmp == nil)
tmp = [XMPPJID jidWithString:[self jidStr]];
[self setPrimitiveJid:tmp];
return tmp;
- (void)setJid:(XMPPJID *)jid
self.jidStr = [jid bare];
- (void)setJidStr:(NSString *)jidStr
[self willChangeValueForKey:@"jidStr"];
[self setPrimitiveJidStr:jidStr];
[self didChangeValueForKey:@"jidStr"];
// If the jidStr changes, the jid becomes invalid.
[self setPrimitiveJid:nil];
- (NSInteger)section
// Create and cache the section on demand
[self willAccessValueForKey:@"section"];
NSInteger tmp = [self primitiveSection];
[self didAccessValueForKey:@"section"];
// section uses zero, so to distinguish unset values, use NSNotFound
if (tmp == NSNotFound)
tmp = [[self sectionNum] integerValue];
[self setPrimitiveSection:tmp];
return tmp;
- (void)setSection:(NSInteger)value
self.sectionNum = [NSNumber numberWithInteger:value];
- (NSInteger)primitiveSection
return section;
- (void)setPrimitiveSection:(NSInteger)primitiveSection
section = primitiveSection;
- (void)setSectionNum:(NSNumber *)sectionNum
[self willChangeValueForKey:@"sectionNum"];
[self setPrimitiveSectionNum:sectionNum];
[self didChangeValueForKey:@"sectionNum"];
// If the sectionNum changes, the section becomes invalid.
// section uses zero, so to distinguish unset values, use NSNotFound
[self setPrimitiveSection:NSNotFound];
- (NSString *)sectionName
// Create and cache the sectionName on demand
[self willAccessValueForKey:@"sectionName"];
NSString *tmp = [self primitiveSectionName];
[self didAccessValueForKey:@"sectionName"];
if (tmp == nil)
// Section names are organized by capitalizing the first letter of the displayName
NSString *upperCase = [self.displayName uppercaseString];
// return the first character with support UTF-16:
tmp = [upperCase substringWithRange:[upperCase rangeOfComposedCharacterSequenceAtIndex:0]];
[self setPrimitiveSectionName:tmp];
return tmp;
- (void)setDisplayName:(NSString *)displayName
[self willChangeValueForKey:@"displayName"];
[self setPrimitiveDisplayName:displayName];
[self didChangeValueForKey:@"displayName"];
// If the displayName changes, the sectionName becomes invalid.
[self setPrimitiveSectionName:nil];
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark NSManagedObject
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)awakeFromInsert
// Section uses zero, so to distinguish unset values, use NSNotFound.
self.primitiveSection = NSNotFound;
- (void)awakeFromFetch
// Section uses zero, so to distinguish unset values, use NSNotFound.
//
// Note: Do NOT use "self.section = NSNotFound" as this will in turn set the sectionNum.
self.primitiveSection = NSNotFound;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Creation & Updates
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ (id)insertInManagedObjectContext:(NSManagedObjectContext *)moc
withJID:(XMPPJID *)jid
streamBareJidStr:(NSString *)streamBareJidStr
if (jid == nil)
NSLog(@"XMPPUserCoreDataStorageObject: invalid jid (nil)");
return nil;
XMPPUserCoreDataStorageObject *newUser;
newUser = [NSEntityDescription insertNewObjectForEntityForName:@"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
newUser.streamBareJidStr = streamBareJidStr;
newUser.jid = jid;
newUser.nickname = nil;
newUser.displayName = [jid bare];
return newUser;
+ (id)insertInManagedObjectContext:(NSManagedObjectContext *)moc
withItem:(NSXMLElement *)item
streamBareJidStr:(NSString *)streamBareJidStr
NSString *jidStr = [item attributeStringValueForName:@"jid"];
XMPPJID *jid = [XMPPJID jidWithString:jidStr];
if (jid == nil)
NSLog(@"XMPPUserCoreDataStorageObject: invalid item (missing or invalid jid): %@", item);
return nil;
XMPPUserCoreDataStorageObject *newUser;
newUser = [NSEntityDescription insertNewObjectForEntityForName:@"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
newUser.streamBareJidStr = streamBareJidStr;
[newUser updateWithItem:item];
return newUser;
- (void)updateGroupsWithItem:(NSXMLElement *)item
XMPPGroupCoreDataStorageObject *group = nil;
// clear existing group memberships first
if ([self.groups count] > 0)
[self removeGroups:self.groups];
NSArray *groupItems = [item elementsForName:@"group"];
NSString *groupName = nil;
for (NSXMLElement *groupElement in groupItems)
groupName = [groupElement stringValue];
group = [XMPPGroupCoreDataStorageObject fetchOrInsertGroupName:groupName
inManagedObjectContext:[self managedObjectContext]];
if (group != nil)
[self addGroupsObject:group];
- (void)updateWithItem:(NSXMLElement *)item
NSString *jidStr = [item attributeStringValueForName:@"jid"];
XMPPJID *jid = [XMPPJID jidWithString:jidStr];
if (jid == nil)
NSLog(@"XMPPUserCoreDataStorageObject: invalid item (missing or invalid jid): %@", item);
return;
self.jid = jid;
self.nickname = [item attributeStringValueForName:@"name"];
self.displayName = (self.nickname != nil) ? self.nickname : jidStr;
self.subscription = [item attributeStringValueForName:@"subscription"];
self.ask = [item attributeStringValueForName:@"ask"];
[self updateGroupsWithItem:item];
- (void)recalculatePrimaryResource
self.primaryResource = nil;
NSArray *sortedResources = [[self allResources] sortedArrayUsingSelector:@selector(compare:)];
if ([sortedResources count] > 0)
XMPPResourceCoreDataStorageObject *resource = [sortedResources objectAtIndex:0];
// Primary resource must have a non-negative priority
if ([resource priority] >= 0)
self.primaryResource = resource;
if (resource.intShow >= 3)
self.section = 0;
else
self.section = 1;
if (self.primaryResource == nil)
self.section = 2;
- (void)updateWithPresence:(XMPPPresence *)presence streamBareJidStr:(NSString *)streamBareJidStr
XMPPResourceCoreDataStorageObject *resource =
(XMPPResourceCoreDataStorageObject *)[self resourceForJID:[presence from]];
if ([[presence type] isEqualToString:@"unavailable"] || [presence isErrorPresence])
if (resource)
[self removeResourcesObject:resource];
[[self managedObjectContext] deleteObject:resource];
else
if (resource)
[resource updateWithPresence:presence];
else
XMPPResourceCoreDataStorageObject *newResource;
newResource = [XMPPResourceCoreDataStorageObject insertInManagedObjectContext:[self managedObjectContext]
withPresence:presence
streamBareJidStr:streamBareJidStr];
[self addResourcesObject:newResource];
[self recalculatePrimaryResource];
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPUser Protocol
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)isOnline
return (self.primaryResource != nil);
- (BOOL)isPendingApproval
// Either of the following mean we're waiting to have our presence subscription approved:
// <item ask='subscribe' subscription='none' jid='robbiehanson@deusty.com'/>
// <item ask='subscribe' subscription='from' jid='robbiehanson@deusty.com'/>
NSString *subscription = self.subscription;
NSString *ask = self.ask;
if ([subscription isEqualToString:@"none"] || [subscription isEqualToString:@"from"])
if ([ask isEqualToString:@"subscribe"])
return YES;
return NO;
- (id <XMPPResource>)resourceForJID:(XMPPJID *)jid
NSString *jidStr = [jid full];
for (XMPPResourceCoreDataStorageObject *resource in [self resources])
if ([jidStr isEqualToString:[resource jidStr]])
return resource;
return nil;
- (NSArray *)allResources
NSMutableArray *allResources = [NSMutableArray array];
for (XMPPResourceCoreDataStorageObject *resource in [[self resources] allObjects])
if(![resource isDeleted])
[allResources addObject:resource];
return allResources;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Comparisons
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the result of invoking compareByName:options: with no options.
**/
- (NSComparisonResult)compareByName:(XMPPUserCoreDataStorageObject *)another
return [self compareByName:another options:0];
/**
* This method compares the two users according to their display name.
*
* Options for the search — you can combine any of the following using a C bitwise OR operator:
* NSCaseInsensitiveSearch, NSLiteralSearch, NSNumericSearch.
* See "String Programming Guide for Cocoa" for details on these options.
**/
- (NSComparisonResult)compareByName:(XMPPUserCoreDataStorageObject *)another options:(NSStringCompareOptions)mask
NSString *myName = [self displayName];
NSString *theirName = [another displayName];
return [myName compare:theirName options:mask];
/**
* Returns the result of invoking compareByAvailabilityName:options: with no options.
**/
- (NSComparisonResult)compareByAvailabilityName:(XMPPUserCoreDataStorageObject *)another
return [self compareByAvailabilityName:another options:0];
/**
* This method compares the two users according to availability first, and then display name.
* Thus available users come before unavailable users.
* If both users are available, or both users are not available,
* this method follows the same functionality as the compareByName:options: as documented above.
**/
- (NSComparisonResult)compareByAvailabilityName:(XMPPUserCoreDataStorageObject *)another
options:(NSStringCompareOptions)mask
if ([self isOnline])
if ([another isOnline])
return [self compareByName:another options:mask];
else
return NSOrderedAscending;
else
if ([another isOnline])
return NSOrderedDescending;
else
return [self compareByName:another options:mask];
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark KVO compliance methods
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ (NSSet *)keyPathsForValuesAffectingJid
// If the jidStr changes, the jid may change as well.
return [NSSet setWithObject:@"jidStr"];
+ (NSSet *)keyPathsForValuesAffectingIsOnline
return [NSSet setWithObject:@"primaryResource"];
+ (NSSet *)keyPathsForValuesAffectingSection
// If the value of sectionNum changes, the section may change as well.
return [NSSet setWithObject:@"sectionNum"];
+ (NSSet *)keyPathsForValuesAffectingSectionName
// If the value of displayName changes, the sectionName may change as well.
return [NSSet setWithObject:@"displayName"];
+ (NSSet *)keyPathsForValuesAffectingAllResources
return [NSSet setWithObject:@"resources"];
@end
我得到的错误是
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'XMPPUserCoreDataStorageObject''
【问题讨论】:
你能展示你的CoreDataModel和你的“XMPPUserCoreDataStorageObject”类吗? 我已经编辑了,检查一下@geo 有谁能帮帮我吗 1.阅读我对我的回答的更新/评论! 2. 如果您还有其他问题,请写下来(可能会创建新问题) 3. 不要使用快捷方式/聊天语言... 我现在正面临这个错误。我不知道如何解决。 @geo。你能指导我吗? 【参考方案1】:nil is not a legal NSManagedObjectContext parameter
- 似乎您的 NSManagedObjectContext
对象在此部分无效。检查你从你的代表那里得到它的部分,启动时可能有错误:)
更新
NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster]; // <- this seems to be nil
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc]; // <- crashing because "nil is not a legal NSManagedObjectContext parameter"
【讨论】:
我一直保持 breckpoint 听到 NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject" inManagedObjectContext:moc]; 错误是从这一行开始的 NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject" inManagedObjectContext:moc]; @geo 我已经在我的代码中构建了你的场景,首先将实体更改为无效,然后设置moc = nil;
。在我的代码中,它也在创建实体的行处崩溃。再次查看变量的状态并判断 moc 是 nil 还是有效的 moc ^^ 并请删除不需要保持干净的 cmets ;) 在问题中的代码中添加注释,所以人们不必阅读每条评论来获取所有信息:) + 不要使用聊天语言,但总是写得干净、易于阅读和理解;)
对不起,我没听懂你能告诉我,请给我写两行代码【参考方案2】:
在 didFinishLaunchingWithOptions 中
[self setupStream];
你不初始化 xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
【讨论】:
以上是关于CoreData:+entityForName: nil 不是合法的 NSManagedObjectContext 参数搜索实体名称 'XMPPUserCoreDataStorageObject的主要内容,如果未能解决你的问题,请参考以下文章
CoreData:“NSInternalInconsistencyException”,原因:“+entityForName:无法在此模型中找到名为“DocumentLocations”的实体。
OSX CoreData:仅针对某些实体的问题:+entityForName:在此模型中找不到名为“myEntity”的实体
iOS:Swift:核心数据:错误:+entityForName:nil 不是搜索实体名称的合法 NSManagedObjectContext 参数
扩展教程材料时 entityForName 和 ManagedObjectContext 的问题