面试题答案
一键面试NSView(macOS)和UIView(iOS)在图形绘制方面的差异
- 绘制方法调用时机
- NSView:通常在
draw(_:)
方法中进行绘制,当视图需要重绘时(如窗口大小改变、视图显示状态变化等),系统会自动调用该方法。 - UIView:自定义绘制一般在
draw(_:)
方法,但iOS视图默认是不调用此方法的,需要手动调用setNeedsDisplay
方法来标记视图需要重绘,然后系统会在合适的时机调用draw(_:)
。
- NSView:通常在
- 坐标系统
- NSView:坐标原点在视图的左下角,x轴向右增长,y轴向上增长。
- UIView:坐标原点在视图的左上角,x轴向右增长,y轴向下增长。
- 绘制环境
- NSView:使用
NSGraphicsContext
,它提供了与macOS图形系统交互的接口,支持Core Graphics(Quartz 2D)以及更高级的Core Animation等技术。 - UIView:使用
UIGraphicsGetCurrentContext()
获取CGContext
,主要基于Core Graphics进行绘制,在iOS上Core Animation也广泛用于动画和视图合成。
- NSView:使用
在不同平台上实现类似自定义图形绘制效果的方法
- 抽象绘制逻辑:将通用的图形绘制逻辑抽象成独立的函数或类方法。例如,绘制一个圆形,可以定义一个函数
drawCircle(withRadius: center: context:)
,其中context
参数根据平台不同传入对应的CGContext
(iOS)或NSGraphicsContext
(macOS)。 - 适配坐标系统:在调用绘制逻辑前,根据平台坐标系统的差异进行坐标转换。比如在iOS上,如果要实现和macOS相同的位置效果,需要将y坐标进行转换,例如
y = view.bounds.height - y - radius
(假设绘制圆形)。 - 利用跨平台图形库:一些跨平台图形库,如Skia,可用于在iOS和macOS上实现一致的图形绘制效果,减少针对不同平台的特定代码编写。
各自平台图形绘制的性能优化要点
macOS(NSView)
- 减少重绘区域:使用
NSRect
来精确指定需要重绘的区域,在draw(_:)
方法中,通过NSGraphicsContext.current?.graphicsPort.clip(to: rect)
来设置裁剪区域,避免不必要的绘制。 - 缓存静态内容:对于不经常变化的图形内容,使用
NSImage
进行缓存。例如,在视图初始化时绘制一次复杂图形到NSImage
,后续直接在draw(_:)
方法中绘制该NSImage
。 - 优化Core Animation:合理使用
CAAnimation
,避免过度复杂的动画组合。例如,对于简单的视图移动动画,使用CABasicAnimation
直接操作position
属性,而不是对整个视图进行复杂的动画变换。
iOS(UIView)
- 使用视图复用:在UITableView或UICollectionView等可复用视图的场景中,尽量复用视图,减少新视图的创建和绘制。例如,在
UITableView
的cellForRowAtIndexPath:
方法中复用UITableViewCell
。 - 异步绘制:利用
CADisplayLink
和UIGraphicsBeginImageContextWithOptions
等方法在后台线程进行绘制,然后在主线程更新视图。这样可以避免主线程阻塞,提高用户体验。 - 优化图片加载和绘制:对于图片绘制,使用
UIImage
的init(data:)
方法加载图片时,尽量在后台线程进行,并且根据设备屏幕分辨率加载合适尺寸的图片,避免内存浪费和性能损耗。