Swift如何在AppDelegate fetch中发送eMail邮件?
Swift how to send eMail mail in AppDelegate fetch?
我现在完全无能为力,我正在尝试发送电子邮件以在 iOS Swift 4 应用程序中上传数据。我发现 Obj-C Mailcore 库可以在正常代码中工作,例如在按钮按下回调中。但是,如果我试图在我的 AppDelegate
获取函数中使用相同的代码,它不会 return 来自 completionHandler。
Mailcore 发送操作是异步的,所以我在它周围使用了信号量包装器,但从未调用完成处理程序。
编辑:
显然代码在带有信号量的按钮中不起作用。只有当我删除
let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
part.
那么有没有其他方法可以等待async completionBlock的完成呢?
是的,看我的回答:-)
我的代码:
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
}
完成要么来自同一个线程,要么在该线程中运行某些东西。
正常的做法是不要等待,而是在完成本身完成后做任何你需要做的事情。
如果必须使用信号量执行此操作,请将开始调用移至另一个线程。
所以我找到了解决方案:
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!")
}
[...]
我现在完全无能为力,我正在尝试发送电子邮件以在 iOS Swift 4 应用程序中上传数据。我发现 Obj-C Mailcore 库可以在正常代码中工作,例如在按钮按下回调中。但是,如果我试图在我的 AppDelegate
获取函数中使用相同的代码,它不会 return 来自 completionHandler。
Mailcore 发送操作是异步的,所以我在它周围使用了信号量包装器,但从未调用完成处理程序。
编辑:
显然代码在带有信号量的按钮中不起作用。只有当我删除
let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
part.
那么有没有其他方法可以等待async completionBlock的完成呢?
是的,看我的回答:-)
我的代码:
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
}
完成要么来自同一个线程,要么在该线程中运行某些东西。
正常的做法是不要等待,而是在完成本身完成后做任何你需要做的事情。
如果必须使用信号量执行此操作,请将开始调用移至另一个线程。
所以我找到了解决方案:
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!")
}
[...]