me
me copied to clipboard
学习MacOS App (Part 3: 从XIB开始理解单一窗口应用)
新建一个interface为XIB的Swift App,此时Xcode给出的template中关键的代码仅2个文件:
- AppDelegate.swift
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
- MainMenu.xib
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17150" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17150"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
...
</menu>
<window title="hello" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<point key="canvasLocation" x="200" y="400"/>
</window>
</objects>
</document>
New ViewController
之前在Part 2中因为是通过storyboard方式进行创建,所以看上去一切顺风顺水,但现在的问题是没有ViewController,那么View-Behind的代码写到哪去呢,总不能写到AppDelegate吧。所以需要将MainMenu.xib理解为程序启动的入口,简单来说,你认为他为你创建了一个Window,后面的View和ViewController你自己往上堆。
所以此时应该新建一个ViewController,具体操作就是新建一个Cocoa Class,name: ViewController, Subclass of: NSViewController, 同时勾选创建XIB,改一下layer颜色,增加一个label,然后在AppDelegate中如下:
@main
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var window: NSWindow!
var viewController: ViewController!
func applicationDidFinishLaunching(_ aNotification: Notification) {
viewController = ViewController()
window.contentView?.addSubview(viewController.view)
viewController.view.frame = window.contentView!.bounds
viewController.view.autoresizingMask = [.width, .height]
}
}
也可以在XIB中通过Object Library加入一个View Controller,然后通过connect引入到AppDelegate,省去了一个new的过程,其实意思是一致的,
IBOutlet weak var viewController: ViewController!
如果需要隔离AppDelegate和AppController, 则需要创建AppController,然后根据L36的视频将AppController加入到XIB中,即实例化,
AppController.swift
class AppController: NSObject {
@IBOutlet weak var container: NSView!
@IBOutlet weak var viewController: ViewController!
override func awakeFromNib() {
container.addSubview(viewController.view)
viewController.view.frame = container.bounds
viewController.view.autoresizingMask = [.width, .height]
}
}
这样就分离了AppDelegate和AppController,为下一步切换多个View做好了准备。
多个View/ViewController切换
具体参加视频,逻辑来说已经很清晰了
- 建立AppController
- 新建FirstViewController和SecondViewController
- awake时首先添加FirstViewController
- 在界面上增加两个Button,每次点击通过currentView.removeFromSuperView上移除,然后添加对应的ViewController.view即可
小结:
- 很灵活,对Window/WindowController, View/ViewController有了一定的认识
- 从学习的角度还是应该理解一下XIB,实践中应该直接用Storyboard,省去了这一堆麻烦事情
参考阅读: