1

我必须解决我认为相关的主要问题,因为它们都发生在同一行代码中。

数据模型

注意:我已经尽我所能简化了代码和模型。

我的核心数据模型中有 3 个实体。

  • Merchant(可以有很多Branch个es,可以有很多个Sectors)
  • Sector(可以有很多Merchants)
  • Branch(可以有一个Merchant

数据(以 JSON 格式)下载到应用程序。每个都Merchant被迭代提取扇区,如果扇区存在,则将其提取并添加到NSMutableArray.

...
//Iterating through Merchants
...
for(NSDictionary *sector in sectors) {
    NSLog(@"\tfetch sectors ID %@", [sector objectForKey:@"sector_id"]);
        
    NSPredicate *sectorPredicate = [NSPredicate predicateWithFormat:@"%K == %d", @"sectorID", [[sector objectForKey:@"sector_id"] integerValue]];
    [sectorRequest setPredicate:sectorPredicate];
                        
    NSArray *existingSector = [self.managedObjectContext executeFetchRequest:sectorRequest error:&error];
                
    if(!error && [existingSector count] == 1) {
        NSLog(@"\tfound sector");
    [merchantSectors addObject:[existingSector objectAtIndex:0]];
    }
    else {
        NSLog(@"\tcreate a new sector");
            
        //Create a new sector
        Sector *newSector = [[Sector alloc] initWithEntity:sectorEntity insertIntoManagedObjectContext:self.managedObjectContext];
        newSector.sectorID = [NSNumber numberWithInteger:[[sector objectForKey:@"sector_id"] integerValue]];
        newSector.name = [sector objectForKey:@"name"];
            
        [merchantSectors addObject:newSector];
            
        [newSector release]; newSector = nil;
    }
}
    
[sectorRequest release]; sectorRequest = nil;
    
NSLog(@"\tadd sectors to merchant");
[currentMerchant addSector:merchantSectors]; //<---- crash and hang

该应用程序将挂在:

 [currentMerchant addSector:merchantSectors];

或者有时抛出异常:

*** Terminating app due to uncaught exception \
'NSInternalInconsistencyException', reason: \ 
'-[__NSCFSet addObject:]: mutating method sent to immutable object'

解析代码几乎相同,Branch但从来没有这些问题,否则应用程序将在成为问题之前挂起或崩溃 (??)。

如果应用程序被删除并重新安装代码将正常工作,是否存在现有的相同关系导致此问题?

编辑:使用 NSInvocationOperation 调用 JSON 的解析,因此当它挂起时界面保持响应。崩溃版本会杀死应用程序。

编辑 2: Merchant.h 和 Merchant.m

商户.h

#import <CoreData/CoreData.h>

@class Branch;
@class Sector;

@interface Merchant :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * street;
@property (nonatomic, retain) NSString * locality;
@property (nonatomic, retain) NSString * city;
@property (nonatomic, retain) NSNumber * merchantID;
@property (nonatomic, retain) NSString * postcode;
@property (nonatomic, retain) NSString * property;
@property (nonatomic, retain) NSString * organisation;
@property (nonatomic, retain) NSDate * expires;
@property (nonatomic, retain) NSSet * Branch;
@property (nonatomic, retain) NSSet* Sector;

@end


@interface Merchant (CoreDataGeneratedAccessors)
- (void)addBranchObject:(Branch *)value;
- (void)removeBranchObject:(Branch *)value;
- (void)addBranch:(NSSet *)value;
- (void)removeBranch:(NSSet *)value;
- (void)addSectorObject:(Sector *)value;
- (void)removeSectorObject:(Sector *)value;
- (void)addSector:(NSSet *)value;
- (void)removeSector:(NSSet *)value;

@end

商人.m

#import "Merchant.h"
#import "Branch.h"

@implementation Merchant 

@dynamic street;
@dynamic locality;
@dynamic city;
@dynamic merchantID;
@dynamic postcode;
@dynamic property;
@dynamic organisation;
@dynamic expires;
@dynamic Branch;
@dynamic Sector;

@end
4

1 回答 1

1

add<Key>Object:尝试使用 CoreData和自动生成的方法将部门一一添加到商家remove<Key>Object:(如自定义对多关系访问器方法中所述)

for(NSDictionary *sector in sectors) {
    NSPredicate *sectorPredicate = [NSPredicate predicateWithFormat:@"%K == %d", @"sectorID", [[sector objectForKey:@"sector_id"] integerValue]];
    [sectorRequest setPredicate:sectorPredicate];

    NSArray *existingSector = [self.managedObjectContext executeFetchRequest:sectorRequest error:&error];

    if(!error && [existingSector count] == 1) 
    {
        [currentMerchant addSectorObject:[existingSector lastObject]];
    }
    else 
    {
        Sector *newSector = [[Sector alloc] initWithEntity:sectorEntity insertIntoManagedObjectContext:self.managedObjectContext];
        newSector.sectorID = [NSNumber numberWithInteger:[[sector objectForKey:@"sector_id"] integerValue]];
        newSector.name = [sector objectForKey:@"name"];

        [currentMerchant addSectorObject:newSector];

        [newSector release];
    }
}

或者,您可以通过以下方式检索包含 currentMerchants 扇区的可变代理对象并向mutableSetValueForKey:其添加扇区:

NSMutableSet *merchantSectors = [currentMerchant mutableSetValueForKey:@"sector"];
for(NSDictionary *sector in sectors) {
    NSPredicate *sectorPredicate = [NSPredicate predicateWithFormat:@"%K == %d", @"sectorID", [[sector objectForKey:@"sector_id"] integerValue]];
    [sectorRequest setPredicate:sectorPredicate];

    NSArray *existingSector = [self.managedObjectContext executeFetchRequest:sectorRequest error:&error];

    if(!error && [existingSector count] == 1) 
    {
        [merchantSectors addObject:[existingSector lastObject]];
    }
    else 
    {
        Sector *newSector = [[Sector alloc] initWithEntity:sectorEntity insertIntoManagedObjectContext:self.managedObjectContext];
        newSector.sectorID = [NSNumber numberWithInteger:[[sector objectForKey:@"sector_id"] integerValue]];
        newSector.name = [sector objectForKey:@"name"];

        [merchantSectors addObject:newSector];

        [newSector release];
    }
}

无论如何,为了方便起见,最好sectors为 Mecrhant 实体使用小写名称,以实现与 Sector 实体的多对多关系:小写不要与Sector类名混淆,并且可以肯定的是,该属性的 getter 方法返回多个对象。

于 2011-01-25T16:56:37.773 回答