Как использовать NSBundle для загрузки NIB из загруженного пакета и возврата к основному пакету

Вот основная проблема: мне понадобился механизм загрузки представлений, который пытается создать представление из загруженного NIB в Documents, а затем возвращается к основному комплекту, если представление не может быть создано.

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

1 ответ

Решение

Вот шаги:

1) Создайте NIB в основном комплекте обычным способом. Я рекомендую использовать файловую группу, которая указывает на папку, чтобы хранить все ресурсы вместе, которые будут использоваться для загруженного пакета. Давайте назовем это NIB_Resources.

Чтобы создать NIB в папке в Навигаторе проекта:

  1. Щелкните правой кнопкой мыши на файловой группе.
  2. Выберите Новый файл...
  3. Выберите Пользовательский интерфейс и выберите Просмотр.

2) Добавить цель для пакета активов.

  1. Нажмите на + на панели целей.
  2. Выберите шаблон Bundle в категории Framework и Library под OS X. Он находится в этой категории, потому что это тип библиотеки активов.
  3. В качестве имени продукта введите имя, которое вы хотите назвать библиотекой активов. Оставьте все остальное как есть и выберите проект, в который вы хотите добавить продукт.
  4. В настройках сборки для нового продукта измените базовый SDK с последней версии OS X на последнюю версию iOS.

3) Добавьте активы в пакет активов.

  1. Выберите фазу сборки ресурсов копирования комплектов для нового продукта.
  2. Перетащите ресурсы, которые вы хотите включить в комплект. Курсор покажет значок +, если возможно добавить ресурс.

4) Создайте комплект активов.

  1. Выберите схему для вновь созданной цели.
  2. Выберите iOS Device в качестве цели сборки.
  3. Построить.
  4. Если это было сделано правильно, продукт для нового комплекта должен был изменить цвет с красного на черный в папке "Продукты" в Навигаторе проектов.

5) Почтовый пакет активов

  1. Щелкните правой кнопкой мыши новый продукт в папке "Продукты" и выберите "Показать в Finder".
  2. Скопируйте пакет в местоположение, например, в какую-то папку в каталоге, выделенном для этого проекта.
  3. Щелкните правой кнопкой мыши каталог, содержащий пакет и, возможно, другие файлы NIB, изображения и т. Д.
  4. Выберите Сжать.

6) Загрузите комплект ресурсов в место, к которому у вас есть доступ для скачивания.

7) Загрузите заархивированный пакет активов:

Приведенный ниже код спрятан в удобных функциях, в удобном файле, который выполняет множество операций низкоуровневой файловой системы. Префикс FS относится к файловой системе.

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

Я использую NSData синхронный метод, initWithContentsOfURL:потому что вызов, скорее всего, будет сделан из вторичного потока. Основная стратегия состоит в том, чтобы загрузить zip-файл во временную папку (каталог Caches обычно является хорошим кандидатом для этой цели), прежде чем выполнять какие-либо необходимые приготовления и разархивировать файл в каталог Documents. Подход к определению встроенных статических операций в заголовочном файле был принят Apple.

// Каталог документов #define FSDocumentsDirectory    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]

// Каталог кэшей #define FSCachesDirectory       [NSSearchPathForDirectoriesInDomains(каталог NSCachesDesk для файловой системы), каталог_коптеров файлов NSC), Заданное имя файла может иметь * несколько разделителей файлов.
 */ встроенная статическая NSString* FSCachesPath(NSString * имя файла)
{
    return [FSCachesDirectory stringByAppendingPathComponent:filename];
}


/**
 * Загрузите файл с указанного URL-адреса и скопируйте его в каталог кэшей с тем же именем, что и имя URL-адреса.
 *
 * Возвращает результат.
 */ встроенная статическая BOOL FSDownloadTempFileWithURLString(NSString *urlString)
{
    NSData *data = getDataFromURL(urlString);
    if (!data) {
        // Ошибка уже зарегистрирована. return FALSE;
    }

    NSString *path = FSCachesDirectory;
    NSString *filename = [urlString lastPathComponent]; путь = [путь строки ByAppendingPathComponent: имя файла];

    NSError *error = nil;
    if (![data writeToFile: параметры пути:NSDataWritingAtomic error:&error]) {
        NSLog(@"Произошла ошибка при попытке записать файл в: %@\n", путь);
        NSLog(@"%@", ошибка); вернуть ЛОЖЬ;
    }

    return TRUE;
}

/**
 * Получить данные с указанного URL.
 */ встроенная статическая NSData* getDataFromURL(NSString *urlString)
{
    NSString *escapedUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSURL *url = [NSURL URLWithString:escapedUrlString];
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    if (!data) {
        debugLog(@"Не удалось загрузить файл: %@", escapedUrlString); вернуть ноль; } вернуть данные; }

8) Разархивируйте загрузку в каталог Documents, используя SSZipArchive или что-то подобное:

NSString * cachesPath = FSCachesPath (URL_RESOURCE_FILENAME);
if (! [SSZipArchive unzipFileAtPath: cachesPath toDestination: FSDocumentsDirectory делегат:nil]) {
    вернуть;
}

9) Наконец, попробуйте загрузить представление из NIB-файла в комплекте в каталоге Documents и вернуться к основному комплекту.

FSResourceNib Операция ниже может быть вызвана из контроллера представления, который пытается загрузить представление из Nib, например так:

UIView * view = FSResourceNib (ResourcesBundle, nibName, self);
/ **
 * Получить NIB из каталога документов, в противном случае отступите к комплекту.
 *
 * Возвращает ноль, если произошла ошибка.
 * /
встроенный статический UIView* FSResourceNib(NSString *bundleFilename, NSString *nibName, идентификатор владельца)
{
    UIView *resourceView = nil;

    // Если в пути к документам нет bundld, тогда используйте основной пакет
    NSString *resourcePath = FSDocumentsPath(bundleFilename);
    if ([[NSFileManager defaultManager] fileExistsAtPath:resourcePath]) {
        NSBundle *resourceBundle = [NSBundle bundleWithPath:resourcePath];

        @пытаться {
            // Попробуем загрузить NIB из данного пакета
            resourceView = [[resourceBundle loadNibNamed:nibName владелец: владелец опции:nil] lastObject];
        }
        @catch (исключение NSException *) {
            // ничего не делать - попробуем основной пакет
        }
    }

    // Если загрузка из данного пакета не удалась, попробуйте загрузить из основного пакета
    if (!resourceView) {
        NSBundle *resourceBundle = [NSBundle mainBundle];

        @пытаться {
            resourceView = [[resourceBundle loadNibNamed:nibName владелец: владелец опции:nil] lastObject];
        }
        @catch (исключение NSException *) {
            // ничего не делать - вернет ноль, указывая на произошедшую ошибку
        }
    }

    вернуть resourceView;
}
Другие вопросы по тегам