SwiftUI 以编程方式从可表示返回到视图
Posted
技术标签:
【中文标题】SwiftUI 以编程方式从可表示返回到视图【英文标题】:SwiftUI go back programmatically from representable to View 【发布时间】:2019-10-16 18:10:47 【问题描述】:我正在尝试在新的 swift ui 应用中设置二维码阅读器。
我可以用这一行加载 UIKit qr 阅读器视图
NavigationLink(destination: QRCodeScan())Text("Scan QR")
这是我的 ViewControllerRepresentable
struct QRCodeScan: UIViewControllerRepresentable
func makeCoordinator() -> Coordinator
Coordinator(self)
func makeUIViewController(context: Context) -> ScannerViewController
let vc = ScannerViewController()
vc.delegate = context.coordinator
return vc
func updateUIViewController(_ vc: ScannerViewController, context: Context)
class Coordinator: NSObject, QRCodeScannerDelegate
func codeDidFind(_ code: String)
print(code)
//Go back to the last page, take 'code' with you
var parent: QRCodeScan
init(_ parent: QRCodeScan)
self.parent = parent
在“返回最后一页...”这一行,我需要以编程方式返回将用户发送到二维码扫描仪的页面。页面加载了导航返回按钮,我非常需要复制此按钮行为以在需要时调用
任何帮助/指针表示赞赏
tia
【问题讨论】:
【参考方案1】:struct ContentView: View
@State var isActive = false
@State var code = ""
var body: some View
NavigationView
ZStack
NavigationLink(destination: DetailView(isActive: $isActive, code: $code), isActive: $isActive, label: EmptyView() )
Button(action:
self.isActive.toggle()
, label:
Text("navigate")
)
struct DetailView: View
@Binding var isActive: Bool
@Binding var code: String
var body: some View
Button(action:
self.code = "new code"
self.isActive.toggle()
)
Text("Back")
这可能对你有帮助,使用 NavigationLink 的 isActive
参数来回导航
【讨论】:
我相信上面的这种方法是首选的方法。现有的 SwiftUI API 通常通过绑定到 isVisible(例如警报)来工作,并通过在关闭时将其设置为 false 来解除它。另一方面,通过 presentation 进行操作现在似乎很普遍,但在我看来,它似乎偏离了 SwiftUI 的声明式风格。 是的,我阅读这个答案的方式并没有真正解决我的问题,它仍然在屏幕 2 上添加了一个按钮,用户必须按下才能返回,这不是什么我一直在寻找,我已经有一个按钮,我需要一种在事件处理程序中调用此操作的方法 @robbo5899 在“//回到最后一页,随身携带'code'”添加self.code = "new code" self.isActive.toggle()
,我只是用一个按钮来告诉你它是如何工作的
啊,好的,谢谢,使用 Representable 并从协调器中获取数据似乎有点尴尬,非常感谢【参考方案2】:
简短的回答是你现在不能这样做。既没有绑定也没有设置环境值可以触发它。我的猜测是会有某种类似于presentationMode
的环境值,你可以利用它,但它目前没有被宣传。
您可以尝试当前的presentationMode
,但我真正的建议是将您的 QR 扫描仪呈现为一张纸而不是推送。无论如何,从导航的角度来看,这实际上可能更有意义。为此,请在您的演示者中设置一个 @State
var 以在其出现时进行处理。
@State var presentQRScanner = false
var body: some View
Button("Scan")
self.presentQRScanner = true
.sheet(isPresented: $presentQRScanner) QRCodeScan()
然后,当您想以编程方式关闭时,您的 UIViewControllerRepresentable
:
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
func scannedCode()
presentationMode.wrappedValue.dismiss()
或者,您也可以通过在 QRCodeScan 上创建一个由代码调用的闭包来驱动演示者,然后让演示者解散。
var onCodeScanned: (Code) -> Void = _ in
func scannedCode()
onCodeScanned(code)
在演示者中:
var body: some View
Button("Scan")
self.presentQRScanner = true
.sheet(isPresented: $presentQRScanner)
QRCodeScan(onCodeScanned:
self.process($0)
self.presentQRScanner = false
)
编辑:不知道isActive
绑定,如果您仍想将视图推送到导航堆栈而不是显示它,那么它实际上应该对您有用。
【讨论】:
谢谢,采纳了您的建议并更改了视图的呈现方式,现在需要从模态视图中取回“代码”。【参考方案3】:您可以使用NavigationLink
的以下重载来做到这一点。它从 ios 13 及更高版本开始可用。
这是代码。
注意将$isShowingView
绑定传递给NavigationLink
对象和您想要通过按钮点击出去的ChildView
。
struct ContentView: View
@State var isShowingChildView = false
var body: some View
NavigationView
NavigationLink(isActive: $isShowingChildView)
ChildView(isShowingView: $isShowingChildView)
label:
Text("Open new view")
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
struct ChildView: View
@Binding
var isShowingView: Bool
var body: some View
VStack
Button("Back to parent view")
isShowingView = false
【讨论】:
以上是关于SwiftUI 以编程方式从可表示返回到视图的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式从 SwiftUI 列表中删除行并刷新列表视图?