Swift如何在AppDelegate提取中发送电子邮件?

时间:2018-11-23 12:13:54

标签: ios swift swift4 appdelegate mailcore2

我现在完全束手无策,我正在尝试发送电子邮件以在iOS Swift 4 App中上传数据。我发现了可以正常代码运行的Obj-C Mailcore库,例如在按钮按下回调中。但是,如果我尝试在我的AppDelegate提取函数中使用相同的代码,则不会从completionHandler返回。

Mailcore发送操作是异步的,因此我在其周围使用了信号量包装器,但是从未调用完成处理程序。

编辑:

显然,该代码在带有信号灯的按钮中不起作用。只有删除了

let _ = semaphore.wait(timeout: DispatchTime.distantFuture)

part。

那么还有另一种方式来等待异步完成区块完成吗?


是的,看看我的回答:-)

我的代码:

let smtpSession = MCOSMTPSession()
[...]
let sendOperation = smtpSession.sendOperation(with: rfc822Data!)
[...]
let semaphore = DispatchSemaphore(value: 0)
if (sendOperation != nil) {
    print("Starting sendOperation...")
    sendOperation?.start { (error) -> Void in
        if (error != nil) {
            sendingError = true
            print("Error sending email: \(error)")
        } else {
            print("Successfully sent email!")
        }
        sendingDone = true
        semaphore.signal()
    }
    let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
} else {
    print("Cant init sendOperation")
    sendingError = true
}

2 个答案:

答案 0 :(得分:0)

完成是在同一线程中进行,还是在该线程中运行某些操作。

通常要做的是不等待,而是在完成本身完成后做任何您需要做的事情。

如果必须使用信号量,请将开始调用移到另一个线程。

答案 1 :(得分:0)

所以我找到了解决方案:

SyncManager.swift

import Foundation

/// A generic Cocoa-Style completion handler
typealias CompletionHandler = (Error?) -> Void

/// Provides syncronous access to results returned by
/// asynchronous processes with completion handlers
class SyncMaker {
    var result: Error? = nil

    /// Generates a synchronous-compliant completion handler
    func completion() -> CompletionHandler{
        return {
            (error: Error?) in

            // Store result, return control
            self.result = error
            CFRunLoopStop(CFRunLoopGetCurrent())
        }
    }

    // Perform task (that must use custom completion handler) and wait
    func run(_ task: @escaping () -> Void) -> Error? {
        task()
        CFRunLoopRun()
        return result
    }
}

AppDelegate.swift (部分)

[...]
let syncMaker = SyncMaker()
let result = syncMaker.run {
    sendOperation?.start(
        syncMaker.completion())
}
if (result != nil) {
    print("Error sending email: \(result)")
} else {
    sendingError = false
    print("Successfully sent email!")
}
[...]