从 SwiftUI 正确呈现 MFMailComposeViewController

问题描述 投票:0回答:1

作为将爱好项目从 UIKit 转换为 SwiftUI 的一部分,我尝试从 SwiftUI 视图呈现 MFMailComposeViewController。它可以工作,但视图控制器没有像使用 UIKit 时那样从屏幕底部正确呈现。

例如,按照Hobbes the tige这个答案,这是我得到的结果:

Mail compose view presented by SwiftUI

使用原始 UIKit 代码,相同的视图如下所示:

Mail compose view presented by UIKit

注意 SwiftUI 版本中屏幕底部看起来更糟糕。有没有办法解决?或者从 SwiftUI 呈现 MFMailComposeViewController 的更好方法?

这是基于上面链接的答案的测试应用程序的完整代码,展示了问题:

MailComposeTestApp.swift

import SwiftUI

@main
struct MailComposeTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

ContentView.swift

import SwiftUI
import MessageUI

struct ContentView: View {
    
    @State var result: Result<MFMailComposeResult, Error>? = nil
    @State var isShowingMailView = false
    
    var body: some View {
        Button(action: {
            self.isShowingMailView.toggle()
        }, label: {
            Label("Send mail", systemImage: "envelope")
        })
        .disabled(!MFMailComposeViewController.canSendMail())
        .sheet(isPresented: $isShowingMailView) {
            MailView(result: self.$result)
        }
    }
}

MailView.swift:

import SwiftUI
import UIKit
import MessageUI

struct MailView: UIViewControllerRepresentable {
    
    @Environment(\.presentationMode) var presentation
    @Binding var result: Result<MFMailComposeResult, Error>?
    
    class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
        
        @Binding var presentation: PresentationMode
        @Binding var result: Result<MFMailComposeResult, Error>?
        
        init(presentation: Binding<PresentationMode>,
             result: Binding<Result<MFMailComposeResult, Error>?>) {
            _presentation = presentation
            _result = result
        }
        
        func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
            defer {
                $presentation.wrappedValue.dismiss()
            }
            guard error == nil else {
                self.result = .failure(error!)
                return
            }
            self.result = .success(result)
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(presentation: presentation, result: $result)
    }
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<MailView>) -> MFMailComposeViewController {
        let vc = MFMailComposeViewController()
        vc.mailComposeDelegate = context.coordinator
        return vc
    }
    
    func updateUIViewController(_ uiViewController: MFMailComposeViewController, context: UIViewControllerRepresentableContext<MailView>) {
        
    }
}
swiftui mfmailcomposeviewcontroller
1个回答
0
投票

在 PHPickerViewController 中看到同样的问题证实了我的怀疑,即这是 SwiftUI 中的普遍行为,并且使解决方案更容易追踪。

事实证明,您必须手动允许工作表视图溢出到底部的安全区域:

        .sheet(isPresented: $isShowingMailView) {
            MailView(result: self.$result)
                .edgesIgnoringSafeArea(.bottom)
        }

这似乎适用于以这种方式呈现的任何类型的视图。

© www.soinside.com 2019 - 2024. All rights reserved.