首页 > 其他分享 >Mac开发基础06-NSView(二)

Mac开发基础06-NSView(二)

时间:2024-08-06 14:19:44浏览次数:8  
标签:dirtyRect 06 self NSView 视图 Mac super view

要理解 NSView 更深层的知识,涉及到其渲染机制、事件处理流程、与 CALayer 的关系及性能优化等方面。

1. NSView 绘制和渲染机制

NSView 的绘制过程主要依赖于 drawRect:(Objective-C)或 draw(_:)(Swift)方法。这个方法被调用是由系统驱动的,通常发生在需要重新绘制视图的时候,如窗口首次显示、窗口大小改变或强制刷新(调用 setNeedsDisplay:)。

绘制生命周期

  • - setNeedsDisplay::标记视图需要重新绘制。
  • - displayIfNeeded:检查视图是否需要绘制,如果需要则调用 drawRect:.
  • - displayRectIgnoringOpacity:- display:可以手动触发视图的绘制。
Objective-C
[view setNeedsDisplay:YES];  // 标记视图需要重新绘制
[view displayIfNeeded];      // 如果需要的话,立即进行绘制
Swift
view.needsDisplay = true  // 标记视图需要重新绘制
view.displayIfNeeded()    // 如果需要的话,立即进行绘制

使用 NSGraphicsContextCGContext

drawRect: 方法中,你可以使用 NSGraphicsContext 获取底层的 CGContext,以便进行更底层的绘图操作。

Objective-C
- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
    CGContextRef context = [currentContext CGContext];
    
    CGContextSetFillColorWithColor(context, [[NSColor redColor] CGColor]);
    CGContextFillRect(context, dirtyRect);
}
Swift
override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    if let context = NSGraphicsContext.current?.cgContext {
        context.setFillColor(NSColor.red.cgColor)
        context.fill(dirtyRect)
    }
}

2. 事件处理流程

响应链

macOS 应用中的事件处理是基于响应链的。响应链起始于窗口,然后传递到最适合处理事件的视图。如果视图不能处理事件,则继续传递给其超级视图,直到到达窗口对象。如果窗口对象也无法处理事件,事件将被忽略。

hitTest:

hitTest: 方法用来确定一个点是否在视图内,它是事件传递过程中关键的一环。

Objective-C
- (NSView *)hitTest:(NSPoint)aPoint {
    NSView *hitView = [super hitTest:aPoint];
    NSLog(@"Hit view: %@", hitView);
    return hitView;
}
Swift
override func hitTest(_ point: NSPoint) -> NSView? {
    let hitView = super.hitTest(point)
    print("Hit view: \(String(describing: hitView))")
    return hitView
}

用户事件处理

Objective-C
- (void)mouseDown:(NSEvent *)event {
    NSPoint locationInWindow = [event locationInWindow];
    NSPoint locationInView = [self convertPoint:locationInWindow fromView:nil];
    NSLog(@"Mouse down at %@", NSStringFromPoint(locationInView));
}
Swift
override func mouseDown(with event: NSEvent) {
    let locationInWindow = event.locationInWindow
    let locationInView = self.convert(locationInWindow, from: nil)
    print("Mouse down at \(locationInView)")
}

3. NSView 和 CALayer 的关系

wantsLayer 和 layer-backed 视图

通过设置 wantsLayer,你可以让 NSView 支持 Core Animation 并使用 CALayer 来管理其内容。这样可以利用 Core Animation 的各种特性,比如动画、变换和更高效的离屏渲染。

Objective-C
[view setWantsLayer:YES];
view.layer.backgroundColor = [[NSColor blueColor] CGColor];
Swift
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.blue.cgColor

4. 性能优化

视图层级

避免过于复杂的视图层级(视图层次结构越深,重绘时需要更新的区域也越多)。尽量减少不必要的子视图。

使用 CALayer

  • 缓存:可以使用 CALayercontents 属性来缓存绘制内容,减少重复绘制开销。
  • 离屏渲染:合理使用 shouldRasterize 来进行离屏渲染,提升复杂视图的渲染性能。
Objective-C
view.layer.shouldRasterize = YES;
view.layer.rasterizationScale = [NSScreen mainScreen].backingScaleFactor;
Swift
view.layer?.shouldRasterize = true
view.layer?.rasterizationScale = NSScreen.main?.backingScaleFactor ?? 1.0

5. 高级自定义绘图

使用 NSBezierPath

NSBezierPath 是用于描述矢量路径的类,适合用于自定义复杂的绘图。

Objective-C
- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    NSBezierPath *path = [NSBezierPath bezierPathWithRect:dirtyRect];
    [[NSColor redColor] setFill];
    [path fill];
}
Swift
override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    let path = NSBezierPath(rect: dirtyRect)
    NSColor.red.setFill()
    path.fill()
}

6. 自定义 NSView 子类

通过自定义 NSView 子类,可以实现更多高级功能。例如,创建一个交互响应的绘图视图:

Objective-C
@interface CustomView : NSView
@end

@implementation CustomView

- (instancetype)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setWantsLayer:YES];
        self.layer.backgroundColor = [[NSColor whiteColor] CGColor];
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect:dirtyRect];
    [[NSColor blueColor] setFill];
    [path fill];
}

