【问题标题】: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];
}

【问题讨论】:

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

标签: ios uitableview core-data save


【解决方案1】:

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

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

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

【讨论】:

  • 我没有提供完整的代码并试图简化它,这导致了您提出的大部分问题。我知道我并不先进,因为我最近才开始学习objective-c。我对核心数据感兴趣,而不是基础知识。我希望你能尊重这一点。无需炫耀
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 2016-11-07
相关资源
最近更新 更多