简体   繁体   English

iOS NSFileManager复制,但文件直到下一次加载才响应

[英]iOS NSFileManager copying but file doesn't respond until the next load

I am having our app move it's readonly db to the App Support directory so that content updates can update it as well(over the wire updates, not app updates). 我让我们的应用程序将其只读数据库移动到应用程序支持目录,以便内容更新也可以更新它(通过有线更新,而不是应用程序更新)。 The code below is in the app delegate to copy over the db, however on the first run NSFileManager in following attempts(during that run) to see if it is there or to load it does not see the copied file. 下面的代码在应用程序委托中,用于通过db复制,但是在第一次尝试运行NSFileManager(在运行期间)以查看是否存在或加载该文件时,看不到复制的文件。 However, it is copying it because if I close the app and restart it, everything works fine. 但是,它正在复制它,因为如果我关闭该应用程序并重新启动它,则一切正常。 I'm at a lose. 我很茫然。

NSFileManager *fm = [[[NSFileManager alloc] init] autorelease];
NSError *err = nil;
NSURL *ASD =  [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&err];

if (!err) {
    NSURL* path = [NSURL URLWithString:DATABASE_NAME relativeToURL:ASD];
    NSString *bundle =  [[ NSBundle mainBundle] pathForResource:@"datafiles/data_main" ofType:@"sqlite"];

    if ([fm fileExistsAtPath:[path path]]) {
        if([DatabaseManager isBundledDBNewerThenInUse]){
            NSLog(@"bundled db is newer");
            [DatabaseManager close];
            [fm removeItemAtURL:path error:&err];
            if (err) {
                NSLog(@"Error deleting old DB:%@",err);
            }
            else {
                [fm copyItemAtPath:bundle toPath:[path path] error:&err];
                if (err) {
                    NSLog(@"Error in copying over DB:%@",err);
                }
                else
                {
                    NSLog(@"db should have been copied over correctly");
                }
            }
        }
    }
    else{
        [fm copyItemAtPath:bundle toPath:[path path] error:&err];
        if (err) {
            NSLog(@"Error in copying over DB:%@",err);
        }
    }
}
else
{
    NSLog(@"Error in opening AS for DB copy:%@",err);
}

"[DatabaseManager isBundledDBNewerThenInUse]" returns YES if the db in the App Support directory either isn't there or has a version that is older then the one in the bundle. 如果“应用程序支持”目录中的数据库不存在或版本比捆绑软件中的数据库旧,则“ [[DatabaseManager isBundledDBNewerThenInUse]””返回YES。 It opens the db in the App Support directory thus the [DatabaseManager close] before trying to remove it. 它将在“应用程序支持”目录中打开数据库,从而在尝试删除数据库之前将其关闭。 I'm using FMDB in my DatabaseManager if that helps at all. 如果有帮助,我将在我的DatabaseManager中使用FMDB。 But as I said after that initial load if you kill the app and go back into it it work perfectly. 但是正如我说的那样,在初始加载后,如果您杀死了该应用程序并重新使用它,它将可以完美运行。 (On a database update from bundle you the db isn't updated on that first load either.) Any help would be great and if you need more info please just ask! (从bundle进行数据库更新时,数据库也不会在第一次加载时进行更新。)任何帮助都将非常有用,如果您需要更多信息,请询问! Thanks! 谢谢!

From the bahaviour you describe (ie you restart the app, then it finds the copied database) it sounds a bit like you're maybe missing a crucial database open/close call somewhere. 从您描述的行为(即重新启动应用程序,然后找到复制的数据库)来看,听起来好像您可能某个地方缺少关键的数据库打开/关闭调用。

I'd double-check where you make any calls to database open and close, and make sure it makes sense. 我会仔细检查您在何处对数据库进行任何打开和关闭调用,并确保它有意义。 Are you missing a database open call? 您是否缺少数据库公开通话? Should there be a database open call in the above code, in the cases where the database gets copied from app bundle to the app support directory, after the copy has happened? 如果复制发生后,数据库从应用程序捆绑包复制到应用程序支持目录,则上述代码中是否应该进行数据库打开调用?

The answer was dispatch_async on the main thread and then double checking the cached data and reloading it if needed. 答案是在主线程上进行dispatch_async,然后仔细检查缓存的数据并在需要时重新加载它。 Corrected code: 更正的代码:

dispatch_async(dispatch_get_main_queue(),^(){
    NSFileManager *fm = [[[NSFileManager alloc] init] autorelease];
    NSError *err = nil;
    NSURL *ASD =  [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&err];

    if (!err) {
        NSURL* path = [NSURL URLWithString:DATABASE_NAME relativeToURL:ASD];
        NSString *bundle =  [[ NSBundle mainBundle] pathForResource:@"datafiles/data_main" ofType:@"sqlite"];

        if ([fm fileExistsAtPath:[path path]]) {
            if([DatabaseManager isBundledDBNewerThenInUse]){
                NSLog(@"bundled db is newer");
                [DatabaseManager close];
                [fm removeItemAtURL:path error:&err];
                if (err) {
                    NSLog(@"Error deleting old DB:%@",err);
                }
                else {
                    [fm copyItemAtPath:bundle toPath:[path path] error:&err];
                    if (err) {
                        NSLog(@"Error in copying over DB:%@",err);
                    }
                    else
                    {
                        NSLog(@"db should have been copied over correctly");
                    }
                }
            }
        }
        else{
            [fm copyItemAtPath:bundle toPath:[path path] error:&err];
            if (err) {
                NSLog(@"Error in copying over DB:%@",err);
            }
            else
                NSLog(@"DB Copied");
        }
    }
    else
    {
        NSLog(@"Error in opening AS for DB copy:%@",err);
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM