jja*_*tie 36 uikit ios swiftui
我已经将我的登录视图控制器重写为 SwiftUI View。该SignInView被包裹在一UIHostingController子类中(final class SignInViewController: UIHostingController<SignInView> {}),并且被呈现模态,全屏,当符号是必要英寸
一切正常,除了我不知道如何SignInViewController从SignInView. 我试过添加:
@Environment(\.isPresented) var isPresented
Run Code Online (Sandbox Code Playgroud)
在SignInView并将其分配给false当登录成功,但这并没有出现与UIKit的互操作到。我怎样才能关闭视图?
Sea*_*ins 37
我发现了另一种似乎效果很好的方法,并且感觉比其他一些方法更简洁。脚步:
dismissAction向 SwiftUI 视图添加一个属性:struct SettingsUIView: View {
var dismissAction: (() -> Void)
...
}
Run Code Online (Sandbox Code Playgroud)
dismissAction当你想关闭视图时调用:Button(action: dismissAction ) {
Text("Done")
}
Run Code Online (Sandbox Code Playgroud)
let settingsView = SettingsUIView(dismissAction: {self.dismiss( animated: true, completion: nil )})
let settingsViewController = UIHostingController(rootView: settingsView )
present( settingsViewController, animated: true )
Run Code Online (Sandbox Code Playgroud)
jja*_*tie 36
更新:来自 iOS 15 beta 1 的发行说明:
isPresented、PresentationMode 和新的 DismissAction 操作会关闭从 UIKit 呈现的托管控制器。(52556186)
我最终找到了一个比提供的更简单的解决方案:
final class SettingsViewController: UIHostingController<SettingsView> {
required init?(coder: NSCoder) {
super.init(coder: coder, rootView: SettingsView())
rootView.dismiss = dismiss
}
func dismiss() {
dismiss(animated: true, completion: nil)
}
}
struct SettingsView: View {
var dismiss: (() -> Void)?
var body: some View {
NavigationView {
Form {
Section {
Button("Dimiss", action: dismiss!)
}
}
.navigationBarTitle("Settings")
}
}
}
Run Code Online (Sandbox Code Playgroud)
bon*_*onk 11
此处提供的所有答案对我都不起作用,可能是因为参考资料较弱。这是我想出的解决方案:
创建视图和 UIHostingController:
let delegate = SheetDismisserProtocol()
let signInView = SignInView(delegate: delegate)
let host = UIHostingController(rootView: AnyView(signInView))
delegate.host = host
// Present the host modally
Run Code Online (Sandbox Code Playgroud)
SheetDismisserProtocol:
class SheetDismisserProtocol: ObservableObject {
weak var host: UIHostingController<AnyView>? = nil
func dismiss() {
host?.dismiss(animated: true)
}
}
Run Code Online (Sandbox Code Playgroud)
必须驳回的观点:
struct SignInView: View {
@ObservedObject var delegate: SheetDismisserProtocol
var body: some View {
Button(action: {
self.delegate.dismiss()
})
}
}
Run Code Online (Sandbox Code Playgroud)
你可以只使用通知。
斯威夫特 5.1
在 SwiftUI 按钮处理程序中:
NotificationCenter.default.post(name: NSNotification.Name("dismissSwiftUI"), object: nil)
Run Code Online (Sandbox Code Playgroud)
在 UIKit 视图控制器中:
NotificationCenter.default.addObserver(forName: NSNotification.Name("dismissSwiftUI"), object: nil, queue: nil) { (_) in
hostingVC.dismiss(animated: true, completion: nil)
}
Run Code Online (Sandbox Code Playgroud)
let rootView = SignInView();
let ctrl = UIHostingController(rootView: rootView);
ctrl.rootView.dismiss = {[weak ctrl] in
ctrl?.dismiss(animated: true)
}
present(ctrl, animated:true, completion:nil);
Run Code Online (Sandbox Code Playgroud)
注意:ctrl.rootView.dismiss不是rootView.dismiss
另一种方法(在我看来相对更容易)是UIViewController在您的中有一个可选的属性类型,SwiftUI view然后将其设置为将呈现UIHostingController的SwiftUI视图控制器,它将包装您的视图。
一个简单的设置视图:
struct SettingsView: View {
var presentingVC: UIViewController?
var body: some View {
Button(action: {
self.presentingVC?.presentedViewController?.dismiss(animated: true)
}) {
Text("Dismiss")
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当您使用UIHostingController以下方法从视图控制器呈现此视图时:
class ViewController: UIViewController {
private func presentSettingsView() {
var view = SettingsView()
view.presentingVC = self
let hostingVC = UIHostingController(rootView: view)
present(hostingVC, animated: true, completion: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,你可以在的作用看Button的SettingsView,我们要谈ViewController驳回它呈现视图控制器,这对我们来说将是UIHostingController一个包装SettingsView。
使用主机控制器演示器扩展环境值怎么样?它允许presentationMode在层次结构中的任何视图中使用,并且易于重用和可扩展。定义您的新环境值:
struct UIHostingControllerPresenter {
init(_ hostingControllerPresenter: UIViewController) {
self.hostingControllerPresenter = hostingControllerPresenter
}
private unowned var hostingControllerPresenter: UIViewController
func dismiss() {
if let presentedViewController = hostingControllerPresenter.presentedViewController, !presentedViewController.isBeingDismissed { // otherwise an ancestor dismisses hostingControllerPresenter - which we don't want.
hostingControllerPresenter.dismiss(animated: true, completion: nil)
}
}
}
private enum UIHostingControllerPresenterEnvironmentKey: EnvironmentKey {
static let defaultValue: UIHostingControllerPresenter? = nil
}
extension EnvironmentValues {
/// An environment value that attempts to extend `presentationMode` for case where
/// view is presented via `UIHostingController` so dismissal through
/// `presentationMode` doesn't work.
var uiHostingControllerPresenter: UIHostingControllerPresenter? {
get { self[UIHostingControllerPresenterEnvironmentKey.self] }
set { self[UIHostingControllerPresenterEnvironmentKey.self] = newValue }
}
}
Run Code Online (Sandbox Code Playgroud)
然后在需要时传递值,例如:
let view = AnySwiftUIView().environment(\.uiHostingControllerPresenter, UIHostingControllerPresenter(self))
let viewController = UIHostingController(rootView: view)
present(viewController, animated: true, completion: nil)
...
Run Code Online (Sandbox Code Playgroud)
并享受使用
@Environment(\.uiHostingControllerPresenter) private var uiHostingControllerPresenter
...
uiHostingControllerPresenter?.dismiss()
Run Code Online (Sandbox Code Playgroud)
你去的地方
@Environment(\.presentationMode) private var presentationMode
...
presentationMode.wrappedValue.dismiss() // .isPresented = false
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12238 次 |
| 最近记录: |