14. NSWindow 窗口与 NSWindowController 窗口控制器

NSWindowController窗口控制器主要用于管理xib/storyboard文件中加载的NSWindow对象:1、创建一个基于xib或storyboard的NSWindowController子类会自动创建一个NSWindow;2、如果手工创建NSWindow对象,则需要维护NSWindowController和NSWindow之间的双向绑定关系。

本节内容可参考 :https://korgs.blog.csdn.net/article/details/142673123

NSWindow与NSControllerWindow

方案1:使用UI设计器

创建一个Cocoa class,然后选择 Also create XIB file for user interface,父类选择NSWindowController
在这里插入图片描述

方案2:切换UI设计器实现

可单独创建一个xib或storyboard视图,然后创建NSWindowController的子类,再手工绑定。
在这里插入图片描述

NSWindow 窗口自定义

编程实现NSWindow窗口

首先需要了解下NSWindow的调用过程,显示window的过程大概如下:

  1. 初始化:NSApplication加载xib或stroyboard文件,创建window对象;
  2. 显示:调用window.showWindow()方法显示窗口,再调用makeKey()方法使当前的窗口标识为keyWindow;也可以调用makeKeyAndOrderFront()方法,makeKeyAndOrderFront方法相当于orderFront()+makeKey()的组合;
  3. 关闭:最后不需要时,可调用window.close()方法,内部执行 orderOut() 方法;

代码实现

//创建一个子类
class CustomWindow: NSWindow {override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing bufferingType: NSWindow.BackingStoreType, defer flag: Bool) {super.init(contentRect: contentRect, styleMask: style, backing: bufferingType, defer: flag)}deinit {Swift.print("release object")}override func orderFront(_ sender: Any?) {super.orderFront(sender)}override func orderOut(_ sender: Any?) {super.orderOut(sender)}override func makeKeyAndOrderFront(_ sender: Any?) {super.makeKeyAndOrderFront(sender)}override func makeKey() {super.makeKey()}
}

使用自定义NSWindow窗口

