NSViewRepresentable 是 SwiftUI 中的一个协议,用来将 macOS 的 AppKit 视图(NSView)嵌入到 SwiftUI 界面中。
NSViewRepresentable 可以在 SwiftUI 中“包装”一个 NSView,从而在 SwiftUI 界面中使用任意 AppKit 控件,比如:NSColorWell、NSTextView、NSScrollView、NSVisualEffectView,甚至自定义的 NSView 子类。
协议结构
protocol NSViewRepresentable {
associatedtype NSViewType: NSView
func makeNSView(context: Context) -> NSViewType
func updateNSView(_ nsView: NSViewType, context: Context)
}
在SwiftUI视图中,需要创建一个遵循NSViewRepresentable协议的结构,并且实现makeNSView和updateNSView方法:
struct NSSomeView: NSViewRepresentable {
func makeNSView(context: Context) -> 返回的NS类型{
创建 NS 视图/控件
return NS 视图/控件
}
func updateNSView(_ nsView: NS类型, context: Context) {
// 更新 NSView 时会调用
}
}
其中,makeNSView需要返回对应的NSViewType类型的视图/控件。
基本用法
创建一个遵循NSViewRepresentable协议的结构。
import SwiftUI
import AppKit
struct ColorWellView: NSViewRepresentable {
func makeNSView(context: Context) -> NSColorWell {
let colorWell = NSColorWell()
colorWell.color = .systemRed
return colorWell
}
func updateNSView(_ nsView: NSColorWell, context: Context) {
// 更新 NSView 时会调用,例如绑定颜色状态
}
}
在SwiftUI中显示该NSView视图:
struct ContentView: View {
var body: some View {
VStack {
ColorWellView()
.frame(width: 160,height:100)
.cornerRadius(10)
.shadow(radius: 3)
}
.frame(width: 200,height: 140)
}
}

生命周期
1、makeNSView(context:):创建 NSView 实例(只调用一次)。
2、updateNSView(_:context:):SwiftUI 状态变化时更新 view 的属性。
3、Context 参数:提供如 Coordinator、环境信息等。
使用场景
1、支持Binding扩展
struct ColorWellRepresentable: NSViewRepresentable {
@Binding var selectedColor: NSColor
func makeNSView(context: Context) -> NSColorWell {
let colorWell = NSColorWell()
colorWell.color = selectedColor
colorWell.target = context.coordinator
colorWell.action = #selector(Coordinator.colorChanged(_:))
return colorWell
}
func updateNSView(_ nsView: NSColorWell, context: Context) {
if nsView.color != selectedColor {
nsView.color = selectedColor
}
}
func makeCoordinator() -> Coordinator {
Coordinator(color: $selectedColor)
}
class Coordinator {
var selectedColor: Binding<NSColor>
init(color: Binding<NSColor>) {
self.selectedColor = color
}
@objc func colorChanged(_ sender: NSColorWell) {
selectedColor.wrappedValue = sender.color
}
}
}
在SwiftUI中,将变量传递给ColorWellRepresentable。
struct ContentView: View {
@State private var selectedColor: NSColor = .systemBlue
var body: some View {
VStack {
Text("颜色选择器")
.foregroundColor(Color(selectedColor))
.padding()
ColorWellRepresentable(selectedColor: $selectedColor)
.frame(width: 60, height: 30)
}
.frame(width: 300,height: 200)
}
}
知识点
1、context是什么?
在 SwiftUI 中,当实现一个 NSViewRepresentable(或 UIViewRepresentable)时,makeNSView(context:) 和 updateNSView(_:context:) 这两个函数会传入一个参数:
func makeNSView(context: Context) -> NSSplitView
这个 context 是 SwiftUI 传给结构体,包含了协调器(Coordinator)和环境信息。
struct Context {
var coordinator: Coordinator
var environment: EnvironmentValues
...
}
它是 SwiftUI 提供的桥梁,作用包括:
1、context.coordinator:提供自定义的 Coordinator 对象(用于代理、事件、共享状态)。
2、context.environment:当前 SwiftUI 的环境(如颜色模式、字体大小)。
也就是说,可以通过 context.coordinator 访问到Coordinator 实例。
func makeCoordinator() -> Coordinator {
Coordinator(color: $selectedColor) // 通过 context.coordinator 访问到该实例
}
2、Coordinator是什么?
Coordinator 是 NSViewRepresentable 提供的机制,用于在 SwiftUI 和 AppKit 之间保存状态和处理桥接逻辑(比如 delegate)。
通过实现这个方法来提供一个 Coordinator 实例:
func makeCoordinator() -> Coordinator
SwiftUI 会:
1、自动调用 makeCoordinator(),创建 Coordinator。
2、自动保留它的引用(直到视图销毁)。
3、把它作为 context.coordinator 使用。
例如,在Coordinator创建对象,设置强引用:
class Coordinator {
let delegate = MySplitDelegate() // 被强引用住
}
然后在 makeNSView 中设置 delegate:
splitView.delegate = context.coordinator.delegate
这样 delegate 会和 Coordinator 一起被 SwiftUI 持久保存。
可以进一步阅读《SwiftUI桥接协议事件回调Coordinator》。
总结
NSViewRepresentable 是 SwiftUI 与 AppKit(NSView)之间的桥梁,在 SwiftUI 中复用任何 macOS 原生控件或自定义视图。
相关文章
1、SwiftUI、AppKit和UIKit之间的桥接控制器:https://fangjunyu.com/2025/06/30/swiftui%e3%80%81appkit%e5%92%8cuikit%e4%b9%8b%e9%97%b4%e7%9a%84%e6%a1%a5%e6%8e%a5%e6%8e%a7%e5%88%b6%e5%99%a8/
2、UIKit显示SwiftUI的桥接控制器UIHostingController:https://fangjunyu.com/2025/06/30/uikit%e6%98%be%e7%a4%baswiftui%e7%9a%84%e4%be%a8%e6%8e%a5%e6%8e%a7%e5%88%b6%e5%99%a8uihostingcontroller/
3、macOS显示SwiftUI的桥接控制器NSHostingController:https://fangjunyu.com/2025/06/30/macos%e6%98%be%e7%a4%baswiftui%e7%9a%84%e6%a1%a5%e6%8e%a5%e6%8e%a7%e5%88%b6%e5%99%a8nshostingcontroller/
4、SwiftUI桥接协议事件回调Coordinator:https://fangjunyu.com/2025/07/03/swiftui%e6%a1%a5%e6%8e%a5%e5%8d%8f%e8%ae%ae%e4%ba%8b%e4%bb%b6%e5%9b%9e%e8%b0%83coordinator/