【问题标题】:Updating object value in core data is also creating a new object更新核心数据中的对象值也是创建一个新对象
【发布时间】:2014-11-25 22:53:08
【问题描述】:

我检查了以下问答,虽然解决方案大致相同,但问题仍然存在: Saving an updated Core Data instance

Update/Edit coreData managed object

How to update existing object in Core Data?

我的应用中有登录/注销功能。

Core Data 实体“NewLog”具有以下属性

String loginTime
String logoutTime
String loginStatus
String name

当我登录时,它会在核心数据中创建一个新对象。当我注销时,我有对象更新。问题是当我注销时它会更新现有对象但也会创建一个新对象。

这是我的超类中的“保存”代码,这样我就不必不断地重写它并冒着在我的类中出错的风险:

- (void) saveAndDismiss{

    NSError * error = nil;
    if ([self.managedObjectContext hasChanges]){
        if (![self.managedObjectContext save: &error]){
            NSLog(@"Save Failed: %@", [error localizedDescription]);
        }
        else {
            NSLog(@"Save Successful");
        }
    }

    [self dismissViewControllerAnimated:YES completion:nil];

}

在我的 loginViewController 实现文件中更新“loginStatus”和“logoutTime”:

- (IBAction)logOutButton:(id)sender {

    //access the managed object context and create a shortcut name
    NSManagedObjectContext *context = [self managedObjectContext];

    //refer to the entity in the core data
    NSEntityDescription *entity = [NSEntityDescription entityForName: @"NewLog" inManagedObjectContext:context];

    //create a request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity: entity];

    // Results should be in descending order of loginTime.
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"loginTime" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    //create an array of results
    NSArray *results = [context executeFetchRequest:request error:NULL];
    NewLog *latestEntity = [results objectAtIndex:0];

    //refer to the specific value that I wish to change
    NSString * statusOfLogin = latestEntity.loginStatus;

    //if the loginStatus in my app is currently YES
    if ([statusOfLogin isEqual:@"YES"]){

        //create a date formatter
        NSDateFormatter *dateformatter=[[NSDateFormatter alloc]init];

        //format as such
        [dateformatter setDateFormat:@"dd MMM yyyy , HH:mm:ss"];

        //convert to a string
        NSString *dateInStringFormated=[dateformatter stringFromDate:[NSDate date]];

        //hide logout button and display login button
        _logOutButton.alpha = 0.0;
        _loginButtonStatus.alpha = 1.0;

        //status declared as String in .h file
        status = @"NO";

        //update the object found in "latestEntity"
        latestEntity.logoutTime = dateInStringFormated;
        //set the login status to be NO
        latestEntity.loginStatus = status;

        //BOOL declared in the .h file
        logStatus = false;


        self.loginLabel.text = @"Logged Out";
        self.dateLabel.text = dateInStringFormated;

        [super saveAndDismiss];

    }

}

当我保存更新的数据时,它会创建一个仅包含 logoutTime 和 loginStatus 的新对象。

有没有办法阻止新对象的创建?

谢谢

编辑

我知道它正在通过以下方式创建一个新对象: 1. SQL 文件显示具有上述内容的新对象 - logoutTime 和 loginStatus 2. 表格视图显示新对象,并在其详细视图中显示这两个项目。

检查它来自的区域是我的选择:

//prepare for segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    //first check whether the segue is equal to our transition name
    if([[segue identifier]isEqualToString:@"loginSegue"])
    {
        //tell the segue where to go
        UINavigationController *navigationController = segue.destinationViewController;

        //create reference to view controller
        LoginViewController *loginVC= (LoginViewController*) navigationController.topViewController;

        //create the new object
        NewLog *addLogDetails = [NSEntityDescription insertNewObjectForEntityForName:@"NewLog" inManagedObjectContext: [self managedObjectContext]];

        loginVC.logEntry = addLogDetails;
    }
}

我知道它为什么要创建一个新对象,但是如何在保持保存能力的同时防止这种情况发生?

【问题讨论】:

    标签: ios objective-c iphone core-data


    【解决方案1】:

    您问题的代码中没有任何内容是创建新的托管对象,因此问题出在代码中的其他地方,或者您误认为正在创建一个额外的对象 - 您没有说明您是如何做到这一点的结论。

    要确定问题,请在您的 NewLog 对象上实现 awakeFromInsert 并添加断点。每次添加这些对象之一时都会触发此问题,然后您可以检查堆栈跟踪以找出添加对象的位置。

    更新

    好的,完成后,您会看到每次执行 segue 时都在创建一个新实体。不要那样做。您需要执行 fetch 以查找现有登录对象,并且只有在没有登录对象或现有登录对象不合适时,才创建一个新对象。

    如果您执行 fetch 并且数组中没有任何内容,objectAtIndex:0 将崩溃。请改用firstObject 并检查其结果是否为零。

    【讨论】:

    • 我知道它正在创建一个新对象,因为我每次运行和测试时都会检查 SQL 文件,并且 tableview 还显示新对象以及显示详细信息的详细信息视图,正如我提到的:“当我保存更新的数据,它会创建一个仅包含 logoutTime 和 loginStatus 的新对象。”。否则我不会发布这个问题。不过,我会尝试使用 awakeFromInsert 的建议。
    • 在使用核心数据时,如果不是您的参考点,请获取并检查计数 sql 文件
    • 发现 segue 是我的下一个视图控制器类中的问题。我知道为什么它现在要创建一个新对象,但是如何在仍然能够保存更新信息的同时防止它?
    • 你有一些我可以尝试的代码吗?我已经尝试过我的方法,当我在核心数据中有对象时工作正常,但是没有任何对象的测试会引发错误消息,因为“objectsAtIndex:0”不再正确。我已经尝试过 "if([statusOfLogin isEqual:@"NO"] || latestEntity == nil)" 但这仍然会引发与索引引用 0 相同的问题。
    • 如果数组中没有任何内容,objectAtIndex:0 将崩溃。改用firstObject 并检查结果是否为nil
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多