SwiftUI:发送电子邮件

79

在 Swift 中的一个普通 UIViewController 中,我使用以下代码发送邮件。

let mailComposeViewController = configuredMailComposeViewController()

mailComposeViewController.navigationItem.leftBarButtonItem?.style = .plain
mailComposeViewController.navigationItem.rightBarButtonItem?.style = .plain
mailComposeViewController.navigationBar.tintColor = UIColor.white

if MFMailComposeViewController.canSendMail() {
    self.present(mailComposeViewController, animated: true, completion: nil)
} else {
    self.showSendMailErrorAlert()
}

我该如何在SwiftUI中实现相同的功能?

我需要使用UIViewControllerRepresentable吗?


也许在2019年进行此操作时还没有这个选项,但是Link视图对此是否可行呢? - spig
13个回答

2
我已经创建了一个 github 仓库,您只需要将其添加到您的项目中并按以下方式使用它:
struct ContentView: View {

@State var showMailSheet = false

var body: some View {
    NavigationView {
        Button(action: {
            self.showMailSheet.toggle()
        }) {
            Text("compose")
        }
    }
    .sheet(isPresented: self.$showMailSheet) {
        MailView(isShowing: self.$showMailSheet,
                 resultHandler: {
                    value in
                    switch value {
                    case .success(let result):
                        switch result {
                        case .cancelled:
                            print("cancelled")
                        case .failed:
                            print("failed")
                        case .saved:
                            print("saved")
                        default:
                            print("sent")
                        }
                    case .failure(let error):
                        print("error: \(error.localizedDescription)")
                    }
        },
                 subject: "test Subjet",
                 toRecipients: ["recipient@test.com"],
                 ccRecipients: ["cc@test.com"],
                 bccRecipients: ["bcc@test.com"],
                 messageBody: "works like a charm!",
                 isHtml: false)
        .safe()
        
    }

  }
}

safe()修饰符检查MFMailComposeViewController.canSendMail()是否为false,如果是,则自动关闭模态视图并尝试打开mailto链接。


0

很遗憾,@Matteo的解决方案对我来说并不完美。看起来有点问题 :(

备选方案

struct MailComposeSheet<T: View>: UIViewControllerRepresentable {
    let view: T

    @Binding var isPresented: Bool

    func makeUIViewController(context: Context) -> UIHostingController<T> {
        UIHostingController(rootView: view)
    }

    func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {
        uiViewController.rootView = view

        if isPresented, uiViewController.presentedViewController == nil {
            let picker = MFMailComposeViewController()

            picker.mailComposeDelegate = context.coordinator
            picker.presentationController?.delegate = context.coordinator

            uiViewController.present(picker, animated: true)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, MFMailComposeViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
        var parent: MailComposeSheet

        init(_ mailComposeSheet: MailComposeSheet) {
            self.parent = mailComposeSheet
        }

        func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
            controller.dismiss(animated: true) { [weak self] in
                self?.parent.isPresented = false
            }
        }

        func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
            parent.isPresented = false
        }
    }
}

extension View {
    func mailComposeSheet(isPresented: Binding<Bool>) -> some View {
        MailComposeSheet(
            view: self,
            isPresented: isPresented
        )
    }
}

使用方法:

struct ContentView: View {
    @State var showEmailComposer = false

    var body: some View {
        Button("Tap me") {
            showEmailComposer = true
        }
        .mailComposeSheet(isPresented: $showEmailComposer)
    }
}

我是新手,如果我做错了什么,请告诉我。


0

我看了上面所有的答案 - 仍然遇到了AXSERVER / CPT端口错误。

对我有用的是

     Button(action: {
                            let email = "mailto://"
                            let emailformatted = email + centreStaff.userName // from MongoDB Atlas
                            guard let url = URL(string: emailformatted) else { return }
                            UIApplication.shared.open(url)
                              }) {
                             Image (systemName: "envelope.circle.fill")
                                .symbolRenderingMode(.multicolor)
                         }

打开填写了员工姓名的Outlook...然后Boom!邮件发送成功。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接