⛓️ ResponderChain
无需对视图或 SwiftUI 中的自定义 ViewRepresentables 进行子类化即可实现跨平台的第一个响应者处理
特点
- 通过
ResponderChain.firstResponder
获取当前第一个响应者 - 通过
ResponderChain.firstResponder
设置新的第一个响应者 - 通过
ResponderChain.availableResponders
获取可用于接收第一个响应者的标记视图
概述
将 ResponderChain 作为环境对象附加。
// In the SceneDelegate or ApplicationDelegate where you have access to the window:
let rootView = Example().environmentObject(ResponderChain(forWindow: window))
// SwiftUI only:
Example().withResponderChainForCurrentWindow()
标记可以成为第一个响应者的视图。
TextField(...).responderTag("MyTextField")
检查目前可用于成为第一个响应者的标记视图。
chain.availableResponders.contains("MyList")
使标记视图成为第一个响应者。
chain.firstResponder = "MyTextField"
if chain.firstResponder == nil {
print("Failed")
}
这是完全安全的,如果 "MyTextField" 不可用于成为第一个响应者或未被正确标记;则
chain.firstResponder
将变为nil
移除第一个响应者。
chain.firstResponder = nil
示例
将 ResponderChain 作为环境对象附加。
...
// In the SceneDelegate or ApplicationDelegate where you have access to the window:
let rootView = ResponderChainExample().environmentObject(ResponderChain(forWindow: window))
// SwiftUI only:
ResponderChainExample().withResponderChainForCurrentWindow()
...
ResponderChainExample.swift
struct ResponderChainExample: View {
@EnvironmentObject var chain: ResponderChain
var body: some View {
VStack(spacing: 20) {
// Show which view is first responder
Text("Selected field: \(chain.firstResponder?.description ?? "Nothing selected")")
// Some views that can become first responder
TextField("0", text: .constant(""), onCommit: { chain.firstResponder = "1" }).responderTag("0")
TextField("1", text: .constant(""), onCommit: { chain.firstResponder = "2" }).responderTag("1")
TextField("2", text: .constant(""), onCommit: { chain.firstResponder = "3" }).responderTag("2")
TextField("3", text: .constant(""), onCommit: { chain.firstResponder = nil }).responderTag("3")
// Buttons to change first responder
HStack {
Button("Select 0", action: { chain.firstResponder = "0" })
Button("Select 1", action: { chain.firstResponder = "1" })
Button("Select 2", action: { chain.firstResponder = "2" })
Button("Select 3", action: { chain.firstResponder = "3" })
}
}
.padding()
.onAppear {
// Set first responder on appear
DispatchQueue.main.async {
chain.firstResponder = "0"
}
}
}
}