gpt4 book ai didi

ios - 解析保存最终在应用程序快速终止时最终失败

转载 作者:行者123 更新时间:2023-12-01 15:58:57 25 4
gpt4 key购买 nike

我有一个使用parse将数据存储在parse的本地数据存储中并将该数据备份到parse云的应用程序。通常,这很好。在本地和云中存储数据的关键代码如下:

- (void)store:(PFObject*) parseObject {
if (parseObject) {
[parseObject pinInBackground];
[parseObject saveEventually];
} else
NSLog(@"Err :Store was passed a nil?");
}

我有一个应用程序,其中一些用户说如果他们设置数据然后此后“很快”终止该应用程序,则会丢失数据。

在更新用户数据时,该函数传递了大约10项或更多项以快速连续存储。

我已经通过执行以下测试此方案。我将所有项目都存储起来,并设置一个断点来完成。然后,我让该应用再次运行,并通过按Home键并刷掉该应用将其终止。它还有一秒左右的运行时间,但关键是在任何情况下存储都已在每个对象上完成。

我确实确实发现数据可能会丢失。似乎仅由于这些方法已运行而不能保证将存储数据。明确地说,我了解这些功能不会存储数据,但是我认为(假设)在完成数据后可以保证存储数据的意图。

我将添加以下内容:
  • 以后的数据更容易丢失。也就是说,解析似乎顺序地处理了数据。
  • 您可以找到数据固定在本地数据存储区中,但没有使其解析(几乎就像固定有效,但最终却没有)。
  • 较旧(较慢)的设备比较新的设备更容易受到影响。实际上,我很难使它在新的iPad mini上实现,但可以在iPhone 4上实现。
  • 需要启用网络,但是如果您模拟了不良网络(使用设备上的iOS设置),则更容易实现。
  • 数据量很小(100字节),我没有达到解析保存限制。
  • 我正在使用解析版本1.8.4。

  • 我的问题如下:

    我期望一旦这些调用返回,任务将被锁定并且将始终完成。我了解无法保证最终会花多长时间,但是即使在下次运行该应用程序时,它也始终会“最终”完成。我做错什么了吗?我是否会遭受此类数据丢失并需要采取进一步的预防措施?有没有人有任何经验或建议?即使仅仅是因为您发现它对您有用?可能是我在其他地方做了一些愚蠢的事情,但是很难看出来。

    谢谢你的时间。

    最佳答案

    我在这里发布我自己的结果,也许它们对某人有用。回顾了Parse的源代码后,我对它的工作方式有所了解,我不能保证这是最终的词或整个故事,但它符合事实。

    Parse现在是开源的,因此您至少可以去看看,如果有问题,请尝试确定正在发生的事情。

    Parse in github

    解析保留任务队列,严格按照请求的顺序对其进行处理。无论任务是在前台(阻止)还是在后台(有或没有回调)请求的,都是如此。同样,任务是查询,固定,保存等也没关系,它们都在任务列表中排队。任务列表保留在内存中,如果应用程序被挂起然后终止,或者在处理所有任务之前终止或终止,则任务丢失。

    因此,如果parse没有执行任何操作,并且您请求固定或保存,它将启动此操作,并且很可能一切都很好。

    如果解析很忙(按照我上面的描述),则saveEventually在队列的末尾等待处理。在处理此任务之前,您可能会遇到parse未记录saveEventually的风险。请注意,重要的是要理解,按过程我的意思是查看任务-不是完成任务-只是简单地查看任务是什么,并在saveEventually情况下进行记录。

    我不一定认为这是一个错误。我的问题是我正在将saveEventually视为数据库提交。我知道这并不意味着它已经在云中了,我只是假定将saveEvent最终返回时以非 Volatile 方式存储将其推送到云中的请求。一旦完成处理,它就像是一次提交,它将最终存储到云中,但是您无法确定它是否已通过编程方式进行处理(saveEventually回调在完成时未记录saveEventually)。

    如果应用程序是裸体应用程序,那么用户已经采取了一些措施,他们应该知道自己在做什么。但是,如果您声明您的应用程序具有后台任务,则可以确保如果用户按下Home键或移至另一个应用程序-我认为他们有权这样做,则仍有线程可以执行。我已经这样做了,似乎可以防止丢失数据。我基本上可以确保任务列表得到处理,并且即使应用程序进入后台,Parse也会注意到我所有的saveEventuallys。

    iOS Background Execution

    很难确定何时终止该线程。在我的应用程序中,我成对固定并最终保存。 Pin确实有回调,所以我保持出色的Pin数。当它达到零时,我等待一分钟,然后关闭线程。这给了1分钟时间来执行最终的save最终,这似乎在测试中绰绰有余。如果那时我可以访问互联网,则在稍后或下次运行该应用时会注意saveEventually。

    我认为您必须是Parse的大量用户才能看到此问题。我有很多小的数据对象分布在不相关的不同表上。这将创建许多要备份的查询和固定,如果您可以一次性插入一个表或一个数据Blob,就不会看到我描述的问题。

    根据注释请求的示例代码(7Jan16编辑)

    下面是我用来实现上述目的的代码的核心。如果使用它,则需要对其进行更改。我建议也阅读上面的后台任务链接。后台线程使应用程序保持足够的 Activity 状态,以便解析仍可以处理其未完成的任务。

    该代码块的目的是提供一个辅助函数,以跟踪所有待解析的未决请求。当它被调用时,它将启动一个后台线程(startPinMonitor)。仅启动一个监视器,这在startPinMonitor中进行了检查。我的代码在UI线程上运行,但是否则您可能需要一些同步逻辑。

    - (void)store:(PFObject*) parseObject {
    if (parseObject) {
    if (self.outStandingPins == 0)
    [self startPinMonitor];

    self.outStandingPins++;

    [parseObject pinInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
    self.outStandingPins--;
    if(!succeeded)
    NSLog(@"Err : Pin failed?");
    }];

    [parseObject saveEventually];
    }
    }

    此段代码的目的是使应用程序保持运行状态,直到处理完所有剩余的解析操作为止。它首先检查监视器是否已经激活。每30秒调用一次“checkPinStatus”方法,并在处理完所有引脚后终止。未完成引脚的日志对于检测正确操作非常有用。按下Home键后,您应该能够验证该应用程序仍在运行。如果注释掉“beginBackgroundTaskWithExpirationHandler”方法,则可以确定此代码试图实现的行为差异。
    -(void) startPinMonitor {
    if (![self.myTimer isValid]) {
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:30
    target:self
    selector:@selector(checkPinStatus)
    userInfo:nil
    repeats:YES];

    self.myBackgroundTask = [[UIApplication sharedApplication]
    beginBackgroundTaskWithExpirationHandler:^{
    NSLog(@"Background tasks stopped");
    }];
    }
    }

    -(void) checkPinStatus {
    NSLog(@"Current outStandingPins=%i", self.outStandingPins);

    if (self.outStandingPins == 0) {
    [self.myTimer invalidate];
    [[UIApplication sharedApplication]
    endBackgroundTask:self.myBackgroundTask];
    }
    }

    关于ios - 解析保存最终在应用程序快速终止时最终失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32617917/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com