Как использовать NSBundle для загрузки NIB из загруженного пакета и возврата к основному пакету
Вот основная проблема: мне понадобился механизм загрузки представлений, который пытается создать представление из загруженного NIB в Documents, а затем возвращается к основному комплекту, если представление не может быть создано.
Я провел много исследований и проб и ошибок, прежде чем заставить это работать, поэтому я хотел поделиться решением с другими.
1 ответ
Вот шаги:
1) Создайте NIB в основном комплекте обычным способом. Я рекомендую использовать файловую группу, которая указывает на папку, чтобы хранить все ресурсы вместе, которые будут использоваться для загруженного пакета. Давайте назовем это NIB_Resources.
Чтобы создать NIB в папке в Навигаторе проекта:
- Щелкните правой кнопкой мыши на файловой группе.
- Выберите Новый файл...
- Выберите Пользовательский интерфейс и выберите Просмотр.
2) Добавить цель для пакета активов.
- Нажмите на + на панели целей.
- Выберите шаблон Bundle в категории Framework и Library под OS X. Он находится в этой категории, потому что это тип библиотеки активов.
- В качестве имени продукта введите имя, которое вы хотите назвать библиотекой активов. Оставьте все остальное как есть и выберите проект, в который вы хотите добавить продукт.
- В настройках сборки для нового продукта измените базовый SDK с последней версии OS X на последнюю версию iOS.
3) Добавьте активы в пакет активов.
- Выберите фазу сборки ресурсов копирования комплектов для нового продукта.
- Перетащите ресурсы, которые вы хотите включить в комплект. Курсор покажет значок +, если возможно добавить ресурс.
4) Создайте комплект активов.
- Выберите схему для вновь созданной цели.
- Выберите iOS Device в качестве цели сборки.
- Построить.
- Если это было сделано правильно, продукт для нового комплекта должен был изменить цвет с красного на черный в папке "Продукты" в Навигаторе проектов.
5) Почтовый пакет активов
- Щелкните правой кнопкой мыши новый продукт в папке "Продукты" и выберите "Показать в Finder".
- Скопируйте пакет в местоположение, например, в какую-то папку в каталоге, выделенном для этого проекта.
- Щелкните правой кнопкой мыши каталог, содержащий пакет и, возможно, другие файлы NIB, изображения и т. Д.
- Выберите Сжать.
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; }