Ios 使用核心数据挑战在线数据库持久性?

Ios 使用核心数据挑战在线数据库持久性?,ios,objective-c,cocoa-touch,core-data,parse-platform,Ios,Objective C,Cocoa Touch,Core Data,Parse Platform,这是我第一次在线进行数据库持久性/维护工作,所以我为我的代码粗心大意提前道歉。我的应用程序包括用户创建一群运动员,并在线保存他们的数据,以便从任何设备访问他们。这真是太棒了,除了每个运动员在网上都被救了两次,这让我想把头发扯下来。我已经检查了我的代码几百次,但我似乎无法找到为什么运动员在服务器上被保存了两次,结果在本地也保存了两次。我正在使用Parse.com框架。我错过什么了吗 从下拉列表调用以下方法来刷新表视图控制器 - (void)getParseData { NSLog(@"GE

这是我第一次在线进行数据库持久性/维护工作,所以我为我的代码粗心大意提前道歉。我的应用程序包括用户创建一群运动员,并在线保存他们的数据,以便从任何设备访问他们。这真是太棒了,除了每个运动员在网上都被救了两次,这让我想把头发扯下来。我已经检查了我的代码几百次,但我似乎无法找到为什么运动员在服务器上被保存了两次,结果在本地也保存了两次。我正在使用Parse.com框架。我错过什么了吗

从下拉列表调用以下方法来刷新表视图控制器

- (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的框架中似乎是不必要的。您可以在查询上设置缓存策略,并为您解决所有问题。此外,您应该只在应用程序委托中设置一次解析applicationId&clientKey。你不应该每次运行这样的方法时都重置它。好的,Logan,我现在就开始做。第一个for循环检查运动员是否是本地的,但不是在线的。第二个for循环检查运动员是否在线但不是本地的。我明白了。该问题是否与
需要的PLOADARRAY
有关?我没有在你的代码片段中找到它是如何填充的。。。除此之外,我建议在本地db为空时一步一步地执行该方法,然后再次执行(因此,您可以检查当它不为空时会发生什么)。你应该很容易发现发生了什么。