核心数据实体阵列在IOS中释放或删除对象时生成崩溃

时间:2013-03-02 10:22:00

标签: ios core-data nsmutablearray nsentitydescription

这是我的CoreDataManagerClass

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface RTC_CoreDataManager : NSObject
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
  - (void)saveContext;
  - (NSURL *)applicationDocumentsDirectory;
  -(void)insertEntity:(NSString *)entityName arrayOfManagedObject:(NSMutableArray *)array;
  +(RTC_CoreDataManager *)shredInstance;
   @end

#import "RTC_CoreDataManager.h"
RTC_CoreDataManager *obj_RTC;
@implementation RTC_CoreDataManager

@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;

 - (void)saveContext
 {
 NSError *error = nil;
  NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
 if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {

           NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
           abort();
        }
   }
}

+(RTC_CoreDataManager *)shredInstance{
if (obj_RTC ==  nil) {
           obj_RTC = [[RTC_CoreDataManager alloc]init];
       }
        return obj_RTC;

    }
#pragma mark - Core Data stack


- (NSManagedObjectContext *)managedObjectContext
{
   if (__managedObjectContext != nil) {
        return __managedObjectContext;
  }

   NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
   if (coordinator != nil) {
       __managedObjectContext = [[NSManagedObjectContext alloc] init];
       [__managedObjectContext setPersistentStoreCoordinator:coordinator];
   }
   return __managedObjectContext;
}


- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil) {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RTC" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
 {
     if (__persistentStoreCoordinator != nil) {
        return __persistentStoreCoordinator;
   }

    NSURL *storeURL = [[self applicationDocumentsDirectory]     URLByAppendingPathComponent:@"RTC.sqlite"];
    NSError *error = nil;
    if (![[NSFileManager defaultManager] copyItemAtURL:storeURL toURL:[NSURL alloc] error:&error]) {
        NSLog(@"Oops, could copy preloaded data");
    }

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

return __persistentStoreCoordinator;
}

#pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

-(void)insertEntity:(NSString *)entityName arrayOfManagedObject:(NSMutableArray *)array 
{
NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
for (id object in array)
 {

 [backgroundMOC performBlockAndWait:^
 {
 NSError *error;
 if (![__managedObjectContext save:&error]) 
 {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
}];
}

}

@end

这是我在另一个控制器中的代码。

    -(void)viewDidLoad
    {
     [super viewDidLoad];
     appDele_Obj = (RTC_AppDelegate *)[[UIApplication sharedApplication] delegate];
   appDele_Obj.entityArray=[[NSMutableArray alloc]init];

for (int i=0; i<10; i++)
{

    Survey *objSurvey = [NSEntityDescription
                         insertNewObjectForEntityForName:@"Survey"
                         inManagedObjectContext:[RTC_CoreDataManager shredInstance].managedObjectContext];        [objSurvey setFirstName:@"1"];
    [objSurvey setLastName:@"2"];
    [objSurvey setEmpId:@"3"];
    [objSurvey setLanguage:@"Hindi"];
    [objSurvey setCountry:@"India"];
    [objSurvey setSurveyNo:[NSNumber numberWithInt:2]];
    [[appDele_Obj entityArray] addObject:objSurvey];
    [objSurvey release];
}
//[objSurvey release];
[[RTC_CoreDataManager shredInstance] insertEntity:@"Survey" arrayOfManagedObject:[appDele_Obj entityArray]];
if ([[appDele_Obj entityArray]count]  >0) {
    [[appDele_Obj entityArray] removeAllObjects];

}
}

所以我的问题是,
如果我在[appDele_Obj entityArray]上调用方法removeAllObjects使应用程序崩溃。为什么我无法拨打[[appDele_Obj entityArray] removeAllObjects]; 在上面的方法。任何人都可以帮我解决这个崩溃。

感谢。

1 个答案:

答案 0 :(得分:1)

这是一个记忆错误管理的简单案例。这会创建一个自动释放的对象:

Survey *objSurvey = [NSEntityDescription
    insertNewObjectForEntityForName:@"Survey"
    inManagedObjectContext:[RTC_CoreDataManager shredInstance].managedObjectContext];

然后你这样做:

[[appDele_Obj entityArray] addObject:objSurvey];
[objSurvey release];

你不应该在这里打电话给release。该对象是自动释放的 - 调用release不仅是不必要的,而且是危险的。稍后当您从数组中删除对象时,最终会过度释放其中的每个对象。这导致了崩溃。

代码中的其他一些内容:

  1. 在循环中调用托管对象上下文中的save:是不必要的,除非您在每次循环中进行新的更改。您的insertEntity:arrayOfManagedObject:方法正在进行大量不必要的工作。

  2. viewDidLoad中的数组对于您正在执行的操作不是必需的或有用的。您已经创建了对象,它们位于托管对象上下文中。完成这些对象的属性设置后,无需保留引用。继续添加对象,直到完成为止,然后告诉托管对象上下文保存。

  3. 这是一个小细节,但您命名了一个创建单例shredInstance的方法。 “Shred”几乎与您在该方法中所做的完全相反。你可能意味着sharedInstance