From 27964aa9dc8b3f5aece2c1528e8135355ee21156 Mon Sep 17 00:00:00 2001 From: Phil Tang Date: Sun, 30 Nov 2014 00:14:09 -0500 Subject: [PATCH] Fix AFNetworkActivityIndicatorManager for iOS 7...dubiously This swizzle used to assume that all `NSURLSessionTask` instances had a superclass named `NSURLSessionTask`. That is not true on iOS 7 devices. Therefore, we need to somehow swizzle the the superclass, which is `__NSCFLocalSessionTask` on iOS 7. This is a way to do it without explicitly mentioning or calling any private API. However, it does end up adding and swizzling methods on `__NSCFLocalSessionTask`. Is this legal? I cannot say for sure. --- AFNetworking/AFURLSessionManager.m | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/AFNetworking/AFURLSessionManager.m b/AFNetworking/AFURLSessionManager.m index a6ebbeed7c..3d29635574 100644 --- a/AFNetworking/AFURLSessionManager.m +++ b/AFNetworking/AFURLSessionManager.m @@ -272,19 +272,27 @@ static inline void af_swizzleSelector(Class class, SEL originalSelector, SEL swi } } +static inline void af_addMethod(Class class, SEL selector, Method method) { + class_addMethod(class, @selector(af_resume), method_getImplementation(method), method_getTypeEncoding(method)); +} + static NSString * const AFNSURLSessionTaskDidResumeNotification = @"com.alamofire.networking.nsurlsessiontask.resume"; static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend"; -@interface NSURLSessionTask (_AFStateObserving) +@interface NSURLSessionDataTask (_AFStateObserving) @end -@implementation NSURLSessionTask (_AFStateObserving) +@implementation NSURLSessionDataTask (_AFStateObserving) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - af_swizzleSelector([self class], @selector(resume), @selector(af_resume)); - af_swizzleSelector([self class], @selector(suspend), @selector(af_suspend)); + NSURLSessionDataTask *dataTask = [[NSURLSession sessionWithConfiguration:nil] dataTaskWithURL:nil]; + Class taskClass = [dataTask superclass]; + af_addMethod(taskClass, @selector(af_resume), class_getInstanceMethod(self, @selector(af_resume))); + af_addMethod(taskClass, @selector(af_suspend), class_getInstanceMethod(self, @selector(af_suspend))); + af_swizzleSelector(taskClass, @selector(resume), @selector(af_resume)); + af_swizzleSelector(taskClass, @selector(suspend), @selector(af_suspend)); }); } @@ -402,7 +410,7 @@ - (NSString *)taskDescriptionForSessionTasks { - (void)taskDidResume:(NSNotification *)notification { NSURLSessionTask *task = notification.object; - if ([task isKindOfClass:[NSURLSessionTask class]]) { + if ([task respondsToSelector:@selector(taskDescription)]) { if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task]; @@ -413,7 +421,7 @@ - (void)taskDidResume:(NSNotification *)notification { - (void)taskDidSuspend:(NSNotification *)notification { NSURLSessionTask *task = notification.object; - if ([task isKindOfClass:[NSURLSessionTask class]]) { + if ([task respondsToSelector:@selector(taskDescription)]) { if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task];