在我的应用程序中向左/向右滑动会触发将数据保存到我的数据库的操作。但是,快速滑动会导致许多保存失败

时间:2015-03-09 20:17:05

标签: ios objective-c cocoa-touch asynchronous parse-platform

我已经完成了类似于tinder的滑动功能,但在保存对象时遇到了问题。

我的数据库中currentUser行中有2列。一列包含一系列已接受的用户(用户已被喜欢),另一列是一个rejectUsers列,其中包含一组被拒绝的用户(已被刷过的用户)。

这是我的数据库在刷卡时更新的方式:

-(void)cardSwipedLeft:(UIView *)card;
{
    NSString *swipedUserId = [[[userBeingSwipedArray objectAtIndex:0] valueForKey:@"user"] valueForKey:@"objectId"];

    [currentUserImagesRow addUniqueObject:swipedUserId forKey:@"rejectedUsers"];
    [currentUserImagesRow saveInBackground];

当我在滑动之间离开大约2秒钟时,这很好用。但是,快速滑动会导致某些保存失败。

有没有更好的方法来做到这一点而不破坏应用程序的用户体验?

在使用for循环之前,我已经将多行保存到我的数据库中,这一直对我有用。我以为parse.com能够处理保存的速度。

我正在为这个项目使用swift和objective-c。

感谢您的时间

2 个答案:

答案 0 :(得分:2)

这是一个有趣的问题。我认为要走的路是将刷卡和节能分开一点。从需要保存的内容开始......

@property(nonatomic, strong) NSMutableArray *toSave;
@property(nonatomic, assign) BOOL busySaving;

    // on swipe
    [self.toSave addObject: currentUserImagesRow];
    [self doSaves];

- (void)doSaves {
    // we get called because of user interaction, and we call ourselves
    // recursively when finished.  keep state so these requests don't pile up
    if (self.busySaving) return;

    if (self.toSave.count) {
        self.busySaving = YES;
        [PFObject saveAllInBackground:self.toSave block:^(BOOL succeeded, NSError *error) {
            self.busySaving = NO;
            // remove just the elements that were saved, remaining aware that
            // new ones might have arrived while the last save was happening
            NSMutableArray *removes = [@[] mutableCopy];
            for (PFObject *object in self.toSave) {
                if (!object.isDirty) [removes addObject:object];
            }
            [self.toSave removeObjectsInArray:removes];
            [self doSaves];
        }];
    }
}

现在,我们可以处理小批量,而不是处理单个保存。用户滑动会导致单个保存,我们会阻止其他请求,直到当前请求完成为止。在当前请求期间,当用户继续进行交互时,我们会让更多的保存队列排队。在一个或多个记录排队的情况下,我们在保存后递归调用自己。如果没有,则递归呼叫立即结束。

编辑 - 只保存一个对象更容易,只需在最后执行相同的阻止技巧和递归调用,但无需跟踪或保存批次...

@property(nonatomic, assign) BOOL busySaving;

    // on swipe
    [self doSaves];

- (void)doSaves {
    if (self.busySaving) return;
    if (currentUserImagesRow.isDirty) {
        self.busySaving = YES;
        [currentUserImagesRow saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            self.busySaving = NO;
            [self doSaves];
        }];
    }
}

答案 1 :(得分:0)

Danh带我回答了我的问题。我方面存在一个问题,导致上述评论中提到的问题。每次滑动后都会使用相同的ID,因为我没有从保存用户对象的数组中删除它。以下是我如何解决问题并使用Danh的答案来找到我的解决方案。

-(void)cardSwipedRight:(UIView *)card
{
    NSString *swipedUserId = [[[userBeingSwipedArray objectAtIndex:0] valueForKey:@"user"] valueForKey:@"objectId"];

    // I save the swiped users id and the key for the column it will 
    // be saved in e.g. if liked then "acceptedUsers" if notLiked then
    // "rejectedUsers" so that the doSave method saves to correct column
    NSArray *array = @[swipedUserId, @"acceptedUsers"];

    [self.toSave addObject: array];

    //remove user from array since he/she is now saved
    [userBeingSwipedArray removeObjectIdenticalTo:[userBeingSwipedArray objectAtIndex:0]];

    [self doSaves];

然后:

- (void)doSaves {

    if (self.busySaving) return;

    if (self.toSave.count) {
        self.busySaving = YES;

        NSArray *arrayWithSwipedUsersIdAndKeyForColumn = [self.toSave objectAtIndex:0];

        [currentUserImagesRow addUniqueObject:[arrayWithSwipedUsersIdAndKeyForColumn objectAtIndex:0] forKey:[arrayWithSwipedUsersIdAndKeyForColumn objectAtIndex:1]];
        [currentUserImagesRow saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            self.busySaving = NO;

            //remove object that was just saved seeing as it is no longer needed
            [self.toSave removeObjectIdenticalTo:arrayWithSwipedUsersIdAndKeyForColumn];
            [self doSaves];
        }];
    }
}

如果有互联网连接,现在可以100%保存。我可以按照自己的意愿快速滑动,对象总是得到保存。