Как получить все пути ресурсов в моем пакете рекурсивно в iOS?

У меня есть "распакованная" папка в моем приложении. Мне нужно получить пути к ресурсам для всех файлов типа txt. Я использовал это,

NSArray *filePaths = [NSBundle pathsForResourcesOfType:@"txt" inDirectory:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/unzipped"]];

Но он только получает файлы в первом каталоге. Есть ли рекурсивная версия этого где-то, что я просто отсутствую?

Ответ 1

Я получил эту работу, используя код, отправленный @rekle в качестве отправной точки. Хитрость заключается в использовании NSDirectoryEnumerator, который будет делать это рекурсивно. Здесь функция, которую я написал, в случае, если кому-то это нужно.

- (NSArray *)recursivePathsForResourcesOfType:(NSString *)type inDirectory:(NSString *)directoryPath{

    NSMutableArray *filePaths = [[NSMutableArray alloc] init];

    // Enumerators are recursive
    NSDirectoryEnumerator *enumerator = [[[NSFileManager defaultManager] enumeratorAtPath:directoryPath] retain];

    NSString *filePath;

    while ((filePath = [enumerator nextObject]) != nil){

        // If we have the right type of file, add it to the list
        // Make sure to prepend the directory path
        if([[filePath pathExtension] isEqualToString:type]){
            [filePaths addObject:[directoryPath stringByAppendingPathComponent:filePath]];
        }
    }

    [enumerator release];

    return [filePaths autorelease];
}

Swift, используя NSURL

func recursivePathsForResources(type type: String) -> [NSURL] {

    // Enumerators are recursive
    let enumerator = NSFileManager.defaultManager().enumeratorAtPath(bundlePath)
    var filePaths = [NSURL]()

    while let filePath = enumerator?.nextObject() as? String {

        if NSURL(fileURLWithPath: filePath).pathExtension == type {
            filePaths.append(bundleURL.URLByAppendingPathComponent(filePath))
        }
    }

    return filePaths
}

Ответ 2

Просто обновите этот метод, чтобы разрешить любые типы файлов (nil) и предоставить правильный формат пути

- (NSArray *)recursivePathsForResourcesOfType:(NSString *)type inDirectory:(NSString *)directoryPath{

    NSMutableArray *filePaths = [[NSMutableArray alloc] init];
    NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:directoryPath];

    NSString *filePath;

    while ((filePath = [enumerator nextObject]) != nil){
        if (!type || [[filePath pathExtension] isEqualToString:type]){
            [filePaths addObject:[directoryPath stringByAppendingPathComponent:filePath]];
        }
    }

    return filePaths;
}

Ответ 3

Попробуйте что-то вроде этого:

NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSError *error = nil;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:&error];

'files' будет массивом строк, содержащих все имена файлов в этом пути...

Ответ 4

Swift 3.1 версия ответа от smokinggoyster

func recursivePathsForResources(type: String, in directoryPath: String) -> [String] {
    // Enumerators are recursive
    let enumerator = FileManager.default.enumerator(atPath: directoryPath)
    var filePaths: [String] = []

    while let filePath = enumerator?.nextObject() as? String {

        if URL(fileURLWithPath: filePath).pathExtension == type {
            filePaths.append(directoryPath.byAppending(pathComponent: filePath))
        }
    }
    return filePaths
}

Ответ 5

Перед копированием подумайте о создании символической ссылки. Вы можете создать символическую ссылку одна в папку с большим количеством элементов. И он будет работать в большинстве ситуаций.

Вы не сможете создавать другой поток, ожидая окончания работы и т.д.