更改未保存在核心数据模型中(例如删除对象)

Posted

技术标签:

【中文标题】更改未保存在核心数据模型中(例如删除对象)【英文标题】:Changes are not saved in the Core Data Model (ex. delete object) 【发布时间】:2014-07-15 13:09:35 【问题描述】:

我有一个显示核心数据模型对象的 tableviewcontroller。我在其导航栏中有一个按钮,单击该按钮会删除模型中的行和对象。出于测试目的,在 AppDelegate 中,我向仅模型实体添加了一个具有 2 个属性的对象。然后我在表格视图中显示这个对象。在删除按钮上单击选定的行被删除,我已将其设置为也从数据模型中删除对象,但它不会保存更改。每次我重建和运行应用程序时,都会添加更多内容,而当我删除它们时,更改不会保留到下一次重建。如何在我的代码中解决这个问题?

AppDelegate.h

#import <UIKit/UIKit.h>
#import "favTable.h"


@interface AppDelegate : UIResponder <UIApplicationDelegate> 

    NSManagedObjectContext *managedObjectContext;
    NSManagedObject *favoritesInfo;



@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) favTable *viewController;
@property (strong, nonatomic) UINavigationController *navController;

@property (nonatomic, retain) NSManagedObject *favoritesInfo;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;


- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory; // reference files for core data


@end

AppDelegate.m

#import "AppDelegate.h"


@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize navController = _navController;

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize favoritesInfo;



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions




    NSManagedObjectContext *context = [self managedObjectContext];

    favoritesInfo = [NSEntityDescription
                                       insertNewObjectForEntityForName:@"FavoritesInfo"
                                       inManagedObjectContext:context];
    [favoritesInfo setValue:@"Product 1" forKey:@"name"];
    [favoritesInfo setValue:[NSNumber numberWithInt:15] forKey:@"score"];


    NSError *error;
    if (![context save:&error]) 
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    





    return YES;


// Core Data methods

- (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();
        
    


- (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:@"DataModel" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

    if (_persistentStoreCoordinator != nil) 
        return _persistentStoreCoordinator;
    

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"DataModel.sqlite"];

    NSError *error = nil;
    _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];



@end

favtable.h

#import <UIKit/UIKit.h>



@interface favTable : UITableViewController  <NSFetchedResultsControllerDelegate> 

    NSFetchedResultsController *fetchedResultsController;
   NSManagedObjectContext *managedObjectContext;

    NSArray *favArr;
    NSMutableArray *favName;




@property (nonatomic, retain) NSArray *favArr;


@property (strong, nonatomic) ScannedProductControllerViewController *spVC;

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, strong) NSMutableArray *favName;

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

@property (strong, nonatomic) ecoViewController *mainController;

@end

favtable.m

#import "favTable.h"
#import "AppDelegate.h"


@interface favTable ()

@end

@implementation favTable

@synthesize favArr;
@synthesize managedObjectContext;
@synthesize fetchedResultsController;
@synthesize favName;




- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];

    self.title = @"Favorites";


    self.navigationController.navigationBar.translucent = NO;

    UIBarButtonItem *delButton = [[UIBarButtonItem alloc]
                                  initWithTitle:@"Del"
                                  style: UIBarButtonItemStyleBordered
                                  target: self
                                  action:@selector(delItemToArray)];


    self.navigationItem.rightBarButtonItem = delButton;


    // passing the array of addedtofavorites to the total one with all favorites


    self.managedObjectContext = ((AppDelegate *) [UIApplication sharedApplication].delegate).managedObjectContext;



    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"FavoritesInfo" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    fetchRequest.resultType = NSDictionaryResultType;

    [fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:@"name", nil]];



      NSError *error=nil;

    self.favArr=[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];


    if (error!=nil) 
        NSLog(@" fetchError=%@,details=%@",error,error.userInfo); 
    


    self.favName = self.favName = [[self.favArr valueForKey:@"name"]mutableCopy];





- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return (interfaceOrientation == UIInterfaceOrientationPortrait);


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return [favName count];;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath



    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell;

         // Configure the cell...

    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    

    // Configure the cell... setting the text of our cell's label

    cell.textLabel.text = [favName objectAtIndex:indexPath.row];

    return cell;




//Delete Item To Array
- (void)delItemToArray 

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

    NSManagedObjectContext *context = [appDelegate managedObjectContext];

    AppDelegate *appDelegatee = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    [context deleteObject:appDelegatee.favoritesInfo];

    NSIndexPath *indexPath;
    [favName removeObjectAtIndex:indexPath.row];

    [appDelegatee saveContext]; // to save changes

    NSError *error = nil;
    if (![context save:&error])
    
        NSLog(@"Error deleting movie, %@", [error userInfo]);
    

    [self.tableView reloadData];

【问题讨论】:

它是否仅发生在重建中,或者如果您实际使用设备/模拟器中的应用程序并使用主页按钮退出它或杀死它并重新-进入它? 当我重建它时。它不是只添加一个对象,而是添加对象,同时它不跟踪删除更改。但是当我退出并租用时,更改就会保存 当你双击主页按钮并从应用切换器中终止应用然后重新打开它时怎么样?我认为这是您重建应用程序时发生的预期行为。重要的是,当您杀死应用程序并再次运行它时,它不应该发生。 当我完全删除应用程序时,它只是从在一行中添加一个对象的正常状态开始。当我重新运行应用程序时,它会继续添加一个对象,而在下次运行时忽略删除操作。当我只是使用主菜单按钮退出应用程序时,它会在我返回时正确保存更改 删除应用程序到底是什么意思?删除进程,还是从设备中完全删除整个应用程序? 【参考方案1】:

你的代码有很多问题,我不知道从哪里开始。

类名应以大写字母开头。 您在 FavTable.m 中为同一个应用程序委托单例使用了两个变量。 您正在声明一个变量 indexPath 而不对其进行初始化。 表视图的重新加载应该在 NSFetchedResultsControllerDelegate 方法中处理。 您显然没有使用 fetched results 控制器。为什么? 您的可变数组 favName 有一个令人困惑的名称,导致普遍缺乏可读性。 你写达达主义的陈述,例如self.favName = self.favName... 您的按钮处理程序方法名称 delItemToArray 同样具有冒险精神。favArr 是一个不可变数组,但您为其分配了一个可变数组。favNamefavArr 是多余的,因为 favArr 已经包含所有信息。 您正在删除期间修改favName,但没有对数据更改做出反应。 应用程序委托没有保留对 favoritesInfo 的引用的业务。 等等……等等……

简而言之,你在这方面做得太过分了。在处理 Objective-C 和 Core Data 之前,您应该花一些时间来获得一些基本的编程技能。

【讨论】:

我没有提供完整的代码并试图简化它,这导致了您提出的大部分问题。我知道我并不先进,因为我最近才开始学习objective-c。我对核心数据感兴趣,而不是基础知识。我希望你能尊重这一点。无需炫耀

以上是关于更改未保存在核心数据模型中(例如删除对象)的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:如何保存以编程方式创建的对象数据模型

使用映射模型在核心数据对象模型之间迁移

核心数据模型对象保存的最佳实践

不同模型之间的核心数据迁移?

当另一个模型正在使用该对象时,从核心数据中删除 NSManagedObject

从 Git 中检索核心数据托管对象模型