Копировать папку (с содержимым) из комплекта в каталог документов - iOS - PullRequest
12 голосов
/ 23 марта 2012

РЕДАКТИРОВАТЬ: РЕШЕНО

Спасибо, Брукс. Ваш вопрос заставил меня продолжать копаться, если файл даже существовал в моем комплекте - и это не так!

Таким образом, с помощью этого кода (также ниже): iPhone / iPad: невозможно скопировать папку из NSBundle в NSDocumentDirectory и инструкции для правильного добавления каталога в Xcode (от здесь и ниже), я смог чтобы заставить его работать.

Копировать папку в Xcode:

  1. Создайте каталог на вашем Mac.
  2. Выберите Добавить существующие файлы в ваш проект
  3. Выберите каталог, который вы хотите импортировать
  4. Во всплывающем окне убедитесь, что вы выбрали «Копировать объекты в Папка целевой группы "и" Создать ссылки на папки для любого добавленные папки "
  5. Хит "Добавить"
  6. Справочник должен отображаться синим вместо желтого.

    -(void) copyDirectory:(NSString *)directory {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:directory];
    NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:directory];
    
    if (![fileManager fileExistsAtPath:documentDBFolderPath]) {
        //Create Directory!
        [fileManager createDirectoryAtPath:documentDBFolderPath withIntermediateDirectories:NO attributes:nil error:&error];
    } else {
        NSLog(@"Directory exists! %@", documentDBFolderPath);
    }
    
    NSArray *fileList = [fileManager contentsOfDirectoryAtPath:resourceDBFolderPath error:&error];
    for (NSString *s in fileList) {
        NSString *newFilePath = [documentDBFolderPath stringByAppendingPathComponent:s];
        NSString *oldFilePath = [resourceDBFolderPath stringByAppendingPathComponent:s];
        if (![fileManager fileExistsAtPath:newFilePath]) {
            //File does not exist, copy it
            [fileManager copyItemAtPath:oldFilePath toPath:newFilePath error:&error];
        } else {
            NSLog(@"File exists: %@", newFilePath);
        }
    }
    

    }

======================== КОНЕЦ РЕДАКТИРОВАНИЯ

FRUs-паразитный-ши-на! Во всяком случае ...

Приведенный ниже код копирует мою папку из комплекта приложений в папку «Документы» в симуляторе. Однако на устройстве я получаю сообщение об ошибке и нет папки. Используя Ze Google, я обнаружил, что ошибка (260) означает, что файл (в данном случае моя папка) не существует.

Что может быть не так? Почему я не могу скопировать свою папку из пакета в Документы? Я проверил, что файлы существуют - хотя папка не отображается - потому что XCode хочет плоский файл? Превратила ли она мою папку (перетаскиваемую в Xcode) в плоский файл ресурсов?

Я благодарю вас за любую помощь.

//  Could not copy report at path /var/mobile/Applications/3C3D7CF6-B1F0-4561-8AD7-A367C103F4D7/cmsdemo.app/plans.gallery to path /var/mobile/Applications/3C3D7CF6-B1F0-4561-8AD7-A367C103F4D7/Documents/plans.gallery. error Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be completed. (Cocoa error 260.)" UserInfo=0x365090 {NSFilePath=/var/mobile/Applications/3C3D7CF6-B1F0-4561-8AD7-A367C103F4D7/cmsdemo.app/plans.gallery, NSUnderlyingError=0x365230 "The operation couldn’t be completed. No such file or directory"}

NSString *resourceDBFolderPath;

NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
                                                     NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:@"plans.gallery"];
BOOL success = [fileManager fileExistsAtPath:documentDBFolderPath];

if (success){
    NSLog(@"Success!");
    return;
} else {
    resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
                                      stringByAppendingPathComponent:@"plans.gallery"];
    [fileManager createDirectoryAtPath: documentDBFolderPath attributes:nil];
    //[fileManager createDirectoryAtURL:documentDBFolderPath withIntermediateDirectories:YES attributes:nil error:nil];

    [fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath           
                          error:&error];
}

    //check if destinationFolder exists
if ([ fileManager fileExistsAtPath:documentDBFolderPath])
{
    //removing destination, so source may be copied
    if (![fileManager removeItemAtPath:documentDBFolderPath error:&error])
    {
        NSLog(@"Could not remove old files. Error:%@",error);
        return;
    }
}
error = nil;
//copying destination
if ( !( [ fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error ]) )
{
    NSLog(@"Could not copy report at path %@ to path %@. error %@",resourceDBFolderPath, documentDBFolderPath, error);
    return ;
}

1 Ответ

11 голосов
/ 23 марта 2012

Я взял на себя смелость отредактировать часть кода, который, я чувствую, нуждается в небольшой уборке. Вы используете устаревшие методы, слишком сложные методы и просто нелепые if-elses. Я, конечно, проверил бы, что ваш путь к файлу действителен, не имея представления о том, что такое файл .gallery, и не пытаясь предоставить фиктивный файл, единственное, что я могу сделать, это то, что ваш путь к файлу просто неверен, потому что ресурс не не существует там, где вы думаете, что оно существует. (В какой-то момент вы просите скопировать файл в каталог документов, а затем проверьте, существует ли он в вашем комплекте!)

    -(void)testMethod {

    NSString *resourceDBFolderPath;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:@"plans.gallery"];
    BOOL success = [fileManager fileExistsAtPath:documentDBFolderPath];

    if (success){
        NSLog(@"Success!");
        return;
    } 
    else {
        //simplified method with more common and helpful method 
        resourceDBFolderPath = [[NSBundle mainBundle] pathForResource:@"plans" ofType:@"gallery"];

        //fixed a deprecated method
        [fileManager createDirectoryAtPath:documentDBFolderPath withIntermediateDirectories:NO attributes:nil error:nil];

        [fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath           
                              error:&error];

        //check if destinationFolder exists
        if ([ fileManager fileExistsAtPath:documentDBFolderPath])
        {
            //FIXED, another method that doesn't return a boolean.  check for error instead
            if (error)
            {
                //NSLog first error from copyitemAtPath
                NSLog(@"Could not remove old files. Error:%@", [error localizedDescription]);

                //remove file path and NSLog error if it exists.
                [fileManager removeItemAtPath:documentDBFolderPath error:&error];
                NSLog(@"Could not remove old files. Error:%@", [error localizedDescription]);
                return;
            }
        }
    }
}
...