这是我第一次在线进行数据库持久化/维护方面的工作,所以我提前为我草率的代码道歉。我的应用程序包括用户创建一群运动员并在线保存他们的数据,以便可以从任何设备访问他们。这非常有效,除了每个运动员都在网上保存两次,这让我想撕掉我的头发。我已经检查了我的代码数百次,但我似乎无法找到为什么运动员在服务器上被保存了两次,导致在本地也保存了 2 次。我正在使用 Parse.com 框架。我错过了什么吗?
以下方法从下拉列表中调用以在 TableView Controller 上刷新。
- (void)getParseData {
NSLog(@"GET PARSE DATA WAS CALLED");
if(self.syncing != TRUE){
NSLog(@"GET PARSE DATA RAN");
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = NSDateFormatterLongStyle;
PFQuery *query = [PFQuery queryWithClassName:@"Athlete"];
[self populateAthleteArray];
if (self.athleteArray.count == 0) {
NSLog(@"ATHLETE ARRAY IS EMPTY");
// If the athlete array has no objects, download all objects from the database.
[query findObjectsInBackgroundWithBlock: ^(NSArray *objects, NSError *error) {
self.syncing = TRUE;
if (!error) {
self.syncing = FALSE;
for (PFObject * object in objects) {
Athlete *newAthlete = [NSEntityDescription insertNewObjectForEntityForName:@"Athlete" inManagedObjectContext:_managedObjectContext];
newAthlete.first = object[@"first"];
newAthlete.last = object[@"last"];
newAthlete.updatedAt = [dateFormatter stringFromDate:[object updatedAt]];
newAthlete.objectId = [object objectId];
[_managedObjectContext save:nil];
}
self.syncing = FALSE;
}
else {
self.syncing = FALSE;
NSLog(@"Error: %@ %@", error, [error userInfo]);
}
if(self.needToUploadArray.count > 0){
[PFObject saveAllInBackground:self.needToUploadArray target:nil selector:@selector(emptyUploadArray)];
}
}];
[self populateAthleteArray];
[self.tableView reloadData];
}
else {
NSLog(@"ATHLETE ARRAY HAS ATHLETES ALREADY");
// Athlete array has athletes already
NSMutableArray *athletesToUpload = [NSMutableArray array];
// Placeholder array for athletes that aren't in the database.
for (Athlete *athlete in athleteArray) {
if (athlete.objectId.length == 0 || athlete.objectId == nil) {
// If the objectId is nil, it wasn't uploaded to the database. Add to placeholder array.
[athletesToUpload addObject:athlete];
}
}
[query findObjectsInBackgroundWithBlock: ^(NSArray *objects, NSError *error) {
self.syncing = TRUE;
if (!error) {
// Downloaded all athletes successfully
self.syncing = FALSE;
BOOL found = FALSE;
[self populateAthleteArray];
NSMutableArray *athletesToDelete = [NSMutableArray array];
for (Athlete * athlete in athleteArray) {
for (PFObject * object in objects) {
// Check to see each local athlete exists in the online database
if ([object.objectId isEqualToString:athlete.objectId]) {
// Athlete was find in the online database
found = TRUE;
break;
}
}
if (found != TRUE) {
NSLog(@"%@ was not found online.",athlete.first);
if(athlete.objectId.length > 0){
NSLog(@"%@ was deleted online. delete them locally",athlete.first);
[athletesToDelete addObject:athlete];
}
else{
// No athlete in the local database matched any of the athletes online
PFObject *onlineAthlete = [PFObject objectWithClassName:@"Athlete"];
onlineAthlete[@"first"] = athlete.first;
onlineAthlete[@"last"] = athlete.last;
PFFile *imageFile = [PFFile fileWithName:[NSString stringWithFormat:@"%@%@MedicalRelease.jpg", athlete.first, athlete.last] data:athlete.medical_release_image];
onlineAthlete[@"medical_release_image"] = imageFile;
[onlineAthlete saveInBackgroundWithBlock: ^(BOOL succeeded, NSError *error) {
self.syncing = TRUE;
if (succeeded) {
NSLog(@"SAVED SUCCESSFULLY");
self.syncing = FALSE;
PFQuery *query = [PFQuery queryWithClassName:@"Athlete"];
[query orderByDescending:@"createdAt"];
[query getFirstObjectInBackgroundWithBlock: ^(PFObject *object, NSError *error) {
Athlete *athleteToChange = [self findAthlete:athlete.objectId];
[athleteToChange setObjectId:[object objectId]];
[_managedObjectContext save:nil];
}];
}
}];
}
}
found = FALSE;
}
if(athletesToDelete.count > 0){
for(id athlete in athletesToDelete){
NSManagedObject *eventToDelete = athlete;
[_managedObjectContext deleteObject:eventToDelete];
[athleteArray removeObjectAtIndex:[athleteArray indexOfObject:athlete]];
[self.tableView reloadData];
NSError *error = nil;
if (![_managedObjectContext save:&error]) {
NSLog(@"there is an error: %@", error);
}
}
}
for (PFObject *object in objects) {
// Loop through every athlete downloaded
for (Athlete * athlete in athleteArray) {
// For every object downloaded, compare it to every athlete in the local database.
if ([object.objectId isEqualToString:athlete.objectId]) {
// If the object's id matches the local athletes id, we found the object
if ([object updatedAt] >= [dateFormatter dateFromString:athlete.updatedAt]) {
// If the object has been updated more recently than the athlete, update the local athlete
Athlete *sameAthlete = [self findAthlete:athlete.objectId];
sameAthlete.first = object[@"first"];
sameAthlete.last = object[@"last"];
sameAthlete.updatedAt = [dateFormatter stringFromDate:[object updatedAt]];
sameAthlete.address = object[@"address"];
sameAthlete.objectId = [object objectId];
[_managedObjectContext save:nil];
}
found = TRUE;
// The athlete was found in the database
break;
}
}
if (found != TRUE) {
// We looped through all the local athletes, the object downloaded isn't in the local database; add them.
Athlete *athlete = [NSEntityDescription insertNewObjectForEntityForName:@"Athlete" inManagedObjectContext:_managedObjectContext];
athlete.first = object[@"first"];
athlete.last = object[@"last"];
athlete.objectId = [object objectId];
athlete.address = object[@"address"];
athlete.updatedAt = [dateFormatter stringFromDate:[object updatedAt]];
[_managedObjectContext save:nil];
}
// Reset flag var
found = FALSE;
}
}
else {
self.syncing = FALSE;
NSLog(@"Error: %@ %@", error, [error userInfo]);
}
self.syncing = FALSE;
}];
if (athletesToUpload.count > 0) {
for (Athlete *athlete in athletesToUpload) {
PFObject *upload = [PFObject objectWithClassName:@"Athlete"];
upload[@"first"] = athlete.first;
upload[@"last"] = athlete.last;
PFFile *imageFile = [PFFile fileWithName:[NSString stringWithFormat:@"%@%@MedicalRelease.jpg", athlete.first, athlete.last] data:athlete.medical_release_image];
upload[@"medical_release_image"] = imageFile;
[upload saveInBackgroundWithBlock: ^(BOOL succeeded, NSError *error) {
if (succeeded) {
PFQuery *uploadQuery = [PFQuery queryWithClassName:@"Athlete"];
[uploadQuery orderByDescending:@"createdAt"];
[uploadQuery getFirstObjectInBackgroundWithBlock: ^(PFObject *object, NSError *error) {
[athlete setObjectId:[object objectId]];
}];
}
}];
}
}
[self populateAthleteArray];
[self.tableView reloadData];
}
}
}
最佳答案
在注释标记的分支中 //本地数据库中没有运动员匹配任何在线运动员
您正在创建一个新的 PFObject
并将其保存到 Parse。以我的理解,这不应该是正确的,因为运动员不在本地数据库中而是在线。
关于ios - 具有核心数据的具有挑战性的在线数据库持久性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22582362/