deleteObjectAndAllDependencies

deleteObjectAndAllDependencies

以下代码是我公司的另一位员工编写的,但是我现在必须解决性能问题...

方法deleteObjectAndAllDependencies从SQLite数据库中删除项目和相关数据...

tableView仍然无法使用,仍然执行所有操作。我如何加快这个过程?不使用功能。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        if ([[SARAM RAM] selectedProjektIndex] == indexPath.row) [[SARAM RAM] setSelectedProjektIndex:0];

        NSBlockOperation *start = [NSBlockOperation blockOperationWithBlock:^{

            [[SAAufmassProject popFromDatabaseForGUID:[SARAM projektPool][indexPath.row]] deleteObjectAndAllDependencies];

            [[self projectData] removeObjectAtIndex:indexPath.row];
        }];

        NSBlockOperation *refresh = [NSBlockOperation blockOperationWithBlock:^{

            [tableView beginUpdates];

            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

            [tableView endUpdates];

            [self dataHasBeenDeleted];
        }];

        [refresh addDependency:start];

        [[NSOperationQueue currentQueue] addOperation:start];
        [[NSOperationQueue currentQueue] addOperation:refresh];
    }
}

最佳答案

这段代码很奇怪。它创建两个同步操作,使一个依赖于另一个。然后,它将这些操作添加到当前队列(主队列!)中。这有点低效,并且无法获得任何性能优势。更糟糕的是,似乎有人希望通过采用异步模式使此代码具有更高的响应能力,但并没有完全实现这一目标。 (这可能表明存在一些更深层次的体系结构问题,这使这一工作变得困难。)

撇开这一点,您可能想要的是在更新主线程中的模型对象和UI时触发数据库的异步更新:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        if ([[SARAM RAM] selectedProjektIndex] == indexPath.row) [[SARAM RAM] setSelectedProjektIndex:0];

        // get reference to the guid

        NSString *guid = [SARAM projektPool][indexPath.row]];

        // perform the deletion in some background queue

        [self.databaseQueue addOperationWithBlock:^{
            [[SAAufmassProject popFromDatabaseForGUID:guid] deleteObjectAndAllDependencies];
        }];

        // meanwhile, back on the ranch, we'll update the table view

        [[self projectData] removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self dataHasBeenDeleted];
    }
}


问题是,这引发了一些问题:


您的SQLite实现是否支持从后台线程进行更新?许多简单的实现将无法正确处理此问题。
我很担心projektPool使用与projectData相同的索引。是deleteObjectAndAllDependencies更新前者,而后者是用此方法更新的。我怀疑这将是一个问题。
我想知道popFromDatabaseForGUIDdeleteObjectAndAllDependenciesprojektPoolprojectData之间是否存在更深的相互依赖性。我还想知道它们是否真的是线程安全的(例如,当在后台运行这些东西时调用cellForRowAtIndexPath时,模型和数据库是否处于一致状态)?


最重要的是,就我之前的观点而言,现有代码表明存在较早的并发处理尝试,我愿意打赌,某些更深层次的体系结构问题阻碍了这一努力。问题是我们在这里没有足够的能力来诊断更深层次的问题(我怀疑设计太复杂了,无法在这样的论坛中有效地传达出来)。

假设(a)确实存在更深层次的建筑问题; (b)对该代码的重构超出了您的预期范围,您可能希望查看该代码以查看是否有任何战术上的机会来提高性能。例如,如果deleteObjectAndAllDependencies正在执行大量单独的SQL语句来更新数据库,您是否正在使用事务来加快速度?使用SQLite可能会对性能产生巨大影响。

最重要的是,我可能会通过“工具”(包括“记录等待线程”选项)中的“时间探查器”工具运行此代码,并找出性能问题的根源。查看是否可能存在与SQL有关的战术机会(例如事务,索引等)。

10-07 14:18