MAC-OS开发笔记一 NSWindow
创建新的Xcode工程,选择 macOS,如下图,点击Next,如下图。过程与创建iOS项目一样。
默认会有main.storyboard文件,个人喜好以及习惯问题,我删除了该文件,于是,第一个问题出现了。(个人习惯:带着问题去学习)
问题 一、窗口怎么显示在屏幕上?
在 AppDelegate.m 文件里我这样写:
@interfaceAppDelegate()
@property(nonatomic,strong)NSWindow*mainWindow;//窗口
@end
@implementationAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
{//设置window
/**
创建方法:重点说一下第二个参数styleMask,添加了一大堆枚举,以下列出常用的几个
NSWindowStyleMaskMiniaturizable 可最小化
NSWindowStyleMaskResizable可调整尺寸,即拉伸
NSWindowStyleMaskTitled 显示标题
NSWindowStyleMaskClosable 可关闭,如果不加,则关闭按钮处显示一个灰色按钮,不可点击
*/
_m_windowMain= [[NSWindowalloc]initWithContentRect:CGRectMake(0,0,800,600)styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable|NSWindowStyleMaskUtilityWindowbacking:NSBackingStoreRetaineddefer:NO];
//全屏按钮显示以及点击后效果,默认为“+”号,点击后在当前屏幕放大;这里设置为新桌面放大
_m_windowMain.collectionBehavior=NSWindowCollectionBehaviorFullScreenPrimary;
_m_windowMain.delegate=self;
[_m_windowMaincenter];
[_m_windowMainmakeKeyWindow];
//设置最小缩放
[_m_windowMainsetMinSize:CGSizeMake(400,300)];
//将window与APP绑定,如果不绑定,无法显示Window。
[NSAppbeginModalSessionForWindow:_m_windowMain];
}
}
@end
注意最后那句注释,[NSAppbeginModalSessionForWindow:_m_windowMain]这句话看似已经完成Window显示到屏幕上这个工作了,实则不然,运行之后Window没有显示。与iOS不同之处,我们还要对main.m文件进行更改。如果是用main.storyboad文件的朋友则不需要,因为OS开发的main.storyboad比iOS的多做了些功能。
在main.m文件中修改并添加如下代码:
intmain(intargc,constchar* argv[]) {
NSApplication*applicaton = [NSApplicationsharedApplication];
iddelegete = [[AppDelegatealloc]init];
applicaton.delegate= delegete;
returnNSApplicationMain(argc, argv);
}
再次运行,正常情况下你就能看到Window了,但是是个灰色的,那么再来看第二个问题。
问题 二、如何更改背景色?
其实看了上一段代码,熟悉iOS开发的朋友应该能看出来,iOS开发中UIKit中的东西是用UI开头的,比如UIWindow,UIView等,而在OS开发中,与之相对于就是NSWindow,NSView了。
NSWindow有个属性叫contentView,继承NSView,所以改变Window的背景色,可以从这个属性开始。与UIView不同的是NSView没有backgroundColor属性,不过还好,有个layer可以用,于是按照思路猜测,是这样写的:
[_m_windowMain.contentView.layersetBackgroundColor:[[NSColorwhiteColor]CGColor]];
运行起来后,然并卵!!!就像iOS开发中给UIView的子类设置圆角一样,需要开启允许裁剪开关,查了些资料,找到这句话:
_m_windowMain.contentView.wantsLayer=YES;
本人英语水平一般般,大概是告诉编译器:这个NSView,我要使用它的Layer,所以对它的Layer设置要有效🤣。
到这里运行程序之后,背景色是白色,点击关闭按钮,窗口消失,但是怎么再让窗口显示呢?
问题 三、如何关闭窗口后再显示?
首先说说我的思路:点击关闭,窗口消失,点击dock中的Icon,窗口再显示;可是刚才点击Dock是没有反应的,所以点击Dock应该是有个方法的。
/**
点击Dock Icon事件
flag:窗口存在YES;窗口关闭NO
*/
- (BOOL)applicationShouldHandleReopen:(NSApplication*)theApplication hasVisibleWindows:(BOOL)flag {
if(!flag){
[NSAppactivateIgnoringOtherApps:NO];//取消其他程序的响应
[_m_windowMainmakeKeyAndOrderFront:self];//主窗口显示自己方法一
//[_mainWindow orderFront:nil]; //主窗口显示自己方法二
returnYES;
}
returnNO;
}
上述方法是NSApplicationDelegate中的,监听了点击Dock中的Icon。看注释应该知道是怎么回事。运行,点击关闭,点击Dock中的Icon,Window出现了,别高兴太早,试试再次点击关闭,你会发现,关闭按钮失效了。好吧,再查……
- (BOOL)windowShouldClose:(id)sender {
[_m_windowMainorderOut:nil];//窗口消失
returnNO;
}
麻烦再添加上述代码,此方法是NSWindowDelegate的,看来目前用过的程序都是假关闭,因为returnNO,意思是不让Window关闭。该方法是监听点击Window上的关闭按钮,而像其他一般程序那样的关闭再打开再关闭的,得用[_m_windowMainorderOut:nil]来实现。(PS:苹果API也不给个注释什么的,参数我都不知道咋给,暂时给nil)。
现在先抛出一个问题,后面做到那块了再去验证:视频播放器(比如爱奇艺),关闭窗口后视频停止了播放,音乐播放器(比如QQ音乐),关闭窗口后音乐还在播放。这两种关闭窗口的方法是否为同一种方法?或者类似于iOS开发,有个“程序后台执行权限”?
问题 四、窗口随着鼠标拖动放大缩小
直接上货吧,找NSApplicationDelegate,实现如下几个方法:
/**
拖动放大缩小、点击全屏(换桌面全屏)时
可以在此方法中更改界面布局,如果未设置最小
*/
- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize {
returnframeSize;
}
/**
当点击“+”号,或者双击放大时,即在本屏幕方法
以下两个方法都是,可以根据返回值控制想要的效果
第一个方法只有放大的时候会被调用
第二个放大缩小都会调用
双击放大时不会调用上面的方法(windowWillResize),因此都需要实现
*/
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window defaultFrame:(NSRect)newFrame {
returnnewFrame;
}
- (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame {
if(newFrame.size.height>350) {
returnYES;
}
returnNO;
}
关于 窗口放大缩小这两个方法也就够了,还有其他的方法,但是没搞清楚来龙去脉。