如何在iOS8上以编程方式创建Today小部件而不使用storyboard?

fra*_*ish 16 widget ios ios8 ios-app-extension

我试图删除故事板文件和相关Info.plist条目,但这次延期停止了工作; 它甚至没有从XCode启动.

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

常规应用程序(包含应用程序)很容易,因为我们看到它的入口点和应用程序委托,但是如何在扩展程序上执行此操作?

Rap*_*ael 39

我做了以下步骤:

  • 从项目中删除storyboard文件
  • 修改info.plist:

转到NSExtension Dictionary,删除此键:NSExtensionMainStoryboard.将其替换为此键NSExtensionPrincipalClass并将ViewController添加为值,例如TodayViewController.

之前:

<key>NSExtension</key>
<dict>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.widget-extension</string>
</dict>
Run Code Online (Sandbox Code Playgroud)

后:

<key>NSExtension</key>
<dict>
    <key>NSExtensionPrincipalClass</key>
    <string>TodayViewController</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.widget-extension</string>
</dict>
Run Code Online (Sandbox Code Playgroud)
  • 如果您使用的是Swift,则必须在目标的Build Settings中启用"Embedded Content Contains Swift Code".将其设置为YES.
  • 另外,我必须@objc (TodayViewController)在我的TodayViewController类中添加(在导入之后).

该应用程序应该立即运行.但我还有两件事要做:

  • 创建一个视图.显然没有自动创建的视图.

所以添加这些行:

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


fra*_*ish 20

NSExtensionMainStoryboardInfo.plist 添加中删除NSExtensionPrincipalClass = YourViewController

不要忘记创建自己的视图 loadView

  • 注意:这需要在info.plist中的NSExtension字典下进行扩展. (2认同)

Sas*_*ats 6

FWIW, it didn't work for me until I added a prefix of the module name for my Swift view controller class, e.g.

<key>NSExtension</key>
<dict>
    <!-- ... -->
    <key>NSExtensionPrincipalClass</key>
    <string>SafariActionExtension.RootViewController</string>
    <!-- ... -->
</dict>
Run Code Online (Sandbox Code Playgroud)

That is probably because class lookup for Swift modules turns module names into prefix for class name. E.g. to create your class in code you would write NSStringFromClass("SafariActionExtension.RootViewController"), hence the prefix.