2015-03-02 24 views
1

我对Core Data很新,一直在尝试遵循很多教程,但其中大部分都将所有Core Data方法放入AppDelegate 。所以任何一个可以帮助我,请在此先感谢CoreData:+ entityForName:nil不是合法的NSManagedObjectContext参数搜索实体名称'XMPPUserCoreDataStorageObject

- (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='[email protected]'/> 
    // <item ask='subscribe' subscription='from' jid='[email protected]'/> 

    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 

错误IAM越来越是

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'XMPPUserCoreDataStorageObject'' 
+0

你能展示你的CoreDataModel和你的“XMPPUserCoreDataStorageObject”类吗? – geo 2015-03-02 13:14:48

+0

我已编辑只是检查@geo – 2015-03-02 13:20:16

+0

任何人都可以帮助我plzz – 2015-03-03 04:21:03

回答

0

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" 
+0

我一直保持breckpoint听到NSManagedObjectContext * moc = [[AppDelegate appdelegate] managedObjectContext_roster]; NSEntityDescription * entity = [NSEntityDescription entityForName:@“XMPPUserCoreDataStorageObject” inManagedObjectContext:moc]; – 2015-03-02 13:41:21

+0

错误是从这行开始NSManagedObjectContext * moc = [[AppDelegate appdelegate] managedObjectContext_roster]; NSEntityDescription * entity = [NSEntityDescription entityForName:@“XMPPUserCoreDataStorageObject” inManagedObjectContext:moc]; @geo – 2015-03-02 13:41:46

+0

我在我的代码中构建了你的场景,并首先将实体改为无效,然后设置'moc = nil;'。在我的代码中,它也崩溃在创建实体的那一行。再看看你的变量的状态,并告诉,如果moc是零或有效的moc ^^,请删除你不需要保留它的注释;)在你的代码中添加一个注释在问题中,所以人们不必阅读每条评论以获取所有信息:) +不使用聊天语言,但总是写得干净,易于阅读和理解;) – geo 2015-03-02 13:45:43

0
在didFinishLaunchingWithOptions

[self setupStream]; 
  • U不init xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
相关问题