- (void)mouseDown:(NSEvent *)event {
    NSPoint location = [self convertPoint:event.locationInWindow fromView:nil];
    NSLog(@"Mouse clicked at %@", NSStringFromPoint(location));
}
@end
Swift
class CustomView: NSView {
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.wantsLayer = true
        self.layer?.backgroundColor = NSColor.white.cgColor
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        
        let path = NSBezierPath(ovalIn: dirtyRect)
        NSColor.blue.setFill()
        path.fill()
    }
    
    override func mouseDown(with event: NSEvent) {
        let location = self.convert(event.locationInWindow, from: nil)
        print("Mouse clicked at \(location)")
    }
}

标签:dirtyRect,06,self,NSView,视图,Mac,super,view
From: https://www.cnblogs.com/chglog/p/18345029

相关文章

  • Mac开发基础05-NSView
    NSView概述NSView是macOS应用中所有用户界面元素的基类。它提供了一系列功能用于视图的绘制、事件处理、动画、自动布局等。1.基本属性bounds和framebounds描述了视图自身坐标系中的矩形区域,而frame描述了视图在其父视图坐标系中的矩形区域。Objective-CNSView*v......
  • 20240806:点分治,虚树选做
    POJ-1741Tree题意:给定一棵树,求多少无序对\((u,v)\)满足\(\text{dist}(u,v)\lek\)。对于树上的路径进行分类:经过根;不经过根。第二类路径点可以通过递归子树求出。对于经过根的路径,可以一遍dfs求出每个点到根的距离\(\text{dis}(u)\)。问题转化为求\(\text{dis}(u)......
  • T240806【2-(一)-1】
    [T240806]设连续函数\(C:~z=z(t),~t\in[\alpha,\beta]\),有\(z'(t_0)\neq0~~(t_0\in[\alpha,\beta])\),试证明曲线\(C\)在点\(z(t_0)\)处有切线.证:先证明曲线\(C\)存在无重点的\(z(t_0)\)邻域.由题设知\(\exists\delta>0\),对\(\forallt_1\inU_{\delta}^......
  • Plugin Boutique Scaler EQ V1.1.3_WIN-TCD&MAC-HCiSO(2024.08更新),持续更新长期有效
    一。PluginBoutiqueScalerEQ1.1.3WIN-TCD&MAC-HCiSO   紧随屡获殊荣的音乐理论插件Scaler之后,ScalerEQ以一种引人注目的全新方式提供了音乐性和色彩的均衡。ScalerEQ是PluginBoutique推出的一款创新均衡器插件,结合传统和和声均衡功能,专注于音乐理论,为音乐制作和混......
  • 0.96寸(128*64) OLED(SSD1306) 中英显示篇
    总线接口模式(现使用的比较多的是4线SPI控制和I2C控制,接下来将以I2C控制为例子)I2C总线数据格式(数据的转换是在I2C协议线中的SCL为低时,进行数据调整)内容数据映射的分布图(I2C的读写时序就不重复造轮子嘞,接下来对屏幕显示的驱动细节做一些要点的总结和整理)当前......
  • BitDock:为Windows桌面带来Mac风格的美化工具(附下载)
    许多人对Mac系统的精致界面情有独钟,但面对苹果电脑不菲的价格标签——就例如年初新登场的基础款MacBookAir,即便配置朴素,也轻易跨过了八千大关(这预算在Windows阵营足以拥抱高端配置),不免让人望而却步。幸运的是,将Windows系统改头换面,焕发Mac般的高雅并非遥不可及的梦想。下载:Bi......
  • Parallels Desktop19.3.0虚拟机软件可以让你在Mac上同时运行Windows、Linux等多个系统
    ParallelsDesktop19,一个虚拟机软件,可以让你在Mac上同时运行Windows、Linux等多个系统。听起来是不是很厉害?但其实它还有更多隐藏的小技巧等着你去发现。如果你还在因为Mac和Windows之间的不兼容而苦恼,那么ParallelsDesktop19就是你的救星。它可以帮助你轻松地在Mac上运行Win......
  • Parallels Desktop19Mac就是这样一个神器!在Windows和Mac之间反复切换横跳!
    在Windows和Mac之间反复横跳,是很多职场人的常态。Windows系统生态完善,软件丰富;而Mac的优雅设计、出色的性能以及稳定的系统体验也让人难以舍弃。但鱼与熊掌不可得兼,两个系统来回切换,需要准备两台电脑,既麻烦又占用空间,还增加了经济负担。如果一台电脑可以同时运行两个操作系......
  • 《DNK210使用指南 -CanMV版 V1.0》第十七章 machine.WDT类实验
    第十七章machine.WDT类实验1)实验平台:正点原子DNK210开发板2)章节摘自【正点原子】DNK210使用指南-CanMV版V1.03)购买链接:https://detail.tmall.com/item.htm?&id=7828013987504)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html5)正......
  • 苹果第一款M4笔记本来了!曝M4 MacBook Pro今年秋季亮相
    MarkGurman爆料,M4MacBookPro、Macmini和iMac将在今年秋季上市,其中M4MacBookPro是苹果第一款M4笔记本。他还提到,MacBookAir、MacStudio和MacPro将在2025年更新,届时也会升级M4芯片。据悉,M4由iPadPro首发搭载,采用了台积电第二代3nm制程工艺(N3E),并配备当前AIPC主流的CPU+GP......