我已经检查了以下Q& A,虽然解决方案大致相同但问题依然存在: Saving an updated Core Data instance
Update/Edit coreData managed object
How to update existing object in 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. tableview显示新对象,在详细视图中显示两个项目。
检查它来自的区域是我的segue:
//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;
}
}
我知道它为什么会创建一个新对象,但如何在保存的同时防止这种情况发生呢?
答案 0 :(得分:1)
您问题中的代码中没有任何内容正在创建新的托管对象,因此问题出在您的代码中的其他位置,或者您错误地认为正在创建一个额外的对象 - 您不会说出你是怎么回事得出了这个结论。
要确定问题,请在awakeFromInsert
对象上实施NewLog
并添加断点。每次添加其中一个对象时都会触发,然后您可以检查堆栈跟踪以找出添加对象的位置。
<强>更新强>
好的,完成后,您会发现每次执行segue时都会创建一个新实体。不要这样做。您需要执行提取以查找现有的登录对象,并且只有在没有,或者现有的登录对象不适合的情况下,才能创建新的登录对象。
如果您进行提取并且数组中没有任何内容,则objectAtIndex:0
将崩溃。请改用firstObject
并检查结果是否为零。