下列代码运行程序后会存在一个小问题,也是在本系列专题中第二篇文章中遗留的一个问题,即编码创建的Window只能创建和关闭一次,再次创建时会被crash,原因是关闭后App中的对象不再持有此NSWindow实例的引用被GC掉了,这个过程人为干预不了,是框架底层的机制,但是可以修复。

    lazy var myWindow: CustomWindow = {let frame = CGRect(x: 0, y: 0, width: 400, height: 280)let style : NSWindow.StyleMask = [NSWindow.StyleMask.titled,NSWindow.StyleMask.closable,NSWindow.StyleMask.resizable]//创建windowlet window  = CustomWindow(contentRect:frame, styleMask:style, backing:.retained, defer:true)//创建双向绑定关系//window.windowController = self.myWindowController//self.myWindowController.window = window;window.title = "New Create Window"return window}()@IBAction func createWindow(_ sender: NSButton) {self.myWindow.makeKeyAndOrderFront(self)self.myWindow.center()}

所以为了修复上面的问题,需要绑定双方的关系,即需要把上面注释的两行代码打开。

    lazy var myWindowController: NSWindowController = {let wondowVC = NSWindowController()return wondowVC}()

NSWindow 窗口显示切换

如果有多个NSWindow应如何控制显示和切换呢?比如下面的例子,首先设计UI,把storyboard id分别设置成LoginMVC和MainAppMvc
在这里插入图片描述

默认Window设置

这个功能同 visible at Lanunch 一样。只不过这里换代码来实现;

@main
class AppDelegate: NSObject, NSApplicationDelegate {//定义当前的windowControllervar loginWVC: NSWindowController?func applicationDidFinishLaunching(_ aNotification: Notification) {//得到Main.storyboard对象,显示初始化窗口let sb = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)loginWVC = sb.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "LoginWVC")) as? NSWindowControllerloginWVC?.showWindow(self)}func applicationWillTerminate(_ aNotification: Notification) {// Insert code here to tear down your application}func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {return true}
}

切换Window显示

在这里插入图片描述
点击 switch window 按钮后会隐藏当前窗口,显示新窗口。

class ViewController: NSViewController {var mainAppWVC: NSWindowController?override func viewDidLoad() {super.viewDidLoad()}override var representedObject: Any? {didSet {}}@IBAction func loginOk(_ sender: NSButton) {//得到Main.storyboard对象,let sb = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)self.view.window?.close() //因为默认是双向绑定了,所以可以直接取mainAppWVC = sb.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "MainAppWVC")) as? NSWindowControllermainAppWVC?.showWindow(self)}
}

如果这两个窗口来回切换时,有时会有选择状态的保持功能,默认是不开启的,如果发生焦点丢失情况,可以注册NSWindowDidBecomeMain或NSWindowDidBecomeKey通知事件,然后调用window.makeFirstResponder方法重新获得响应者,比如:selft.makeFirstResponder(self.tableView)

Storyboard工程结构解析

xib工程的设计模式大概如下:
在这里插入图片描述
采用了二层设计结构:

  • AppDelegate:负责代理Application;
  • NSWindowController:负责代理NSWindow;

上面这种设计是把所有的控制全部交给了AppDelegate代理,从架构角度来讲AppDelegate只对Application负责就可以了,不需要拥有那么多的职责,所以优化一下,可进行如下拆分为三层结构。
在这里插入图片描述
三层设计结构,同时拆分controller和view采用MVC设计模式实现:

  • AppDelegate:负责代理Application;
  • NSWindowController:负责代理NSWindow;
  • NSViewController:负责代理NSView(后面章节会讲);

因此一个XIB工程,代码可以这样来改造一下:

AppDelegate.swift

包含了 NSWindowController对象。

class AppDelegate: NSObject, NSApplicationDelegate {//引用一个自定义的NSWindowControllerlazy var windowController: AppMainWindowController = {let wondowVC = AppMainWindowController()return wondowVC}()func applicationDidFinishLaunching(_ aNotification: Notification) {self.windowController.showWindow(self)}
}

AppWindowController.swift

包含了 NSViewController对象。这个文件创建时要关联一个xib/storyboard,也可以用代码实现。

class AppMainWindowController: NSWindowController {//引用一个自定义的NSViewControllerlazy var viewController: AppViewController = {let vc = AppViewController()return vc}()override func windowDidLoad() {super.windowDidLoad()self.contentViewController = self.viewController}//返回window的xib文件名override var windowNibName: NSNib.Name? { return NSNib.Name("AppMainWindowController") }
}

AppViewController.swift

这个文件创建时要关联一个xib/storyboard,也可以用代码实现。


class AppViewController: NSViewController {override func viewDidLoad() {super.viewDidLoad()// Do view setup here.}   
}

最后对XIB进行一些改造;
在这里插入图片描述

上述这种结构就是storyboard的原理,所以我们创建工程时建议使用storyboard而不是xib。Xcode快捷创建窗口如下图所示:
在这里插入图片描述
实际开发时,下述三个类一般都需要自定义扩展。

NSApp对象简介

这个对象是个全局对象,比如一些以下操作

点击Dock 需要显示窗口

//--AppDelegate/**点击Dock 需要显示窗口,要实现这个方法*/func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {if flag == false {// 1. 获取到我们的App 窗口let win = NSApp.window(withWindowNumber: windowNumber)// 2. 让窗口显示win?.makeKeyAndOrderFront(nil)return true}return !flag}

ViewController控制App

    // 关闭应用@IBAction func closeApp(_ sender: Any) {NSApp.terminate(self)}//显示App的数字提醒@IBAction func showAppNumber(_ sender: Any) {NSApp.dockTile.badgeLabel = "20"}//docker跳动@IBAction func jump(_ sender: Any) {/**criticalRequest   // 多次跳动App Dock 上的图标,直到用户选中App为活动状态informationalRequest  // 一次跳动App Dock 上的图标*/// 这个方法只能在当前App 不是处于非活动时才有效DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { NSApp.requestUserAttention(.informationalRequest)}}// 隐藏Dock 上的App 图标@IBAction func hideDockIcon(_ sender: Any) {// 隐藏App 图标,会自动隐藏窗口NSApp.setActivationPolicy(.accessory)DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) { NSApp.unhideWithoutActivation()}}// 显示Dock 上的App 图标@IBAction func showDockIcon(_ sender: Any) {NSApp.setActivationPolicy(.regular)}

全屏设置

guard let screenSize = NSScreen.main?.frame.size else { return  }//        view.layer?.backgroundColor = NSColor.red.cgColorview.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height-22.0)label.frame = view.bounds;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460704.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02 什么是Babel

什么是Babel? Babel 是一个 JavaScript 编译器,提供了JavaScript的编译过程,能够将源代码转换为目标代码。AST -> Transform -> Generate 官网 Babel Babel 查看AST https://astexplorer.net/ Babel所有的包 babel/traverse Babel Babel 是…

【论文阅读笔记】VLP: A Survey on Vision-language Pre-training

目录 前言2 特征提取(Feature extraction)2.1.1 图象特征提取OD-based Region feature / RoIFreeze the pre-trained object detectorsGrid features(网格特征)CNN-GFsEnd-to-End Training(端到端训练)ViT-…

TortoiseSVN小乌龟下载安装(Windows11)

目录 TortoiseSVN 1.14.7工具下载安装 TortoiseSVN 1.14.7 工具 系统:Windows 11 下载 官网:https://tortoisesvn.subversion.org.cn/downloads.html如图选 TortoiseSVN 1.14.7 - 64 位 下载完成 安装 打开 next,next Browse&#xf…

Mac OS 搭建MySQL开发环境

Mac OS 搭建MySQL开发环境 文章目录 Mac OS 搭建MySQL开发环境一、安装Mysql:二、配置环境变量三、安装Navicat 本地环境: Mac OS Sequoia15.0.1(M3 Max) 目标状态: 下载安装Mysql,配置相关环境。 一、安装Mysql&…

docker Desktop开启远程访问端口

文章目录 问题解决方法1.首先开启docker Desktop的访问端口2.将本地端口绑定远程访问ip 验证 问题 Windows上部署的docker,没办法通过远程的ip进行访问,实现远程代码的部署。 解决方法 1.首先开启docker Desktop的访问端口 通过开启docker访问端口&am…

Linux文件系统学习(未完)

1. Linux文件系统的特点与类别 1.1 特点 Linux系统中,文件组织在一个统一的树形目录结构中,整个文件系统有一个根“/”(文件夹),然后以每个目录(文件夹)作为分叉,叶子节点作为文件…

Three.js 快速入门构建你的第一个 3D 应用

![ 开发领域:前端开发 | AI 应用 | Web3D | 元宇宙 技术栈:JavaScript、React、Three.js、WebGL、Go 经验经验:6年 前端开发经验,专注于图形渲染和AI技术 开源项目:github 晓智元宇宙、数字孪生引擎、前端面试题 大家好…

排序算法汇总

一、二分查找 public static int binarySearch(int[] nums,int target){int l 0, r nums.length-1;while(l < r){int mid l (r-l)/2;if(nums[mid] target){return mid;}else if(nums[mid] < target){r mid - 1;}else{l mid 1;}}return -1;} 对于防止溢出的 mid …

类和对象(2)

1.类的默认成员函数 默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不…

AcWing 1303:斐波那契前 n 项和 ← 矩阵快速幂加速递推

【题目来源】https://www.acwing.com/problem/content/1305/http://poj.org/problem?id3070【题目描述】 大家都知道 数列吧&#xff0c;。现在问题很简单&#xff0c;输入 和 &#xff0c;求 的前 项和 。【输入格式】 共一行&#xff0c;包含两个整数 和 。【输出格式】…

ElasticSearch备考 -- Index rollover

一、题目 给索引my-index-000001&#xff0c;创建别名my-index&#xff0c;并设置rollover&#xff0c;满足以下三个条件的 The index was created 7 or more days ago.The index contains 5 or more documents.The index’s largest primary shard is 1GB or larger. 二、思考…

zabbix 6.0 监控clickhouse(单机)

zabbix 6.0 LTS已经包含了clickhouse的监控模板&#xff0c;所以我们可以直接使用自带的模板来监控clickhouse了。 0.前置条件 clickhouse 已经安装&#xff0c;我安装的是24.3.5.47zabbix-agent 已经安装并配置。系统是ubuntu 2204 server 1. 新建监控用户 使用xml的方式为…

Jmeter自动化实战

一、前言 由于系统业务流程很复杂,在不同的阶段需要不同的数据,且数据无法重复使用,每次造新的数据特别繁琐,故想着能不能使用jmeter一键造数据 二、创建录制模板 可参考:jmeter录制接口 首先创建一个录制模板 因为会有各种请求头,cookies,签名,认证信息等原因,导致手动复制…

提升网站速度与性能优化的有效策略与实践

内容概要 在数字化快速发展的今天&#xff0c;网站速度与性能优化显得尤为重要&#xff0c;它直接影响用户的浏览体验。用户在访问网站时&#xff0c;往往希望能够迅速获取信息&#xff0c;若加载时间过长&#xff0c;轻易可能导致他们转向其他更为流畅的网站。因此&#xff0…

OpenCV视觉分析之目标跟踪(6)轻量级目标跟踪器类TrackerNano的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 Nano 跟踪器是一个超轻量级的基于深度神经网络&#xff08;DNN&#xff09;的通用目标跟踪器。 由于特殊的模型结构&#xff0c;Nano 跟踪器速度…

C数组手动输入问题

问题界面 解析 输入数组数据也需要加取地址符吗&#xff1f;数组不就是地址了吗&#xff1f; 理解array[i]和array[i][j]的区别&#xff1a; array[i]是一个指向第i行第一个元素的指针&#xff08;int*类型&#xff0c;指向array[i][0]&#xff09;。 array[i][j]是一个int类…

Hadoop-002-部署并配置HDFS集群

集群规划 Hadoop HDFS的角色包含 NameNode(主节点管理者)、DataNode(从节点工作者)、SeconddaryNameNode(从节点辅助) 节点CPU内存hadoop-11C4Ghadoop-21C2Ghadoop-31C2G 一、下载上传Hadoop包 注意: 登录hadoop-1节点root用户执行 1、官网下载安装包后上传 到hadoop-1服务…

Android 在github网站下载项目:各种很慢怎么办?比如gradle下载慢;访问github慢;依赖下载慢

目录 访问github慢gradle下载慢依赖下载慢 前言 大家好&#xff0c;我是前期后期&#xff0c;在网上冲浪的一名程序员。 为什么要看这篇文章呢&#xff1f;问题是什么&#xff1f; 我们在Github上面看到一些好的项目的时候&#xff0c;想下载下来研究学习一下。但经常遇到各…

信息安全数学基础(35)同态和同构

一、同态 定义&#xff1a; 设(M,)和(S,)是两个群&#xff08;或更一般的代数系统&#xff09;&#xff0c;如果存在一个映射σ:M→S&#xff0c;使得对于M中的任意两个元素a、b&#xff0c;都有σ(ab)σ(a)σ(b)&#xff0c;则称σ为M到S的同态或群映射。 性质&#xff1a; 同…

微信小程序中点击搜素按钮没有反应,可能是样式问题(按钮被其他元素覆盖或遮挡)

文章目录 1. 确认 bindtap 绑定在正确的元素上2. 检查是否有遮挡或重叠元素3. 检查 this 上下文绑定问题4. 清除微信小程序开发者工具的缓存5. 用微信开发者工具查看事件绑定6. 确保 handleSearch 没有拼写错误进一步调试 1、searchResults.wxml2、searchResults.wxss3、search…