如何在swift中等待ui委托

Posted

技术标签:

【中文标题】如何在swift中等待ui委托【英文标题】:how to wait for ui delegate in swift 【发布时间】:2015-12-22 08:09:38 【问题描述】:

我想在我的 Swift 2.0 应用程序的许多地方创建简单的对象助手来发送短信,并在下一步中创建另一个助手(电子邮件、pdf 打开器等)

我创建简单的类:

import Foundation
import MessageUI

class SmsHelper: MFMessageComposeViewControllerDelegate 

    func sendSMS(body: String)
        if (MFMessageComposeViewController.canSendText())
            let messageVC = MFMessageComposeViewController()
            messageVC.body = body
            //messageVC.recipients = ["Enter tel-nr"]
            messageVC.messageComposeDelegate = self;
            AppDelegate().sharedInstance().getTopController().presentViewController(messageVC, animated: false, completion: nil)

        
        else
            //do some alert etc.
        
    


    func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult)
        sendSMSRsp(result, errorMsg: nil)
        controller.dismissViewControllerAnimated(true, completion: nil)
        print("sms didFinishWithResult")
    

在代码中我想这样做的任何地方:

class someAnotherClass
  func someFunction()
    let smsHelper = SmsHelper()
    smsHelper.sendSms("some text")
  

所以短信 ios 编辑器已打开,但是当我想关闭它或发送时,它不会关闭,函数 messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) 我从未调用过并且应用程序因内存泄漏而崩溃,我知道原因:是因为 SmsHelper 对象在 ' someFunction' 在该函数结束作用域后删除,并且该对象为 nil,系统尝试在 nil 对象处调用 didFinishWithResult。我确认它:当我将 smsHelper 对象添加为“SomeClass”的成员时,它起作用了 - 调用了委托。

问题是:这样做的最佳做法是什么,添加成员对我来说不是一个选项,因为许多类都可以使用它,而且创建一个单例,appDelegate 成员我认为很愚蠢。如何在作用域函数结束时强制不删除对象?

【问题讨论】:

【参考方案1】:

尝试使用单例方式:

class SmsHelper: MFMessageComposeViewControllerDelegate 
   static let sharedInstance = SmsHelper()
   private init() 

及用法:

SmsHelper.sharedInstance().sendSms('some text')

编辑: 如果你从抽象类中添加不同的 init 方法。

 private override init(message: String)
        super.init()
    

然后将定义更改为static let sharedInstance = SmsHelper(message:"smsHelper") 并不复杂。

对于您的委托,只需将其分配到 init 方法之外,在 UIViewController viewDidLoad 中,

SmsHelper.sharedInstance().delegate = self

【讨论】:

它有效,但如果 SmsHelper 有一个带有自定义构造函数的父级,例如,当我有 3 个类:SmsHelper、PdfHelper、EmailHelper 和具有构造函数 Helper(body:String) 的抽象类 Helper 时,它可能会很复杂) ,我开始阅读有关 NSOperation 的内容,是否可以使用 NSOperation 呢? 对不起,我失去了你所说的,但为什么你需要抽象类?如果添加一些方法可以摆脱耦合。为什么不?所有的 Helper 都应该是 NSObject 的子类。仅从我的角度来看。如果这个答案有帮助,请采纳。 我看到他描述also creating a singleton, appDelegate member is I think quite stupid. 我解释说:我写了最简单的例子来创建关于***的明确问题 - 在我的真实代码中,需要抽象帮助类有两个原因:1)有一个带有调用者和构造函数的委托 Helper(delegate: SomeProtocol) 2) 有抽象方法来创建 JsonResponse f.ex 时发送或不发送短信我创建一个 JSON 并将其发送给委托由于某些原因。 查看我的编辑。不确定是否解决了您的“复杂”问题。【参考方案2】:

对我来说,这样做的方法是创建闭包的类型别名,然后存储此类型别名的可选变量。当您调用 sendSMS 时,您传入一个闭包并将其设置为您的变量。然后可以在委托中调用它,然后通过 sendSMS 的闭包传递它:

import Foundation
import MessageUI

class SmsHelper: MFMessageComposeViewControllerDelegate 

    let messageVC: MFMessageComposeViewController!
    typealias SMSCompletion = (result: MessageComposeResult, errorMsg: NSError?) -> ()
    var sendSMSRsp: SMSCompletion?

    func sendSMS(body: String, completion: SMSCompletion)
        sendSMSRsp = completion
        if (MFMessageComposeViewController.canSendText())
            messageVC = MFMessageComposeViewController()
            messageVC.body = body
            //messageVC.recipients = ["Enter tel-nr"]
            messageVC.messageComposeDelegate = self;
            AppDelegate().sharedInstance().getTopController().presentViewController(messageVC, animated: false, completion: nil)

         else 
            //do some alert etc.
        
    


    func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult)
        sendSMSRsp?(result: result, errorMsg: nil)
        controller.dismissViewControllerAnimated(true, completion: nil)
        print("sms didFinishWithResult")
    


class SomeOtherClass 

    func someFunction() 
        let smsHelper = SmsHelper()
        smsHelper.sendSMS("some text")  (result, errorMsg) -> () in

        
    


【讨论】:

这段代码对我来说是一个优雅的解决方案,但它不起作用,'messageComposeViewController didFinishWithResult' 永远不会被调用。 这听起来像是一个问题,因为代理设置不正确。我认为您需要在函数之外创建MFMessageComposeViewController,我会更改我的答案以适应。 当你回答时 - 我移到函数的 MFMessageComposeViewController 之外 - 仍然没有工作并崩溃,看起来 smshelper 对象在 sendSms 范围的末尾被删除。

以上是关于如何在swift中等待ui委托的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中的 UI 标签栏上应用渐变?

如何使用代码连接数据源和委托 - iOS Swift

如何在 Swift 中转换 Objective-C TOCropViewController 委托方法?

如何在目标 c 中引用 swift app 委托

如何使用 swift 在应用程序委托函数中使用 toast 方法

如何在 Swift Flutter 插件中接收应用程序委托调用?