1,应用设置
@objc func termedApp(){
//关闭应用
NSApplication.shared.terminate(nil)
}
//显示提示角标
@objc func showAppAlertNum(){
NSApp.dockTile.badgeLabel = "20"
}
//app图标弹跳
@objc func appshaked(){
/*
criticalRequest 多次跳动,直到用户选中app
informationalRequest 一次跳动
*/
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
//此方法只能当前app处在非活跃状态
NSApp.requestUserAttention(NSApplication.RequestUserAttentionType.criticalRequest)
}
}
//隐藏或者显示dock图标
@objc func hidOrShowDockIcon(){
/*
/* The application is an ordinary app that appears in the Dock and may have a user interface. This is the default for bundled apps, unless overridden in the Info.plist. */
case regular
/* The application does not appear in the Dock and does not have a menu bar, but it may be activated programmatically or by clicking on one of its windows. This corresponds to LSUIElement=1 in the Info.plist. */
case accessory
/* The application does not appear in the Dock and may not create windows or be activated. This corresponds to LSBackgroundOnly=1 in the Info.plist. This is also the default for unbundled executables that do not have Info.plists. */
case prohibited
*/
//隐藏dock上的图标,上面的toolbar 也会隐藏
NSApp.setActivationPolicy(NSApplication.ActivationPolicy.accessory)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4) {
//显示窗口
NSApp.unhideWithoutActivation()
}
}
override func viewDidAppear() {
let window1 = view.window
//标题
window1?.title = "测试window"
//背景色
window1?.backgroundColor = NSColor.gray
//设置窗口的按钮关闭和最小化和全屏
// window1?.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
window1?.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
// window1?.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
//设置窗口显示级别,可以将窗口置顶
/*
如果两个window的级别是一样的,就按照出现顺序,后出现的显示最顶层,否则就按照levelz值大小来显示
*/
window1?.level = NSWindow.Level(rawValue: NSInteger(CGWindowLevelForKey(CGWindowLevelKey.normalWindow)))
//点击窗口背景支持鼠标拖动窗口
window1?.isMovableByWindowBackground = true
//希望窗口进来是全屏的
// window1?.toggleFullScreen(window1)
//在Dock中有窗口提示
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+5) {
window1?.dockTile.badgeLabel = "20"
}
//设置窗口样式
//不显示窗体边线
window1?.titlebarAppearsTransparent = true
}
AppDelegate.swift
import Cocoa
/***
类似main函数入口
*/
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var windownum = 0
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
//获取窗口号
guard let win = NSApp.mainWindow else {
return
}
windownum = win.windowNumber
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
//重新开关应用,
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
//如果主窗口已经显示
if flag == true {
return flag
}
//获取到app,让窗口显示出来
/*
NSApp.mainWindow 主窗口
NSApp.keyWindow 当前窗口
*/
let window = NSApp.window(withWindowNumber: windownum)
window?.makeKeyAndOrderFront(nil)
return true
}
}
2,常见控件使用
//开启背景色可编辑
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.white.cgColor
// Do view setup here.
let button1 = NSButton(frame: NSMakeRect(0, 0, 80, 50))
button1.title = "点击一下试试"
button1.alternateTitle = "欢迎再次点击"
view.addSubview(button1)
button1.state = NSControl.StateValue.on
button1.bezelStyle = .rounded
button1.setButtonType(NSButton.ButtonType.radio)
button1.image = NSImage(named: "42.png")
button1.alternateImage = NSImage(named: "39")
button1.target = self
button1.action = #selector(buttonClicked(sender:))
button1.tag = 10
let imageView = NSImageView(frame: NSMakeRect(20, 150, 40, 40))
view.addSubview(imageView);
imageView.image = NSImage(named: "44.png")
imageView.animates = true
imageView.isEditable = true
// imageView.allowsCutCopyPaste = true
/*
NSImageFrameNone = 0,
NSImageFramePhoto,
NSImageFrameGrayBezel,
NSImageFrameGroove,
NSImageFrameButton
*/
imageView.imageFrameStyle = .photo
//imageview 默认的animation 是 true
imageView.animates = true
//拖拽效果,苹果推荐使用nsbutton
imageView.target = self
imageView.action = #selector(clickImageview(_:))
//用户行为操作
/*1,imageview 上方添加一个按钮*/
/*2 手势操作*/
let clickGes = NSClickGestureRecognizer(target: self, action: #selector(clickImageViewFor1(_:)))
GesImageView.addGestureRecognizer(clickGes)
/*3 自定义nNSImageView 重写方法*/
MyImageV.target = self
MyImageV.action = #selector(clickMyOwnImagView)
}
@objc func clickMyOwnImagView(){
print("点击了自定义的imagView")
}
@objc func clickImageViewFor1(_ view1:NSControl) -> Void {
print("使用手势来处理")
}
@IBAction func ClickImageAction(_ sender: NSButton) {
print("点击图片按钮了")
}
@objc func clickImageview(_ view:NSImageView) -> Void {
print("其它文件图片已经拖拽到文件筐里了")
}
@objc func buttonClicked(sender : NSButton) -> Void {
print("Click button")
}
约束添加,中间有一部分控件是从故事版拉过来的
mybox.translatesAutoresizingMaskIntoConstraints = false
// NSLayoutAnchor
let myViewConts = [
mybox.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
mybox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20),
mybox.heightAnchor.constraint(equalToConstant: 20),
mybox.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20)
]
NSLayoutConstraint.activate(myViewConts)
mybox.layer?.backgroundColor = NSColor.red.cgColor
//关闭之前的试图约束
blueTf.translatesAutoresizingMaskIntoConstraints = false
//添加约束
let blueTfConts = [
blueTf.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20),
blueTf.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50),
blueTf.heightAnchor.constraint(equalToConstant: 80),
blueTf.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100)
]
//激活约束
NSLayoutConstraint.activate(blueTfConts)
//设置背景色
blueTf.layer?.backgroundColor = NSColor.blue.cgColor
3,点击按钮全屏
let window1 = self.view.window
window1?.toggleFullScreen(window1)
4,NSCollectionView 实现流布局
(1),注册单元格,或者头部视图
let headerId :String? = "BOB_Header"
class SevenVc: NSViewController {
//
@IBOutlet weak var myCollectionView: NSCollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
//注册NSCollectionView的Items
myCollectionView.register( MyCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ADC"))
//headerView 或者 footerView需要维护
let headNib = NSNib(nibNamed: "HeadView", bundle: nil)
myCollectionView.register(headNib, forSupplementaryViewOfKind: (NSCollectionView.elementKindSectionHeader), withIdentifier: NSUserInterfaceItemIdentifier(headerId ?? ""))
(myCollectionView.collectionViewLayout as! NSCollectionViewFlowLayout).sectionHeadersPinToVisibleBounds = true
}
}
(2),遵守NSCollectionViewDelegate 和NSCollectionViewDataSource 协议,并且实现协议方法
//数据源
extension SevenVc:NSCollectionViewDataSource{
//返回每个section中单元格个数
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
//section个数
func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 2
}
// func collectionViewItem 的样式
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ADC"), for: indexPath) as! MyCollectionViewItem
var imageName:String = "39.png"
switch ((indexPath.item) % 3) {
case 0:
imageName = "39.png"
break
case 1:
imageName = "42.png"
break
case 2:
imageName = "44.png"
break
default:
imageName = "39.png"
break
}
// let image = NSImage(named: <#T##NSImage.Name#>)
// item.mimageView.image = NSImage(byReferencingFile: imageName)
item.mtitleLab.stringValue = "\(indexPath.item)"
return item
}
//headview和footerView的操作
func collectionView(_ collectionView: NSCollectionView, viewForSupplementaryElementOfKind kind: NSCollectionView.SupplementaryElementKind, at indexPath: IndexPath) -> NSView {
let headView = collectionView.makeSupplementaryView(ofKind: NSCollectionView.elementKindSectionHeader, withIdentifier: NSUserInterfaceItemIdentifier(headerId ?? ""), for: indexPath) as! HeaderView
headView.TitleLab.stringValue = "\(indexPath.section)"
return headView
}
}
//代理的操作
extension SevenVc:NSCollectionViewDelegate{
//选中操作
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("选中操作 ")
}
//取消选中操作
func collectionView(_ collectionView: NSCollectionView, didDeselectItemsAt indexPaths: Set<IndexPath>) {
print("取消选中")
}
}
5 NSAlert 和 NSPopover 提示的使用
import Cocoa
class TwoVc: NSViewController {
var popVc:NSWindowController?
@IBOutlet weak var btn1: NSButton!
@IBOutlet weak var btn2: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
btn1.target = self
btn1.action = #selector(showAlert1)
btn2.target = self
btn2.action = #selector(showPopOver)
}
@objc func showPopOver(){
let popOver = NSPopover()
//从故事版加载控制器
let popoverVc = NSStoryboard(name: "Two", bundle: nil).instantiateController(withIdentifier: "popOverVc") as! NSViewController
//设置内容控制器
popOver.contentViewController = popoverVc
popOver.delegate = self
/*
case applicationDefined 默认值,不会关闭
case transient 点击窗口以外会关闭
case semitransient 点击esc 消失
*/
popOver.behavior = .semitransient
/*
显示popover
relativeTo:popover 三角箭头指向的边界
of:说明第一个控件的父控件
preferredEdge:四条边的那一条边界
*/
popOver.show(relativeTo: view.bounds, of: view, preferredEdge: NSRectEdge.maxY)
}
@objc func showAlert1(){
let alert = NSAlert()
alert.messageText = "提示警告"
alert.informativeText = "显示提示框详细内容"
alert.icon = NSImage(named: "warn")
alert.addButton(withTitle: "按钮1")
alert.addButton(withTitle: "按钮2")
let btns = alert.buttons
for btn in btns {
print(btn.title)
}
//代理方法,实现z帮助内容
alert.delegate = self
alert.showsHelp = true
alert.helpAnchor = "帮助内容"
//辅助视图
alert.layout()
let imgV = NSImageView(frame: NSMakeRect(0, 0, 100, 100))
imgV.image = NSImage(named: "beauty")
alert.accessoryView = imgV
alert.showsSuppressionButton = true
alert.suppressionButton?.title = "是否不再提示"
//关联窗口显示
alert.beginSheetModal(for: view.window!) { (result) in
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
print("点击了btn1")
}
//是否选中
print(alert.suppressionButton?.state)
}
//独立窗口显示
// let result = alert.runModal()
// if result == NSApplication.ModalResponse.alertFirstButtonReturn {
// print("点击了btn1")
// }
}
}
//NSAlertDelegate
extension TwoVc:NSAlertDelegate{
//return false 表示代理自己处理,否则就是系统自己处理
func alertShowHelp(_ alert: NSAlert) -> Bool {
//一般跳转帮助页面来提示
print("点击了帮组选项")
return false
}
}
//NSPopoverDelegate
extension TwoVc:NSPopoverDelegate{
//根据返回值确认窗口是否可以关闭
func popoverShouldClose(_ popover: NSPopover) -> Bool {
print("想要关闭窗口")
return true
}
func popoverDidShow(_ notification: Notification) {
print("显示了")
}
func popoverDidClose(_ notification: Notification) {
print("已经关闭窗口")
}
func popoverWillShow(_ notification: Notification) {
print("将要显示")
}
func popoverWillClose(_ notification: Notification) {
print("将要关闭窗口")
}
//支持鼠标拖动
func popoverShouldDetach(_ popover: NSPopover) -> Bool {
return true
}
func popoverDidDetach(_ popover: NSPopover) {
print("拖动")
}
//拖动时候变成独立window
func detachableWindow(for popover: NSPopover) -> NSWindow? {
popVc = NSStoryboard(name: "Two", bundle: nil).instantiateController(withIdentifier: "popwindowVc") as! NSWindowController
return popVc?.window
}
}
5,NSMenu菜单使用
(1).app菜单:系统会提供一个默认的菜单
(2).控件右侧显示菜单:应用本身提供一些快捷操作选项,控件左侧也有但是很少用
(3).Dock栏上菜单,系统有默认选项,用户可以自己添加
(4).使用故事板 MainStoryBoard 会有默认menu 可编辑
(5).在StoryBoard的ViewController最上方bar上添加,编辑
//
// ThreeVc.swift
// MyMacOsApp1
//
// Created by syStudio sy on 2019/6/3.
// Copyright © 2019 syStudio sy. All rights reserved.
//
import Cocoa
/*
1。app菜单:系统会提供一个默认的菜单
2,控件右侧显示菜单:应用本身提供一些快捷操作选项,控件左侧也有但是很少用
3.Dock栏上菜单,系统有默认选项,用户可以自己添加
*/
class ThreeVc: NSViewController {
@IBOutlet weak var leftBtnMenu: NSButton!
@IBOutlet weak var rightBtnMenu: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
rightBtnMenu.target = self
rightBtnMenu.action = #selector(showRightMenue)
leftBtnMenu.target = self
leftBtnMenu.action = #selector(showLeftMenue)
//添加系统菜单栏Item
addAppMenueItem()
}
@objc func showRightMenue(){
let rightMenue = NSMenu(title: "菜单")
let item = NSMenuItem(title: "功能1", action: #selector(clickItems(Sender:)), keyEquivalent: "")
let item1 = NSMenuItem(title: "功能2", action: #selector(clickItems(Sender:)), keyEquivalent: "")
let item2 = NSMenuItem(title: "功能2", action: #selector(clickItems(Sender:)), keyEquivalent: "")
rightMenue.addItem(item)
rightMenue.addItem(item1)
rightMenue.addItem(item2)
//给右键菜单f
rightBtnMenu.menu = rightMenue
}
@objc func clickItems(Sender:NSMenuItem) -> Void {
print("\(Sender.title)")
}
//添加左键菜单
@objc func showLeftMenue(){
let menu = NSMenu(title: "左键")
let item = NSMenuItem(title: "功能1", action: #selector(clickItems(Sender:)), keyEquivalent: "")
let item1 = NSMenuItem(title: "功能2", action: #selector(clickItems(Sender:)), keyEquivalent: "")
let item2 = NSMenuItem(title: "功能3", action: #selector(clickItems(Sender:)), keyEquivalent: "")
menu.addItem(item)
menu.addItem(item1)
menu.addItem(item2)
//绑定事件
NSMenu.popUpContextMenu(menu, with: NSApp.currentEvent!, for: leftBtnMenu)
}
//在app菜单栏添加
func addAppMenueItem() -> Void {
//1.获取app菜单
let menu = NSApp.mainMenu
//2.创建item
let myMenue = NSMenu(title: "MyMenue")
let item1 = NSMenuItem(title: "我的设置", action: #selector(clickItems1(Sender:)), keyEquivalent: "")
//添加z到我的菜单
// myMenue.addItem(item1)
//将我们的菜单项添加到主菜单
let mFirstItem = menu?.items.first
//这样添加会覆盖,就是重新生成一个新菜单
// mFirstItem?.submenu = myMenue
mFirstItem?.submenu?.insertItem(item1, at: 0)
}
}
extension ThreeVc{
@objc func clickItems1(Sender:NSMenuItem) -> Void {
print("\(Sender.title)")
}
}