【问题标题】:How to create a Today widget programmatically without storyboard on iOS8?如何在没有情节提要的情况下在 iOS8 上以编程方式创建 Today 小部件?
【发布时间】:2014-11-20 03:39:05
【问题描述】:

我试图删除故事板文件和相关的Info.plist 条目,但这次扩展停止工作;它甚至不会从 XCode 启动。

The operation couldn’t be completed. (LaunchServicesError error 0.)

在常规应用程序(包含应用程序)上很容易,因为我们看到它是入口点和应用程序委托,但是如何在扩展上也这样做呢?

【问题讨论】:

    标签: ios widget ios8 ios-app-extension


    【解决方案1】:

    我做了以下步骤:

    • 从您的项目中删除情节提要文件
    • 修改info.plist:

    转到 NSExtension 字典,删除这个键:NSExtensionMainStoryboard。将其替换为此键 NSExtensionPrincipalClass 并将您的 ViewController 添加为值,例如TodayViewController。

    之前:

    <key>NSExtension</key>
    <dict>
        <key>NSExtensionMainStoryboard</key>
        <string>MainInterface</string>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.widget-extension</string>
    </dict>
    

    之后:

    <key>NSExtension</key>
    <dict>
        <key>NSExtensionPrincipalClass</key>
        <string>TodayViewController</string>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.widget-extension</string>
    </dict>
    
    • 如果您使用的是 Swift,则必须在目标的构建设置中启用“嵌入式内容包含 Swift 代码”。将其设置为“是”。
    • 此外,我必须在 TodayViewController 类中添加 @objc (TodayViewController)(在导入之后)。

    应用程序现在应该运行。但我还有两件事要做:

    • 创建视图。显然没有自动创建视图。

    所以添加这些行:

    override func loadView()
    {
        view = UIView(frame:CGRect(x:0.0, y:0, width:320.0, height:200.0))
    }
    
    • 并在 viewDidLoad 方法中设置小部件的高度:self.preferredContentSize = CGSizeMake(0, 200)

    【讨论】:

    • 必须这样做才能使其工作:stackoverflow.com/questions/24416003/…
    • 请问为什么我们必须在TodayViewController类中创建一个视图?视图控制器不是已经包含视图了吗?
    • @Raphael,很好的答案。我想为 iMessage 扩展遵循类似的逻辑,但没能做到。 :-/
    • @Raphael,实际上我做到了。不确定这是否是一种有效的方法。 (通过添加 childViewController。)但是,我猜导致早上的崩溃是一个错字! :-(
    【解决方案2】:

    Info.plist 中删除NSExtensionMainStoryboard 添加NSExtensionPrincipalClass = YourViewController

    别忘了在loadView中创建自己的视图

    【讨论】:

    • 注意:这需要在扩展的 info.plist 中的 NSExtension 字典下。
    • 必须这样做才能使其工作:stackoverflow.com/questions/24416003/…
    • 是的,这篇文章有效,你必须在你的主类声明之前插入@objc(PrincipalClassName)
    【解决方案3】:

    FWIW,直到我为我的 Swift 视图控制器类添加了模块名称的前缀,例如

    <key>NSExtension</key>
    <dict>
        <!-- ... -->
        <key>NSExtensionPrincipalClass</key>
        <string>SafariActionExtension.RootViewController</string>
        <!-- ... -->
    </dict>
    

    这可能是因为 Swift 模块的类查找将模块名称转换为类名称的前缀。例如。要在代码中创建你的类,你会写NSStringFromClass("SafariActionExtension.RootViewController"),因此是前缀。

    【讨论】:

    • 我无法让它与前缀一起工作,所以我只是使用 @obj(RootViewController) 来指定类名并且它可以工作。
    • 这个答案解决了我的问题! :-) 应该标记为正确答案!
    猜你喜欢
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    相关资源
    最近更新 更多