Совместное использование вложенных активов между приложением и расширением
Расширение My Photo Sharing планирует использовать те же дизайнерские активы (для навигации и добавления "марок/наклеек" к фотографии).
Как поясняется в Руководстве по дизайну приложений Sandbox, группы изолированных приложений которые должны обмениваться файлами и другой информацией, могут запросить контейнер как часть их прав. Эти каталоги хранятся в ~/Library/Group Containers/. https://developer.apple.com/documentation/foundation/nsfilemanager/1412643-containerurlforsecurityapplicati
В настоящее время активы добавляются или загружаются и добавляются в папку Documents
. Если я хочу использовать активы в расширении Photo Sharing, было бы ли смысл размещать все в ~/Library/Group Containers/
, и как контейнерное приложение, так и расширение получат оттуда активы?
Ответы
Ответ 1
Что касается обмена данными:
Если вы хотите делиться файлами между вашим iOS8-расширением и вашим сотовым приложением, вы хотите записывать файлы в общий контейнер или использовать общие настройки по умолчанию.
Из текущей документации iOS8 от Apple:
По умолчанию ваше приложение и его расширения не имеют прямого доступ к контейнерам друг друга
Вы хотите создать группу приложений и добавить в нее свою содержащую программу и ее расширения. Это довольно просто, используя Xcode 6, здесь, как это сделать в xcode:
![how to create an app group using xcode 6]()
В имени группы приложений введите константу, например:
group.com.bundle.app.soething
Это создает общий контейнер для вашего приложения и расширения, который позволяет:
-
Поделиться NSUserDefaults:
[[NSUserDefaults alloc] initWithSuiteName:@"group.com.bundle.app.soething"];
-
Поделитесь каталогом в файловой системе:
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.bundle.app.soething"];
ИЗМЕНИТЬ
Это напечатает все комбинации путей, которые у нас есть:
// App group path
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.test.app"];
NSLog(@"App group: %@", containerURL.path);
// Bundle path
NSLog (@"Bundle: %@", [[NSBundle mainBundle] bundlePath]);
// Good old Documents path
NSArray *Paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [Paths objectAtIndex:0];
NSLog(@"Documents: %@ ", path);
EDIT - и для Swift:
-
Поделиться NSUserDefaults:
var sharedDefaults = NSUserDefaults(suiteName: "group.com.bundle.app.soething")
-
Поделитесь каталогом в файловой системе:
var containerURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.bundle.app.soething")!
Надеюсь, это поможет вам:)
Ресурсы:
Руководство по разработке расширений iOS8.0 для Apple - https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1
Справочник по классу Apple iOS8.0 NSFileManager - https://developer.apple.com/documentation/foundation/nsfilemanager/1412643-containerurlforsecurityapplicati
Ответ 2
Мне нужно разделить связанные ресурсы между приложением и расширением. Сначала я думал, что смогу скопировать их в общую область группы при первом запуске, но что, если пользователь вызывает расширение и никогда не запускает приложение?
В качестве заметок mxcl вы можете включить активы в обе цели, но это расширит размер вашего окончательного отправленного двоичного файла.
Я подтвердил, что в инфраструктуру Xcode 6.1 (например, она работает раньше, но я просто пытаюсь это сделать) работает в инфраструктуре:
Вы можете иметь автономные изображения в своей структуре или каталоге активов. Оба будут работать.
В рамках просто настройте класс с помощью методов доступа, возвращающих объекты UIImage
. Что-то вроде этого (Objective-C):
@implementation AssetService
+ (UIImage *)frameworkImageNamed:(NSString *)name {
return [UIImage imageNamed:name
inBundle:[NSBundle bundleForClass:[self class]]
compatibleWithTraitCollection:nil];
}
@end
Или в Swift:
public class AssetService {
public init() {
}
// class method version
public class func frameworkImageNamed(name: String) -> UIImage? {
return UIImage(named: name,
inBundle: NSBundle(forClass: AssetService.self),
compatibleWithTraitCollection: nil)!
}
}
Обратите внимание, что поскольку указанный код находится внутри фреймворка, но будет работать в "пространстве приложения", вам нужно указать пакет.
Затем ваше приложение или расширение могут просто ссылаться в фреймворке и вызывать [AssetService frameworkImageNamed:@"myimage"]
или AssetService.frameworkImageNamed("myimage")
.
Предостережение: несмотря на возвращение необязательного UIImage?
, код становится очень сердитым, если он не может найти изображение с именем и будет сбой. Но если это ваша собственная структура, вы должны знать, что там, и поймать такую ошибку.
Ответ 3
выполните следующие действия:
-
перейти в xcode открыть приложение, содержащее функцию расширения приложения
-
перейти к целевому проекту xcode и выбрать расширение вашего приложения
-
перейти к этапам сборки
-
разверните ресурсы пакета, затем нажмите кнопку "+" и добавьте
image из поисковика.
Ответ 4
Похоже, вы хотите использовать фреймворк вместо этого. Однако ваша инфраструктура будет в основном ресурсами вместо кода:
OS X широко использует фреймворки для распространения общего кода и ресурсов, таких как интерфейсы к самой системе. Вы можете создавать собственные каркасы для предоставления общего кода и ресурсов одному или нескольким приложениям вашей компании. Вы также можете создавать фреймворки, содержащие библиотеки классов или дополнительные модули, с целью распространения их на других разработчиков.
https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPFrameworks/Frameworks.html#//apple_ref/doc/uid/10000183i
Ответ 5
Активы могут быть добавлены в каркас и повторно использованы как в приложении/расширении.
Подробнее читайте в "Загрузка ресурсов из платформы".
public class AmazingView: UIView {
private func setupView() {
let bundle = Bundle(for: AmazingView.self)
guard let image = UIImage(named: "MyImage", in: bundle, compatibileWith: nil) else {
fatalError("Missing MyImage...")
}
}
}