【问题标题】:Loading a resource (e.g. storyboard) in a Swift framework在 Swift 框架中加载资源(例如故事板)
【发布时间】:2014-07-27 16:14:03
【问题描述】:

我正在尝试制作一个可以捆绑故事板的框架。我已经检查过了,创建的 .framework 包括我的 .storyboard 文件(作为.storyboardc 文件),并且已经获得了在运行时加载情节提要的框架。但是,这是一个框架,我希望代码尽可能多才多艺,而且我觉得我目前的解决方案有点笨拙。目前,我正在使用以下代码加载情节提要:

let mainBundlePath: String = NSBundle.mainBundle().resourcePath
let frameworkBundlePath = mainBundlePath.stringByAppendingPathComponent("Frameworks/AuthenticationManager.framework")
let frameworkBundle = NSBundle(path: frameworkBundlePath)
let storyboard = UIStoryboard(name: "Storyboard", bundle: frameworkBundle)

我注意到的几件事可能是陷阱:

  • 框架 (Frameworks/) 的路径可能会在未来发生变化,不应依赖?
  • 框架的名称可以更改,但如果不先获取框架的NSBundle,就无法获取产品名称?
  • 框架并不是真正的捆绑包 (?),因此将它们作为捆绑包加载可能会在未来产生无法预料的后果?

可能还有其他问题,上述问题的解决方案,或者上述问题可能根本不是问题,但我一直想不出来。

这个问题可能更适合Code Review,但我觉得它也很适合这里。如果需要将其移到那里,请随时这样做或告诉我这样做。

【问题讨论】:

  • 你好,我知道这个话题已经有 4 年历史了。我想做几乎相同的事情,但我没有找到任何教程或好的例子,所以我可以从中学习。你(或其他人)能帮帮我吗?只是给我一个提示或一些链接..非常感谢

标签: ios swift


【解决方案1】:

一个框架(从“Cocoa Touch Framework”模板创建)有一个包标识符, 它存储在生成的框架包的 Info.plist 中。

捆绑标识符在常规目标设置中配置。 默认为<organization prefix>.<framework name>

您可以使用此标识符定位框架,例如:

let frameworkBundle = NSBundle(identifier: "com.duffy.AuthenticationManager")
let storyboard = UIStoryboard(name: "Storyboard", bundle: frameworkBundle)

【讨论】:

  • 有没有办法从框架内访问应用程序的包。使用标识符可能不是可行的方法,因为框架可能不知道应用程序的包标识符。
  • @niks: Bundle.main 是主要的应用程序包。
【解决方案2】:

这是一个更简洁的解决方案(不涉及框架标识符):

let storyboardName = "StoryboardName"
let storyboardBundle = NSBundle(forClass: self)
let storyboard = UIStoryboard(name: storyboardName, bundle: storyboardBundle)

如果此代码不在static 方法内,请使用YourClass.self 而不是self

Swift 3 示例:

let storyboardBundle = Bundle(for: NumberPadViewController.self)
super.init(nibName: "NumberPadViewController", bundle: storyboardBundle)

【讨论】:

  • 而不是 let storyboardBundle = NSBundle(forClass: self),现在应该是 let storyboardBundle = NSBundle(forClass: className.self)
  • @azimov 好吧,这取决于。如果它在静态方法中,self 就足够了。我添加了一个小注释以使事情更清楚。谢谢!
  • 如果这段代码是在框架本身的一个类中执行的,这只是一个更干净的解决方案。如果框架的“消费者”想要访问(并且各种类的访问控制设置为公共),那么接受的答案仍然是要走的路。
  • @wuf810 你仍然可以在它的YourClass.self 中使用框架中的一个类,不是吗?
【解决方案3】:

对于 Swift 3/4,它现在只是 Bundle :

let bundle = Bundle(identifier: "com.myframework.id")
let storyboard = UIStoryboard(name: "FrameworkMain", bundle: bundle)

【讨论】:

    【解决方案4】:

    这是在 Swift 3 中加载包的更好方法,无需传递更可能失败的字符串

    let myBundle = Bundle(for: MyViewController.self)
    let myStoryboard = UIStoryboard(name: "StoryboardName", bundle: myBundle) 
    

    【讨论】:

    • 如果你有 R.Swift 之类的东西,你可以使用生成的故事板名称使其编译时安全
    猜你喜欢
    • 2015-10-19
    • 1970-01-01
    • 2013-04-03
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多