最后更新: 2017-12-15

一、 项目初始化

  1. 解析对应的资源, 下载Pap.er之后,需要解析里面的资源.

    采用如下的方法: http://blog.csdn.net/xuzihai0703/article/details/50327531

  2. 创建项目工程

  3. 导入里面的资源icon, 然后运行

    可以看到,资源文件夹里面有一个AppIcon.icns 文件夹, 里面包含搜有的icon资源.可以在 这里 进行解析、下载, 添加到项目Assets.xcassets - AppIcon中, cmd + R运行;



    运行之后,什么都没有,当然是这样的,毕竟我们什么都没做

  4. 在状态栏显示App, 进行如下操作

    • 把资源文件夹内的两张 icon16*16的文件,放到 Assets里面去

    关于StatusBar icon尺寸可以参考这篇文章

    • applicationDidFinishLaunching 的上面通过 NSStatusBar 实例化一个 NSStatusItem 对象, 通过设置此对象, 我们可以进行一系列的操作,例如icon、title、action等.

@NSApplicationMain

class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)

    func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
let icon = NSImage(named: NSImage.Name(rawValue: "icon16*16"))
icon?.isTemplate = true
statusItem.image = icon
statusItem.button?.target = self
statusItem.button?.action = #selector(onStatusItemDidClicked(_:))
} @objc private func onStatusItemDidClicked(_ item: NSStatusItem) {
print("onStatusItemDidClicked")
}

}

