【问题标题】:How to set initial controller programmatically from storyboard in Cocoa using Swift 4 Xcode 10?如何使用 Swift 4 Xcode 10 从 Cocoa 的情节提要中以编程方式设置初始控制器?
【发布时间】:2019-03-08 15:01:33
【问题描述】:

简介:

我想创建一个在首次启动时显示一些“用户指南”的应用程序,我已经完成了检测应用程序是否首次启动的部分,但是当涉及到设置视图控制器部分时,我可以不知道怎么做。

现状:

我已经做了很多研究,也看到了很多关于“如何在 swift 中以编程方式设置初始视图控制器”等主题的 Q/A 文章,但基本上都是以 ios 开发为例,没有一个他们在 OSX 开发中的 UIWindowUINavigationController(rootViewController:) 匹配。然后我发现AppDelegate.swift文件中似乎没有didFinishLaunchingWithOptions这样的东西,而是只有一个applicationDidFinishLaunching(_ aNotification: Notification)

问题:

我已经为我的两个视图控制器取消选中 Is Initial Controller 选项,并且它们都有故事板 ID(标识符?)和它们自己指定的类。

MainPageController

用户指南页面控制器

或者我也应该指定和识别我的窗口控制器?因为'我不知道如何处理窗口控制器..

为了在AppDelegate 中为我的应用程序设置初始视图控制器,我需要做什么?

附:这是我的界面视图的图片:

故事板界面

AppDelegate.swift

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

  let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
  var window = MainWindow().window

  func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) - > Bool {
    return true
  }

  func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Insert code here to initialize your application
    let firstLaunch = UserDefaults.isFirstLaunch()
    let mainPageController = storyboard.instantiateController(withIdentifier: NSStoryboard.Name("MainPageController")) as? MainPageController
    let userGuidePageController = storyboard.instantiateController(withIdentifier: NSStoryboard.Name("MainPageController")) as? UserGuidePageController
    if !firstLaunch {
      print("first run")
      window?.contentViewController = userGuidePageController
    } else {
      print("not first run")
      window?.contentViewController = mainPageController
    }
  }

  func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
  }
}

我试过这种方式,但效果不佳,我的代码有什么问题吗?

【问题讨论】:

  • Mac OS Cocoa 基于窗口,而不是视图控制器。只需决定首先显示哪个窗口
  • @matt 好的,但具体如何?你能通过代码告诉我怎么做吗?

标签: macos cocoa swift4 viewcontroller xcode10


【解决方案1】:

一开始你需要从应用委托类处理这样的场景 适用于 iOS 应用程序

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


let shouldShowUserGuide = // your cached key from user defaults for example

let mainController = //MainPageController Instance
let userGuide = //UserGuidePageController Instance


if shouldShowUserGuide {
window.rootViewController = userGuide 
}else{
window.rootViewController = mainController
}
window.makeKeyAndVisisble()
  return true
}

// 这段代码我只是在 sublime 上写的,不是从 xcode 写的,所以你可能需要格式化它并修复任何语法问题

对于 OSX 主窗口:NSWindowController

func applicationDidFinishLaunching(_ aNotification: Notification) {
        let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
        var window = storyboard.instantiateController(withIdentifier: "MainWindow") as! NSWindowController
        let firstLaunch = true//UserDefaults.isFirstLaunch()
        let mainPageController = storyboard.instantiateController(withIdentifier: "MainController") as! NSViewController
        let userGuidePageController = storyboard.instantiateController(withIdentifier: "UserGuideController") as! NSViewController
        if firstLaunch {
            print("first run")
            window.contentViewController = userGuidePageController
        } else {
            print("not first run")
            window.contentViewController = mainPageController
        }
        window.showWindow(self) // needed as long as your window controller has no static window content (No Content View Controller)
    }

【讨论】:

  • 谢谢,但是我应该如何处理原来的 applicationDidFinishLaunching() 呢?
  • 但是 Cocoa 没有 didFinishLaunchingWithOptions,它只有类似的东西叫做 applicationDidFinishLaunching()
  • 如果您将方法覆盖到您的应用委托中,只需将方法主体添加到您的,否则将整个代码复制到您的 appDelegate
  • 你能不能给你的 appdelegate 拍个截图看看你有什么问题
  • 我在描述中发布了我的 AppDelegate.swift。
【解决方案2】:

MacOS 和 iOS 有不同的初始化函数调用顺序。直到调用初始窗口控制器 viewDidLoad 方法之后,才会调用 applicationDidFinishLaunching。但这没关系。您可以在 Window Controller viewDidLoad 方法中执行您的逻辑。

  1. 将 WindowController 拖放到情节提要上并为其指定情节提要 ID。此外,设置自定义类名称。例如,“EntryWindowWC”。但是不要将它连接到内容视图控制器。您将以编程方式执行此操作。

  2. 创建一个 NSWindowController swift 类

import Cocoa

class EntryWindowWC: NSWindowController
{
    override func windowDidLoad()
    {
        super.windowDidLoad()
    
        let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
        
        if (Security.shared.isLifetimeMember())
        {
            let homepage = storyboard.instantiateController(withIdentifier: "homepageStoryId") as! NSViewController
            window!.contentViewController = homepage
        }
        else
        {
            let subscription = storyboard.instantiateController(withIdentifier: "subscriptionStoryId") as! NSViewController
            window!.contentViewController = subscription
        }
    }
}
  1. 构建、运行并完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多