【问题标题】:Delegate cannot be constructed because it has no accessible initializers?无法构造委托,因为它没有可访问的初始化程序?
【发布时间】:2021-02-14 13:50:06
【问题描述】:

所以我有一个类具有发送 SMS 消息的功能。我尝试使该类符合委托协议...它最终导致该类需要一个类型别名,我认为该类型别名是 MFMessageViewController 类型,但这不起作用

class functions: NSObject, ObservableObject, MFMessageComposeViewControllerDelegate {
    func sendInviteMessage(number: String) {
        if MFMessageComposeViewController.canSendText() {
            let message = MFMessageComposeViewController()
            message.messageComposeDelegate = self
            message.recipients = [number]
            message.body = "Hi, I'd like to invite you to join my app google.com"
        
            message.present(message, animated: true)
        }
    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}

【问题讨论】:

  • MFMessageComposeViewControllerDelegate 是一个协议,因此您无法创建它的实例。

标签: swift delegates uikit mfmessagecomposeview


【解决方案1】:

我认为您应该看看 here 以快速深入了解委托和协议。你不能实例化一个协议——你需要一个符合该协议的类来完成你想要的。

我认为你的班级应该是这样的:

class functions: NSObject, ObservableObject, MFMessageComposeViewControllerDelegate {
    
    func sendInviteMessage() {
    
        if MFMessageComposeViewController.canSendText() {
            let message = MFMessageComposeViewController()
            message.messageComposeDelegate = self
            message.recipients = ["##########"]
            message.body = "Hi, I'd like to invite you to join my app google.com"

            // here we have a problem - You will need a ViewController or something that presents the MessageComposeViewController "message" --> It cannot present itself
            //message.present(message, animated: true)
        }
    }
    
    func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
        controller.dismiss(animated: true)
    }
}

这在很大程度上取决于您的需求,您的演示解决方案是什么样的。 (IMO 这个代码应该放在UIViewController

如果有帮助请告诉我!

【讨论】:

  • 我在您发送此答案之前就想通了,但是当我尝试调用 sendInviteMessage() 函数时,我收到一个奇怪的错误,提示“应用程序试图在自身上呈现模态视图控制器”。 ..有什么想法吗?
  • 我编辑了我的答案 - 现在应该更清楚了
  • 我明白——我正在使用 SwiftUI 工作,如果这不是 MVC 有帮助的话......我应该只制作两个 MFMessageComposeViewControllers,然后让一个呈现另一个吗?因为问题在于信息正在呈现本身,对吧?
  • 如果您使用 SwiftUI,可见视图负责呈现和关闭控制器。您必须将 MessageController 包装在 UIViewControllerRepresentable-Protocol 中。看看这里如何做到这一点:medium.com/@Johannes_Nevels/… 那里有很多教程。
  • 那么我是否只是让函数协议符合该协议?如果我这样做,最终会导致该类需要一个类型别名,我认为该类型别名是 MFMessageViewController 类型,但那不起作用......
【解决方案2】:

如果您的项目使用 SwiftUI,那么您可以使用 UIViewControllerRepresentable

struct MessageComposeViewController: UIViewControllerRepresentable {
    
    var toRecipients: [String]
    var messageBody: String
    
    var didFinish: ()->()
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<MessageComposeViewController>) -> MFMessageComposeViewController {
        
        let message = MFMessageComposeViewController()
        message.messageComposeDelegate = context.coordinator
        message.recipients = self.toRecipients
        message.body = self.messageBody
        
        return message
    }
    
    final class Coordinator: NSObject, MFMessageComposeViewControllerDelegate {
        
        var parent: MessageComposeViewController
        
        init(_ controller: MessageComposeViewController) {
            self.parent = controller
        }
        
        func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
            parent.didFinish()
            controller.dismiss(animated: true)
        }
    }
    
    func updateUIViewController(_ uiViewController: MFMessageComposeViewController, context: UIViewControllerRepresentableContext<MessageComposeViewController>) {
        
    }
}

用法:

struct MessageView: View {
    
    @State private var showingMessage = false
    
    var body: some View {
        VStack {
            Button("Open Message") {
                self.showingMessage.toggle()
            }
        }
        .sheet(isPresented: $showingMessage) {
            MessageComposeViewController(toRecipients: ["1234567890"], messageBody: "Hi, I'd like to invite you to join my app google.com") {
                // Did finish action
            }
        }
    }
}


可能的另一种解决方案。您可以创建一个单例类并在根控制器上显示 MFMessageComposeViewController。 像这样

class Functions: NSObject, MFMessageComposeViewControllerDelegate {

    static let shared = Functions()
    
    func sendInviteMessage(number: String) {
        if MFMessageComposeViewController.canSendText() {
            
            let message = MFMessageComposeViewController()
            message.messageComposeDelegate = self
            message.recipients = [number]
            message.body = "Hi, I'd like to invite you to join my app google.com"
            
            UIApplication.shared.windows.first?.rootViewController?.present(message, animated: true)
        }
    }
    
    func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
        controller.dismiss(animated: true)
    }
}

用法:

struct MessageView: View {
    var body: some View {
        Button("Open Message") {
            Functions.shared.sendInviteMessage(number: "12345678")
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    相关资源
    最近更新 更多