CATiledLayer doesn't work as expected on macOS.
It's choosing to render too few tiles.
In my example, my view is 300px wide. I set layer's transform scale to 4x.
In that case, CATiledLayer renders only two tiles: 50px wide at 2x scale, and stretches them.
Interestingly, when I run similar code on iOS, it works correctly - it renders 3 tiles, 25px wide at 4x scale.
Is it a bug or am I missing something here?
My code below:
class WaveformView: NSView {
		var scale: CGFloat = 1.0 {
				didSet {
						layer?.transform = CATransform3DScale(CATransform3DIdentity, scale, 1.0, 1.0)
						layer?.setNeedsDisplay(bounds)
				}
		}
		private var tiledLayer: CATiledLayer { layer as! CATiledLayer }
		override init(frame frameRect: NSRect) {
				super.init(frame: frameRect)
				wantsLayer = true
				tiledLayer.levelsOfDetail = 8
				tiledLayer.levelsOfDetailBias = 8
				tiledLayer.tileSize = CGSize(width: 100.0, height: .infinity)
				tiledLayer.contentsScale = 1.0
		}
		required init?(coder: NSCoder) {
				fatalError("init(coder:) has not been implemented")
		}
		override func draw(_ dirtyRect: NSRect) {
				let nsContext = NSGraphicsContext.current!
				let cgContext = nsContext.cgContext
				cgContext.saveGState()
				let scaleX: CGFloat = cgContext.ctm.a
				NSColor.red.setStroke()
				NSBezierPath(rect: dirtyRect)
						.stroke()
				let fontSize: CGFloat = 12.0
				let attr = [
						NSAttributedString.Key.font: NSFont.systemFont(ofSize: fontSize)
					]
				let str = "S: \(scaleX)\n\(dirtyRect.width)" as NSString
				str.draw(at: NSPoint(x: dirtyRect.minX, y: dirtyRect.midY), withAttributes: attr)
				nsContext.cgContext.restoreGState()
		}
		override func makeBackingLayer() -> CALayer {
				return CATiledLayer()
		}
}
2
0
1.7k