如何正确使用信号灯同步 Alamofire 请求 Swift4 的主线程?
Posted
技术标签:
【中文标题】如何正确使用信号灯同步 Alamofire 请求 Swift4 的主线程?【英文标题】:How make correctely main thread on using sempanhores to sync Alamofire requests Swift4? 【发布时间】:2018-03-23 18:17:02 【问题描述】:我正在使用信号量在 AlamofireXMLRPC 上同步我的请求。所以我的功能是:
let semaphore = DispatchSemaphore(value: 0)
for i in idsCloud
if !idsLocal.contains(i)
count += 1
print("\n---->O ID: \(i) NÃO CONSTA NO BANCO LOCAL! <----\n")
// se o id nao consta no banco local, deve inseri-lo
OdooService.getProductByIdFromOdoo(id: i,successBlock: (p) in
CoreDataHandler.saveProduct(p: p)
semaphore.signal()
, failureBlock: (erro) in
print(erro)
)
semaphore.wait()
static func getProductByIdFromOdoo( id : Int, successBlock: @escaping (_ params : [String:Any]) -> Void, failureBlock: @escaping (_ params : String) -> Void)
if !checkOdooConn()
failureBlock("Falha na conexão com o Odoo")
return
let options = ["fields": fieldsProducts] as [String:Any]
let params = [OdooAuth.db,OdooAuth.uid,OdooAuth.password,"product.template","search_read",[[["id","=",id]]],options] as [Any]
print("start request...")
AlamofireXMLRPC.request(OdooAuth.host2, methodName: "execute_kw", parameters: params).responseXMLRPC(queue: DispatchQueue.global(qos: .background))
(response: DataResponse<XMLRPCNode>) -> Void in
switch response.result
case .success( _):
let str = String(data: response.data!, encoding: String.Encoding.utf8) as String!
let options = AEXMLOptions()
let pdict = strToDict(str: str!,options: options)
successBlock(pdict.first!)
break
case .failure(let error):
failureBlock(error.localizedDescription)
break
// fim switch
// fim request
在我的“for i in idsCloud”的第一次迭代中,我在控制台上收到一条奇怪的消息。
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 30310, TID: 1868520, Thread name: (none), Queue name: com.apple.root.background-qos, QoS: 9
Backtrace:
4 OdooVendas 0x00000001082d184e _T010OdooVendas15CoreDataHandlerC10getContext33_C78C41DC1F74DDA11E962327A9344CC5LLSo015NSManagedObjectG0CyFZ + 94
5 OdooVendas 0x00000001082d1951 _T010OdooVendas15CoreDataHandlerC11saveProductys10DictionaryVySSypG1p_tFZ + 33
6 OdooVendas 0x00000001082d588c _T010OdooVendas15CoreDataHandlerC12syncProductsyyFZys10DictionaryVySSypGcfU1_ + 60
7 OdooVendas 0x00000001082d5aaa _T010OdooVendas15CoreDataHandlerC12syncProductsyyFZys10DictionaryVySSypGcfU1_TA + 58
8 OdooVendas 0x00000001082f6cb1 _T010OdooVendas0A7ServiceC018getProductByIdFromA0ySi2id_ys10DictionaryVySSypGc12successBlockySSc07failureL0tFZy9Alamofire12DataResponseVy0N6XMLRPC10XMLRPCNodeVGcfU_ + 1697
9 OdooVendas 0x00000001082f6f62 _T010OdooVendas0A7ServiceC018getProductByIdFromA0ySi2id_ys10DictionaryVySSypGc12successBlockySSc07failureL0tFZy9Alamofire12DataResponseVy0N6XMLRPC10XMLRPCNodeVGcfU_TA + 114
10 AlamofireXMLRPC 0x00000001087e052d _T09Alamofire12DataResponseVy0A6XMLRPC10XMLRPCNodeVGIxx_AGIxi_TR + 173
11 AlamofireXMLRPC 0x00000001087e1092 _T09Alamofire12DataResponseVy0A6XMLRPC10XMLRPCNodeVGIxx_AGIxi_TRTA + 66
12 Alamofire 0x0000000108686819 _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_ + 905
13 Alamofire 0x000000010868f08e _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_TA + 110
14 Alamofire 0x000000010863f269 _T0Ix_IyB_TR + 41
15 libdispatch.dylib 0x000000010e1bc2f7 _dispatch_call_block_and_release + 12
16 libdispatch.dylib 0x000000010e1bd33d _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010e1c93a2 _dispatch_root_queue_drain + 1444
18 libdispatch.dylib 0x000000010e1c8da0 _dispatch_worker_thread3 + 132
19 libsystem_pthread.dylib 0x000000010e6881ca _pthread_wqthread + 1387
20 libsystem_pthread.dylib 0x000000010e687c4d start_wqthread + 13
2018-03-23 15:06:48.237961-0300 OdooVendas[30310:1868520] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 30310, TID: 1868520, Thread name: (none), Queue name: com.apple.root.background-qos, QoS: 9
Backtrace:
4 OdooVendas 0x00000001082d184e _T010OdooVendas15CoreDataHandlerC10getContext33_C78C41DC1F74DDA11E962327A9344CC5LLSo015NSManagedObjectG0CyFZ + 94
5 OdooVendas 0x00000001082d1951 _T010OdooVendas15CoreDataHandlerC11saveProductys10DictionaryVySSypG1p_tFZ + 33
6 OdooVendas 0x00000001082d588c _T010OdooVendas15CoreDataHandlerC12syncProductsyyFZys10DictionaryVySSypGcfU1_ + 60
7 OdooVendas 0x00000001082d5aaa _T010OdooVendas15CoreDataHandlerC12syncProductsyyFZys10DictionaryVySSypGcfU1_TA + 58
8 OdooVendas 0x00000001082f6cb1 _T010OdooVendas0A7ServiceC018getProductByIdFromA0ySi2id_ys10DictionaryVySSypGc12successBlockySSc07failureL0tFZy9Alamofire12DataResponseVy0N6XMLRPC10XMLRPCNodeVGcfU_ + 1697
9 OdooVendas 0x00000001082f6f62 _T010OdooVendas0A7ServiceC018getProductByIdFromA0ySi2id_ys10DictionaryVySSypGc12successBlockySSc07failureL0tFZy9Alamofire12DataResponseVy0N6XMLRPC10XMLRPCNodeVGcfU_TA + 114
10 AlamofireXMLRPC 0x00000001087e052d _T09Alamofire12DataResponseVy0A6XMLRPC10XMLRPCNodeVGIxx_AGIxi_TR + 173
11 AlamofireXMLRPC 0x00000001087e1092 _T09Alamofire12DataResponseVy0A6XMLRPC10XMLRPCNodeVGIxx_AGIxi_TRTA + 66
12 Alamofire 0x0000000108686819 _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_ + 905
13 Alamofire 0x000000010868f08e _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_TA + 110
14 Alamofire 0x000000010863f269 _T0Ix_IyB_TR + 41
15 libdispatch.dylib 0x000000010e1bc2f7 _dispatch_call_block_and_release + 12
16 libdispatch.dylib 0x000000010e1bd33d _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010e1c93a2 _dispatch_root_queue_drain + 1444
18 libdispatch.dylib 0x000000010e1c8da0 _dispatch_worker_thread3 + 132
19 libsystem_pthread.dylib 0x000000010e6881ca _pthread_wqthread + 1387
20 libsystem_pthread.dylib 0x000000010e687c4d start_wqthread + 13
奇怪的是一切正常,但我担心这条消息,我不知道我是否做错了什么。我不知道如何快速处理队列,但这段代码似乎解决了我的问题。 我使用 CoreData 来管理我的数据库。
【问题讨论】:
日志出现在哪一行?CoreDataHandler.saveProduct
有一些 UI 更新吗?标签、进度条等?
不,没有 UI。只有一个按钮来调用func。我用线条的图像进行了编辑。
【参考方案1】:
你不能在后台线程上调用 UIKit 方法,所以你不能访问UIApplication.delegate
(这是一个 UIKit 方法)。这是您永远不应在应用程序委托中存储全局变量的众多原因之一。创建一个单独的单例,或者在需要的地方传递 viewContext。但不要在应用委托中存储任何内容。
也就是说,您也不应该在这里使用信号量。信号量几乎从来都不是正确的工具。即使您需要同步,您几乎总是应该使用 DispatchGroup,而不是 Semaphore。
如果您需要序列化调用,则让每个完成处理程序调用下一个。
如果您可以并行执行调用,则使用 DispatchGroup 并在其上使用 .notify
方法来安排在所有调用完成后执行的操作。 (对于每个网络调用,添加一个group.enter()
,完成后,调用group.leave()
。)
【讨论】:
我编辑并开始使用 DispatchGroup,但仅在调用请求之前group.enter()
,在成功或失败块上使用group.leave()
,在请求下方使用group.wait()
。我创建了一个 Singleton 来获取上下文,但消息保留警告我只能在主线程上使用,并建议使用 DispatchQueue.main.async
但我不知道在哪里写这个。
"但消息保留警告我只能在主线程上使用。"只在主线程上使用什么?另外,你确定在非主线程上调用group.wait()
吗?如果你阻塞了主线程,你的程序就会崩溃。通常你想使用group.notify()
,而不是group.wait()
。
我很难理解,我去创建另一个项目并用其他问题的上下文提出另一个问题。以上是关于如何正确使用信号灯同步 Alamofire 请求 Swift4 的主线程?的主要内容,如果未能解决你的问题,请参考以下文章