0

我正在处理使用 UIManagedDocument 让我的应用程序工作。几天前我发布了另一个问题,但我还没有得到它的工作。让我们看看我能不能做得更好。
我的应用程序需要从 plist 文件中加载一些数据并用它填充数据库。然后,有些参数会不时更改,我还需要在数据库中加载和更新它们。
应用程序应遵循以下顺序:创建/打开数据库、加载数据、更新变量数据。
我的问题是在尝试正确遵循该顺序时出现的,主要是因为我无法在数据库中创建所有对象之前更新变量数据(因此必须更新 nil 变量),而我的解决方法只会导致我出乎意料崩溃和不合逻辑的行为。
这里'

在视图代码中:

- (void)viewDidLoad{
    [super viewDidLoad];
    self.database = [DataHelper opendatabaseAndUseBlock:^{
        [self setupFetchedResultsController]; // I pass this method trough a Block because I want it
                                              // to be executed once the database is opened, not before.
    }];
}  

然后我使用这个助手类“DataHelper”,它包含以下代码:

@implementation DataHelper

// This method creates and opens the database, then calls the necessary methods
+ (UIManagedDocument *)openDatabaseAndUseBlock:(completion_block_t)completionBlock
{

    NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    url = [url URLByAppendingPathComponent:@"Database"];
    UIManagedDocument *database = [[UIManagedDocument alloc] initWithFileURL:url];

    if (![[NSFileManager defaultManager] fileExistsAtPath:[database.fileURL path]]) {
        [database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            [self loadDataIntodatabase:database withSuccess:success];
            completionBlock();
        }];

    } else if (database.documentState == UIDocumentStateClosed) {
        [database openWithCompletionHandler:^(BOOL success) {
            [self loadDataIntodatabase:database withSuccess:success];
            completionBlock();
        }];

    } else if (database.documentState == UIDocumentStateNormal) {
        [self loadDataIntodatabase:database withSuccess:YES];
        completionBlock();
    }

    return database;
}


// This method loads the "static" data into the database, by reading it from a plist file.
// Once the loading finishes, it should call the last method, for updating the variable data
+ (void)loadDataIntoDatabase:(UIManagedDocument *)database withSuccess:(BOOL)success
{
    if (success) {        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
        NSArray *plistData = [NSArray arrayWithContentsOfFile:path];

        [database.managedObjectContext performBlock:^{
            for (NSDictionary *data in plistData) {
                [Object createObjectWithData:data inManagedObjectContext:database.managedObjectContext];
            }

            // Not sure what to do here!!
            //[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
                 // [DataHelper updateVariableDataOfDatabase:database];
            //}];

            // Or...?
            //[database updateChangeCount:UIDocumentChangeDone];             
            // [DataHelper updateVariableDataOfDatabase:database];

        }];

    } else {
        NSLog(@"NO SUCCESS");
    }
}

// This last method updates some parameters of the existing data
// in the database, to the ones found in another plist file
+ (void)updateVariableDataOfDatabase:(UIManagedDocument *)database
{
    // This path is provisional, should be gotten from an online resource
    NSString *path = [[NSBundle mainBundle] pathForResource:@"VariableData" ofType:@"plist"];
    NSDictionary *variables = [NSDictionary dictionaryWithContentsOfFile:path];

    [database.managedObjectContext performBlock:^{
        // Update the objects changing the values of the variable parameters
        // to the ones found in "variables"

        // Now I should save the changes, or maybe not?
        //[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:nil];
        // Or...
        //[database updateChangeCount:UIDocumentChangeDone];

    }];
}
@end

如果我使用“saveToURL”方法,虽然它看起来不正确,但它会正确执行加载顺序,因为在所有数据都加载到数据库之前不会执行最后一个方法。但是,当尝试执行许多操作时,应用程序会随机崩溃(内部有很多节省,例如删除、更新或重新加载)。
另一方面,通过使用“updateChangeCount”,应用程序不再崩溃,但序列不能正常工作:变量数据没有更新,应用程序找不到存在的对象,on数据库等等。如果我在每个动作之间等待 2 分钟左右,那么是的,它有效……但这不是我想要的。

我真的很感谢这里的一些帮助,这很浪费我的时间,而且这个项目的截止日期已经很近
了 :( 非常感谢!

4

1 回答 1

0

一段时间过去了,希望您已经在这里解决了您的问题,但以防万一我自己在过去几个月里一直在解决一堆与 UIManagedDocument 相关的问题,所以我能感受到您的痛苦。你在这里所做的与我在最近的一个项目中需要做的非常相似。

不幸的是,关于如何保存(或不保存)一般的 UIManagedDocument 的文档和各种建议似乎到处都是。我使用 saveToURL 和 updateChangeCount 方法发现了类似的结果,但是 updateChangeCount 方法似乎不太频繁地导致保存错误。但我认为这不会真正影响您的问题。

只要您只有一个线程访问您的文档,并且只要您只为您的数据打开一个文档,您实际上不需要保存,它会在该上下文中自动保存。需要保存才能将更改从该上下文推送到另一个上下文(UIManagedDocument 有两个)并最终推送到云和其他设备。您的 completionHandler 中有两层 performBlock,这可能会使事情复杂化,并导致多个线程可能以不可预测的顺序同时访问您的数据库的情况。当我完成所有预加载和设置时,它只是在 completionHandler 中按顺序进行,然后是相当于你的 opendatabaseAndUseBlock 并且它永远不会崩溃。

于 2012-06-13T18:06:15.673 回答