代码:
func getRequestRespJson(httpRequest:Alamofire.Request, mergedAllPara:Dictionary<String, AnyObject>, respJsonHandler: (Alamofire.Result<JSON, NSError>, mergedAllPara:Dictionary<String, AnyObject>) -> Void) { gLog.info("httpRequest=\(httpRequest), mergedAllPara=\(mergedAllPara), respJsonHandler=\(respJsonHandler)") dispatchBackground_async({ httpRequest.responseJSON(completionHandler: { response in gLog.debug("request=\(response.request), response=\(response.response), statusCode=\(response.response?.statusCode), result=\(response.result)") |
但是对于此处的:
responseJSON的completionHandler
始终无法进入了
注:
之前没有使用dispatch_semaphore_t时,代码是可以正常工作的
dispatch_semaphore_t
此处使用了:
对应代码是:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. self.window?.rootViewController = SingletonRootNC() if SingletonLoginRegisterVC().tryRestoreUserAndPassword() { SingletonLoginRegisterVC().isLogin = true SingletonLoginRegisterVC().isRegister = false SingletonLoginRegisterVC().loginAction() dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER) } var loginDoneSemaphore:dispatch_semaphore_t! func resetGlobalValues(){ gLog.debug("") loginDoneSemaphore = dispatch_semaphore_create(0) } |
导致:Alamofire的responseJSON不返回了。。。
搜:
swift dispatch_semaphore_t alamofire
好像是:
Alamofire内部 也是用到了dispatch_semaphore_t?
线程锁 —- NSLock , @synchronized 和 dispatch_semaphore_t – IOS888888的专栏 – 博客频道 – CSDN.NET
Alamofire-Synchronous/Alamofire+Synchronous.swift at master · Dalodd/Alamofire-Synchronous
ios – Capturing data from Alamofire – Stack Overflow
然后,如果去掉了:
dispatch_semaphore_t
则:Alamofire就正常工作,可以正常返回值了。
alamofire not response dispatch_semaphore_t
alamofire not response semaphore
alamofire no response semaphore
alamofire semaphore
Check if all concurrent requests have been completed · Issue #224 · Alamofire/Alamofire
好像也遇到,可能算是类似的问题了
然后去改为:
确保所有的调用到Alamofire的地方,都是主线程,
结果也还是不行。
Allow synchronous calls · Issue #1147 · Alamofire/Alamofire
iOS Free App: How to return value from Alamofire
tvOS: Dynamic TopShelf Based on Remote JSON – HalGatewood.com
->好像responseJSON没有和dispatch_semaphore_create冲突啊?
alamofire DISPATCH_TIME_FOREVER
突然想到了:
貌似是:
Alamofire自己内部变态:
每次返回的http的response时,都是故意,主动的,返回到主线程中:
导致:
此处的:
dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER) |
是在主线程(的didFinishLaunchingWithOptions)中的
-》因此导致了让主线程永远等待loginDoneSemaphore
-》而Alamofire返回的内容,默认是返回到主线程中的(而不是你调用时候的线程)
-》从而导致死锁了:
Alamofire的responseJSON,想要获得主线程,才能返回JSON内容
而此时,主线程已经被我们的loginDoneSemaphore锁住了,永远在等待DISPATCH_TIME_FOREVER了。
-》解决办法,尝试去看看,Alamofire中,是否有配置选项,使得可以设置response的内容,不返回到主线程
通过看Alamofire的接口定义:
extension Request { /** Creates a response serializer that returns a JSON object constructed from the response data using `NSJSONSerialization` with the specified reading options. – parameter options: The JSON serialization reading options. `.AllowFragments` by default. – returns: A JSON object response serializer. */ public class func JSONResponseSerializer(options options: NSJSONReadingOptions = default) -> Alamofire.ResponseSerializer<AnyObject, NSError> /** Adds a handler to be called once the request has finished. – parameter options: The JSON serialization reading options. `.AllowFragments` by default. – parameter completionHandler: A closure to be executed once the request has finished. – returns: The request. */ public func responseJSON(queue queue: dispatch_queue_t? = default, options: NSJSONReadingOptions = default, completionHandler: Alamofire.Response<AnyObject, NSError> -> Void) -> Self } |
默认是返回到queue是default
-》此处暂时没源码,所以看不到是哪个线程
但是能猜测出来是主线程
-》通过设置对应的queue,也许问题能够解决。
果然是这个原因,去改为:
let BackgroundThread:dispatch_queue_t = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0) dispatchBackground_async({ httpRequest.responseJSON(queue: BackgroundThread, completionHandler: { response in gLog.debug("request=\(response.request), response=\(response.response), statusCode=\(response.response?.statusCode), result=\(response.result)") } |
即可正常执行。
-》这也间接的解决了,之前一直困扰我的问题:
为何Alamofire的所有的response,默认都返回到dispatch_get_main_queue的主线程中呢?
原来是:
Alamofire的所有的response函数,默认如果不传入对应的queue,则默认,应该就是main queue。
去下载源码,再去确认此推断:
然后才看懂:
default是nil,最终返回时,如果发现queue是(default的)nil,则使用主线程:
public func responseJSON( queue queue: dispatch_queue_t? = nil, options: NSJSONReadingOptions = .AllowFragments, completionHandler: Response<AnyObject, NSError> -> Void) -> Self { return response( queue: queue, responseSerializer: Request.JSONResponseSerializer(options: options), completionHandler: completionHandler ) } } -》 public func response<T: ResponseSerializerType>( queue queue: dispatch_queue_t? = nil, responseSerializer: T, completionHandler: Response<T.SerializedObject, T.ErrorObject> -> Void) -> Self { dispatch_async(queue ?? dispatch_get_main_queue()) { completionHandler(response) } |
至此,算是完全搞懂了。。。
另外:
然后也才注意到:
Check if all concurrent requests have been completed · Issue #224 · Alamofire/Alamofire
中的回复:
This is because responseSwiftyJSON was dispatched to main queue, do this and your problem is solved. return response(queue: dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0),responseSerializer: User.userResponseSerializer, completionHandler: completionHandler) |
其实就已经说明问题,并给出解决办法了。。。
所以,最后,相关部分的代码是:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. self.window?.rootViewController = SingletonRootNC() if SingletonLoginRegisterVC().tryRestoreUserAndPassword() { SingletonLoginRegisterVC().isLogin = true SingletonLoginRegisterVC().isRegister = false SingletonLoginRegisterVC().loginAction() dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER) gLog.debug("has dispatched loginDoneSemaphore") if gCurUserItem.hasLogined { gLog.info("login successfully") } } func getRequestRespJson(httpRequest:Alamofire.Request, mergedAllPara:Dictionary<String, AnyObject>, respJsonHandler: (Alamofire.Result<JSON, NSError>, mergedAllPara:Dictionary<String, AnyObject>) -> Void) { gLog.info("httpRequest=\(httpRequest), mergedAllPara=\(mergedAllPara), respJsonHandler=\(respJsonHandler)") dispatchBackground_async({ httpRequest.responseJSON(queue: BackgroundThread, completionHandler: { response in gLog.debug("request=\(response.request), response=\(response.response), statusCode=\(response.response?.statusCode), result=\(response.result)") } } |
即可避免由于:
dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER)
而导致的死锁的问题,使的Alamofire的responseJSON可以正常返回数据了。
转载请注明:在路上 » [已解决]swift中Alamofire的request的responseJSON不执行不返回了