【问题标题】:Sharing bundled assets between app and extension在应用程序和扩展程序之间共享捆绑资产
【发布时间】:2014-08-06 00:40:24
【问题描述】:

我的照片共享扩展程序计划使用相同的设计资源(用于导航和为照片添加“图章/贴纸”)。

如应用沙盒设计指南中所述,沙盒应用组 需要共享文件和其他信息的可以请求容器 目录作为其权利的一部分。这些目录存储 在 ~/Library/Group Containers/. https://developer.apple.com/documentation/foundation/nsfilemanager/1412643-containerurlforsecurityapplicati

目前资产已捆绑或下载并添加到Documents 文件夹中。如果我想在照片共享扩展中使用资产,将所有内容放在~/Library/Group Containers/ 中并且容器应用程序和扩展都从那里获取资产是否有意义?

【问题讨论】:

    标签: objective-c ios8


    【解决方案1】:

    关于共享数据:

    如果您想在您的 iOS8 扩展程序和您的包含应用程序之间共享文件,您希望将文件写入共享容器或使用共享用户默认值。

    来自 Apple 的 iOS8 当前文档:

    默认情况下,您的包含应用及其扩展没有直接 访问彼此的容器

    您想要创建一个应用组,并将您的包含应用及其扩展添加到该组。使用 Xcode 6 非常简单,以下是在 xcode 中的操作方法:

    在应用组名称中,输入一个常量,如:

    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's 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);
    

    编辑 - 对于 Swift:

    • 分享 NSUserDefaults:

      var sharedDefaults = NSUserDefaults(suiteName: "group.com.bundle.app.soething")
      
    • 在文件系统上共享一个目录:

      var containerURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.bundle.app.soething")!
      

    希望对你有帮助:)

    资源: 苹果iOS8.0扩展开发指南-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

    【讨论】:

    • 我可以确认这是被认可的方法,也是我做类似事情的方式。
    • @ChrisWagner by 'sanctioned',你的意思是苹果拒绝了你的应用因为使用了这种方法?
    • 抱歉,这可能是一个不好的词选择,我的意思是说这是 Apple 在其文档中使用的方法。
    • @nurne 谢谢 - 我更感兴趣/担心Documents 文件夹中的项目。除了将下载的 IAP 内容添加到 Documents 文件夹之外,我可以将其添加到 Group Containers 文件夹吗?
    • 将文件保存在应用组目录安全吗?是否所有文件都会像保存在.UserDomainMask中的文件一样永远保留@
    【解决方案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?,但如果找不到命名的图像,代码会非常生气并且会崩溃。但如果它是你自己的框架,你应该知道里面有什么并抓住这种错误。

    【讨论】:

    • 如何与添加到资产包的扩展程序共享图像?它在进行开发构建时有效,但在发布构建中,图像无法在扩展中加载。
    • 使用应用组有帮助吗?还是这个解决方案真的错了(我现在会尝试发布版本来确认)。
    • @blackjack75 我使用了应用程序组,并在首次启动时从捆绑包复制到应用程序组容器区域。这意味着应用程序需要在扩展之前首先启动。
    【解决方案3】:

    这里是解决问题的步骤:

    1. 转到 xcode 打开包含应用扩展功能的应用

    2. 转到您的 xcode 项目中的目标并选择您的应用扩展名

    3. 进入构建阶段

    4. 展开复制包资源,然后单击“+”按钮并添加 finder 中的图片资源文件夹。

    【讨论】:

    • 这会使您的资产存储需求翻倍,因为它们现在被捆绑到您的应用中两次。
    【解决方案4】:

    听起来您想改用框架。但是,您的框架将主要是资源而不是代码:

    OS X 广泛使用框架来分发共享代码和资源,例如系统本身的接口。您可以创建自己的框架,为公司的一个或多个应用程序提供共享代码和资源。您还可以创建包含类库或附加模块的框架,以便将它们分发给其他开发人员。

    https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPFrameworks/Frameworks.html#//apple_ref/doc/uid/10000183i

    【讨论】:

    • 框架不会帮助处理磁盘上的文件。不过,框架将允许您跨目标重复使用已编译的代码。
    • 史蒂夫,我听说你不能将资产添加到框架中——这是真的吗?如果可以,你是怎么做到的?
    • 您将创建自己的框架,然后将其“导入”到另一个项目中。因此,当您想添加更多文件时,只需更新框架即可。
    • 让它在框架目标中使用 .xcassets 和普通旧图像。看看我对这个问题的回答。
    【解决方案5】:

    资产可以添加到框架中并在应用程序/扩展程序中重复使用。 详情请见"Loading Resources From A Framework"

      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...")
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-25
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-12
      相关资源
      最近更新 更多