Совместное использование вложенных активов между приложением и расширением

Расширение 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...")
    }
  }
}