```

  • cmd + R 运行一下, 跑起来了。 状态栏出现了, 点击一下, 控制台出现打印信息。 Good!

    动手一下: 删除 icon?.isTemplate = true 会是什么效果?

二、处理 Dock栏以 及 状态栏左

当我们点击cmd + R 运行时候, 会出现如下情况:

  • 左边的状态栏

  • Dock栏 以及显示一个系统默认给加载的窗口.

找到 MainMenu.xib, 然后删除 Main Menu 以及 Window, 然后运行。

运行好之后,你会发现,状态栏左在没有那多选项了,但是还是存在一个 . Dock 栏以后存在, 值得称赞的是,系统默认加载的 Window 消失了

这是你需要在系统设置文件 info.plist 设置 Application is agent (UIElement) = YES 即可, 如下图

对了,别忘记删除 applicationDidFinishLaunching 上面的 @IBOutlet weak var window: NSWindow!, 因为window 以及被我们干没了。

三、NSPopover 使用

观察官方的 Pap.er, 点击 状态栏icon, 会出现如下界面:

.

macOS开发中,系统为我们提供了 NSPopover 来实现此效果。

3.1 NSPopover 属性介绍

查看NSPopover文档, 简单介绍其属性。

属性 说明
@IBOutlet weak open var delegate: NSPopoverDelegate? 代理
open var appearance: NSAppearance? popover的外观, 默认 NSAppearanceNameVibrantLight
open var behavior: NSPopover.Behavior Popover 的行为:
applicationDefined 表示NSPopover的关闭需要App自己负责控制;
transient: 表示只要点击到NSPopover显示的窗口之外就自动关闭;
semitransient: 表示 只要点击到NSPopover显示的窗口之外就自动关闭,但是点击到当前App 窗口之外不会关闭。
open var animates: Bool 是否动画
@IBOutlet open var contentViewController: NSViewController? popover 内容展示的控制器, 在show之前一定要设置
open var contentSize: NSSize popover 显示的大小
方法
open func show(relativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge) 显示
@IBAction open func performClose(_ sender: Any?) 关闭popover 但是有可能会关不掉
open func close() 强制关闭

3.2 JUST DO IT

简单介绍之后,我们开始动手吧。

Step1:applicationDidFinishLaunching 上面添加一个 NSPopover 的实例;

let popover = NSPopover()

Step2:applicationDidFinishLaunching 里面添加如下设置:

popover.behavior = .transient
popover.animates = true
popover.contentSize = CGSize(width: 285, height: 600)

Step3:statusItem.button的响应方法中添加对应的响应

if !self.popover.isShown {
self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: .minY)
}

仅仅这几步还是不行的, 我们忘记了最重要的设置 contentViewController.点击 File->New->File->MacOS->Cocoa Class, 新建一个 MainPopoverViewController, 我们采用xib 来布局视图,当然 这不是必须的;

Last Step: 在 Step2 设置 popover 的地方,添加一句

popover.contentViewController =  MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)

设置完之后, cmd + R 运行, 点击Status Item。显示如下,Great!

3.3 细节优化

  1. Popover 展示出来之后, 用户如果点击非App 区域, 那么需要Popover 消失, 有如下两种方式:
  • 获取用户点击的区域, 然后判断用户点击是否在Popover的 contentViewController上-- 此种方式比较复杂
  • 根据 NSApplicationDelegateapplicationWillResignActive 通知处理,简单,有效。
    func applicationWillResignActive(_ notification: Notification) {
    self.popover.close()
    }
  1. MainPopoverViewController 从nib中加载出来,但是外界其实不要知道其实例化方式, 给 MainPopoverViewController 提供一个类方法实例化即可。
extension MainPopoverViewController {
static func make() -> MainPopoverViewController {
let vc = MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)
return vc
}
}

四、代码

AppDelegate.swift

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) let popover = NSPopover() func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
let icon = NSImage(named: NSImage.Name(rawValue: "icon16*16"))
icon?.isTemplate = true
statusItem.image = icon
statusItem.button?.target = self
statusItem.button?.action = #selector(onStatusItemDidClicked(_:)) popover.contentViewController = MainPopoverViewController.make()
popover.behavior = .transient
popover.animates = true
popover.contentSize = CGSize(width: 285, height: 600) } @objc private func onStatusItemDidClicked(_ statusBarButton: NSStatusBarButton) {
print("onStatusItemDidClicked")
if !self.popover.isShown {
self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: .minY)
}
} func applicationWillResignActive(_ notification: Notification) {
self.popover.close()
}
}

MainPopoverViewController.swift

extension MainPopoverViewController {
static func make() -> MainPopoverViewController {
let vc = MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)
return vc
}
} class MainPopoverViewController: NSViewController { override func viewDidLoad() {
super.viewDidLoad()
} }

Pap.er 模仿 - 第一天的更多相关文章

  1. Pap.er 模仿 - 第二天

    最后更新:2017-12-19 在第一天中, 我们完成了项目的基本设置.隐藏Dock.显示和隐藏Popover等操作,接下来的这章中, Pap.er将会去搭建对应 UI. 一.设置Popover对应颜 ...

  2. power designer 绘制E-R 图

    总体概括:本篇主要先介绍E-R图的一些基本概念,然后介绍怎么绘制E-R图,特别是用power designer 的反向工程怎么把表中对字段的注释也展示出来. 1.E-R图的基本概念: E-R图就是en ...

  3. Tomcat6启用Gzip压缩功能

    配置Tomcat根目录下/conf/server.xml文件: <Connector port="8080" protocol="HTTP/1.1" co ...

  4. mongo数据库的常见操作

    连接mongodb数据库的命令查看对应数据库mongo.exeuse shujukuming;db.opportunity.findOne({"id":5}); db.opport ...

  5. 爬取5K分辨率超清唯美壁纸

    目录 爬取5K分辨率超清唯美壁纸 简介 编写思路 使用教程 演示图片 完整源代码 @ 爬取5K分辨率超清唯美壁纸 简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空 ...

  6. Mac 上有哪些比较有意思的小软件?

    文章素材来源:微博.新浪看点 收录于:风云社区(SCOEE)[提供mac软件下载] 更多专题,可关注小编[磨人的小妖精],查看我的文章,也可上[风云社区 SCOEE],查找和下载相关软件资源. (一) ...

  7. MetaMask/safe-event-emitter

    https://github.com/MetaMask/safe-event-emitter safe-event-emitter An EventEmitter that isolates the ...

  8. MSER最稳定极值区域源码分析

    最稳定极值区域介绍 如把灰度图看成高低起伏的地形图,其中灰度值看成海平面高度的话,MSER的作用就是在灰度图中找到符合条件的坑洼.条件为坑的最小高度,坑的大小,坑的倾斜程度,坑中如果已有小坑时大坑与小 ...

  9. 已知二叉树的中序序列为DBGEAFC,后序序列为DGEBFCA,给出相应的二叉树

    面对这种问题时我们该怎么解决? 今天写数据结构题.发现了一道总是碰见问题的题在这里我写了一种求解方法我自己称它为分层递归求解. 第一步通过观察我们知道后序遍历时最后一个是根节点A 在中序序列中A的左边 ...

随机推荐

  1. Marked Ancestor

    一道并查集的题目硬是被我当成线段树写了,感觉这样写虽然不是最好的,不过能a就行 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103906 ...

  2. SQL server字符分割

    USE [vanke_develop] GO /****** Object: UserDefinedFunction [dbo].[func_Split] Script Date: 2019/5/22 ...

  3. 你知道 Java 类是如何被加载的吗?

    前言 最近给一个非 Java 方向的朋友讲了下双亲委派模型,朋友让我写篇文章深度研究下JVM 的 ClassLoader,我确实也好久没写 JVM 相关的文章了,有点手痒痒,涂了皮炎平也抑制不住的那种 ...

  4. pistat 查看进程状态

    该pidstat命令用于监视当前正在由Linux内核管理的各个任务.对于使用选项-p选择的每个任务,或者如果使用了选项-p ALL,则它将写入Linux内核管理的 每个任务的标准输出活动.不选择任何任 ...

  5. git学习指南

    近来学习Git,苦寻资料下发现廖雪峰老师的教程很好,在此推荐传送门 附每节总结,方便查阅 创建版本库 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 使用命令git ...

  6. Burp Suite详细使用教程-Intruder模块详3

    Burp Suite使用详细教程连载的第三章.0×02 Intruder—内置有效负荷测试使用技巧内置有效负荷测试选择项如下图: 今天的小技巧使用的是 numbers,给大伙科普下:Numbers 数 ...

  7. 利用webSocket实现浏览器中多个标签页之间的通信

    webSoket用来实现双向通信,客户端和服务端实时通信. webSoket优点和缺点? 优点:对于前端来说,使用简单,功能灵活,如果部署了webSocket服务器,可以实现实时通信. 缺点:需要服务 ...

  8. 自己制作 Android Vector Asset 矢量图

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/c5138891/article/deta ...

  9. SpringMVC拦截器(资源和权限管理)

    转自:https://www.cnblogs.com/downey/p/4928951.html 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServl ...

  10. linux c下的c文件 h文件 o文件 so文件 a文件 可执行文件 gcc使用

    linux下c语言工程: c文件:主要每个模块的原代码都在c文件中. h文件:每个c文件都跟着一个h文件,h文件的作用是放着c文件中函数的声明,结构体的定义,宏的定义等. o文件:目标文件.每个文件经 ...