iOS NSFileManager копирует, но файл не отвечает до следующей загрузки - PullRequest
0 голосов
/ 18 ноября 2011

Я перевожу наше приложение только для чтения в каталог поддержки приложений, чтобы обновления содержимого могли также обновлять его (по проводным обновлениям, а не обновлениям приложений).Приведенный ниже код находится в делегате приложения для копирования через базу данных, однако при первом запуске NSFileManager в следующих попытках (во время этого запуска), чтобы увидеть, есть ли он или загрузить, он не видит скопированный файл.Тем не менее, он копирует его, потому что, если я закрою приложение и перезапустить его, все работает нормально.Я в растерянности.

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]" возвращает YES, если БД в каталоге поддержки приложений либо отсутствует, либо имеет версию, которая старше, чем версия в комплекте,Он открывает базу данных в каталоге поддержки приложений, поэтому [DatabaseManager close], прежде чем пытаться удалить его.Я использую FMDB в моем DatabaseManager, если это вообще помогает.Но, как я сказал после этой начальной загрузки, если вы убьете приложение и вернетесь в него, оно будет работать отлично.(При обновлении базы данных из комплекта вы также не обновляете базу данных при первой загрузке.) Любая помощь будет отличной, и если вам нужна дополнительная информация, просто спросите!Спасибо!

Ответы [ 2 ]

0 голосов
/ 23 ноября 2011

Ответ был dispatch_async в главном потоке, а затем дважды проверял кэшированные данные и перезагружал их при необходимости. Исправленный код:

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);
    }
});
0 голосов
/ 18 ноября 2011

Из описанного вами поведения (то есть вы перезапускаете приложение, затем оно находит скопированную базу данных) это звучит немного похоже на то, что вы, возможно, пропускаете важный вызов открытия / закрытия базы данных где-то.

Я быперепроверьте, где вы делаете какие-либо вызовы, чтобы открыть и закрыть базу данных, и убедитесь, что это имеет смысл.Вам не хватает открытого вызова базы данных?Должен ли быть вызов открытия базы данных в приведенном выше коде, в случаях, когда база данных копируется из комплекта приложения в каталог поддержки приложения после того, как происходит копирование?

...