iPhone (iOS): ошибка копирования файлов из основного пакета в папку с документами

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

dstPath не должен существовать до операции.

Как мне лучше всего выполнить копирование прямо в корень документов? Причина, по которой я хочу это сделать, - разрешить поддержку совместного использования файлов iTunes.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Populator"];

  NSLog(@"\nSource Path: %@\nDocuments Path: %@", sourcePath, documentsDirectory);

  NSError *error = nil;

  if([[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:documentsDirectory error:&error]){
    NSLog(@"Default file successfully copied over.");
  } else {
    NSLog(@"Error description-%@ \n", [error localizedDescription]);
    NSLog(@"Error reason-%@", [error localizedFailureReason]);
  }
  ...
  return YES;
}

Спасибо


person Jack    schedule 14.07.2010    source источник


Ответы (2)


Путь назначения должен содержать имя копируемого элемента, а не только папку с документами. Пытаться:

if([[NSFileManager defaultManager] copyItemAtPath:sourcePath 
          toPath:[documentsDirectory stringByAppendingPathComponent:@"Populator"]
          error:&error]){
...

Изменить: Извините, я неправильно понял ваш вопрос. Не знаю, есть ли лучший вариант, чем перебирать содержимое папки и копировать каждый элемент отдельно. Если вы ориентируетесь на iOS4, вы можете использовать для этого функцию NSArray -enumerateObjectsUsingBlock::

NSArray* resContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:copyItemAtPath:sourcePath error:NULL];
[resContents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        NSError* error;
        if (![[NSFileManager defaultManager] 
                  copyItemAtPath:[sourcePath stringByAppendingPathComponent:obj] 
                  toPath:[documentsDirectory stringByAppendingPathComponent:obj]
                  error:&error])
            DLogFunction(@"%@", [error localizedDescription]);
    }];

P.S. Если вы не можете использовать блоки, вы можете использовать быстрое перечисление:

NSArray* resContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:copyItemAtPath:sourcePath error:NULL];

for (NSString* obj in resContents){
    NSError* error;
    if (![[NSFileManager defaultManager] 
                 copyItemAtPath:[sourcePath stringByAppendingPathComponent:obj] 
                 toPath:[documentsDirectory stringByAppendingPathComponent:obj]
                 error:&error])
            DLogFunction(@"%@", [error localizedDescription]);
    }
person Vladimir    schedule 14.07.2010
comment
Спасибо за ответ, но я не хочу этого делать. Я хочу скопировать содержимое папки Populator в корень каталогов (а не в папку Populator в корне документов). То, что вы говорите, работает, но это не то, чего я хочу достичь. - person Jack; 14.07.2010
comment
Большое спасибо, это недоразумение почти наверняка было моей ошибкой. Я использую этот код для приложения для iPad, поэтому буду ориентироваться на iOS 3.2, хотя в конечном итоге он будет поддерживать iOS4. Спасибо за код, есть идеи, как заставить его работать для 3.2 (без блоков)? - person Jack; 14.07.2010
comment
Я добавил код, используя быстрое перечисление. Решение с блоками было больше для меня - блоки - это новая концепция для меня. - person Vladimir; 14.07.2010
comment
Большое вам спасибо, очень ценю ваши усилия. - person Jack; 14.07.2010

примечание: не выполняйте длительную операцию в didFinishLaunchingWithOptions: это концептуальная ошибка. Если эта копия займет слишком много времени, сторожевой пес убьет вас. запустить его во вторичном потоке или NSOperation ... Я лично использую процесс таймера.

person ingconti    schedule 04.09.2011