Эх сурвалжийг харах

Merge pull request #2684 from AFNetworking/2685_crash_on_AFNetworkingOperationDidStartNotification

AFNetworkingOperationDidStartNotification crash
Kevin Harwood 10 жил өмнө
parent
commit
850e5e7850

+ 8 - 0
Tests/AFNetworking Tests.xcodeproj/project.pbxproj

@@ -16,6 +16,8 @@
 		2902D29517DF4E2A00C81C5A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2902D29317DF4E2A00C81C5A /* InfoPlist.strings */; };
 		2902D29517DF4E2A00C81C5A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2902D29317DF4E2A00C81C5A /* InfoPlist.strings */; };
 		2902D29C17DF4E3700C81C5A /* AFTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B9ED7617DF4D790021E4D5 /* AFTestCase.m */; };
 		2902D29C17DF4E3700C81C5A /* AFTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B9ED7617DF4D790021E4D5 /* AFTestCase.m */; };
 		2902D29D17DF4E3800C81C5A /* AFTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B9ED7617DF4D790021E4D5 /* AFTestCase.m */; };
 		2902D29D17DF4E3800C81C5A /* AFTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B9ED7617DF4D790021E4D5 /* AFTestCase.m */; };
+		2940C00A1B063C6700AFDAC7 /* AFUIActivityIndicatorViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2940C0091B063C6700AFDAC7 /* AFUIActivityIndicatorViewTests.m */; };
+		2940C00C1B064C3200AFDAC7 /* AFUIRefreshControlTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2940C00B1B064C3200AFDAC7 /* AFUIRefreshControlTests.m */; };
 		29CBFC3917DF4F120021AB75 /* AFHTTPRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3817DF4F120021AB75 /* AFHTTPRequestOperationTests.m */; };
 		29CBFC3917DF4F120021AB75 /* AFHTTPRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3817DF4F120021AB75 /* AFHTTPRequestOperationTests.m */; };
 		29CBFC3C17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */; };
 		29CBFC3C17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */; };
 		29CBFC3D17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */; };
 		29CBFC3D17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */; };
@@ -85,6 +87,8 @@
 		29133DD417DE77A5006E0493 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		29133DD417DE77A5006E0493 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		29133DD617DE77ED006E0493 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		29133DD617DE77ED006E0493 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		29133DD817DE7829006E0493 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
 		29133DD817DE7829006E0493 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+		2940C0091B063C6700AFDAC7 /* AFUIActivityIndicatorViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFUIActivityIndicatorViewTests.m; sourceTree = "<group>"; };
+		2940C00B1B064C3200AFDAC7 /* AFUIRefreshControlTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFUIRefreshControlTests.m; sourceTree = "<group>"; };
 		29B9ED5C17DF4D350021E4D5 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
 		29B9ED5C17DF4D350021E4D5 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
 		29B9ED6D17DF4D670021E4D5 /* AFHTTPClientTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClientTests.m; sourceTree = "<group>"; };
 		29B9ED6D17DF4D670021E4D5 /* AFHTTPClientTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClientTests.m; sourceTree = "<group>"; };
 		29B9ED6E17DF4D670021E4D5 /* AFHTTPRequestOperationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationTests.m; sourceTree = "<group>"; };
 		29B9ED6E17DF4D670021E4D5 /* AFHTTPRequestOperationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationTests.m; sourceTree = "<group>"; };
@@ -273,6 +277,8 @@
 				B6774DC818FBB49E0044DB17 /* AFNetworkActivityManagerTests.m */,
 				B6774DC818FBB49E0044DB17 /* AFNetworkActivityManagerTests.m */,
 				943B1F40192E406C00304316 /* AFURLSessionManagerTests.m */,
 				943B1F40192E406C00304316 /* AFURLSessionManagerTests.m */,
 				DE533FCD1ACCF34200C62CFB /* AFNetworkReachabilityManagerTests.m */,
 				DE533FCD1ACCF34200C62CFB /* AFNetworkReachabilityManagerTests.m */,
+				2940C0091B063C6700AFDAC7 /* AFUIActivityIndicatorViewTests.m */,
+				2940C00B1B064C3200AFDAC7 /* AFUIRefreshControlTests.m */,
 			);
 			);
 			path = Tests;
 			path = Tests;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -526,9 +532,11 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				2940C00A1B063C6700AFDAC7 /* AFUIActivityIndicatorViewTests.m in Sources */,
 				29CBFC3917DF4F120021AB75 /* AFHTTPRequestOperationTests.m in Sources */,
 				29CBFC3917DF4F120021AB75 /* AFHTTPRequestOperationTests.m in Sources */,
 				943B1F41192E406C00304316 /* AFURLSessionManagerTests.m in Sources */,
 				943B1F41192E406C00304316 /* AFURLSessionManagerTests.m in Sources */,
 				F837FFAF195744A0009078A0 /* AFHTTPResponseSerializationTests.m in Sources */,
 				F837FFAF195744A0009078A0 /* AFHTTPResponseSerializationTests.m in Sources */,
+				2940C00C1B064C3200AFDAC7 /* AFUIRefreshControlTests.m in Sources */,
 				29CBFC5A17DF61B30021AB75 /* AFSecurityPolicyTests.m in Sources */,
 				29CBFC5A17DF61B30021AB75 /* AFSecurityPolicyTests.m in Sources */,
 				29CBFC3F17DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */,
 				29CBFC3F17DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */,
 				B6774DC918FBB49E0044DB17 /* AFNetworkActivityManagerTests.m in Sources */,
 				B6774DC918FBB49E0044DB17 /* AFNetworkActivityManagerTests.m in Sources */,

+ 149 - 0
Tests/Tests/AFUIActivityIndicatorViewTests.m

@@ -0,0 +1,149 @@
+// AFNetworkReachabilityManagerTests.h
+// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFTestCase.h"
+#import <AFNetworking/UIActivityIndicatorView+AFNetworking.h>
+#import <AFNetworking/AFURLSessionManager.h>
+#import <AFNetworking/AFHTTPRequestOperationManager.h>
+
+@interface AFUIActivityIndicatorViewTests : AFTestCase
+@property (nonatomic, strong) NSURLRequest *request;
+@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
+@property (nonatomic, strong) AFURLSessionManager *sessionManager;
+@property (nonatomic, strong) AFHTTPRequestOperationManager *operationManager;
+@end
+
+@implementation AFUIActivityIndicatorViewTests
+
+- (void)setUp {
+    [super setUp];
+    self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
+    self.request = [NSURLRequest requestWithURL:[self.baseURL URLByAppendingPathComponent:@"delay/1"]];
+    self.sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:nil];
+    self.operationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:self.baseURL];
+}
+
+- (void)tearDown {
+    [super tearDown];
+    [self.sessionManager invalidateSessionCancelingTasks:YES];
+    self.sessionManager = nil;
+}
+
+- (void)testTaskDidResumeNotificationDoesNotCauseCrashForAIVWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidResumeNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      [expectation fulfill];
+                                  }];
+    
+    [self.activityIndicatorView setAnimatingWithStateOfTask:task];
+    self.activityIndicatorView = nil;
+    
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testTaskDidCompleteNotificationDoesNotCauseCrashForAIVWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidCompleteNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      //Without the dispatch after, this test would PASS errorenously because the test
+                                      //would finish before the notification was posted to all objects that were
+                                      //observing it.
+                                      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                          [expectation fulfill];
+                                      });
+                                  }];
+    
+    [self.activityIndicatorView setAnimatingWithStateOfTask:task];
+    self.activityIndicatorView = nil;
+    
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testTaskDidSuspendNotificationDoesNotCauseCrashForAIVWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidSuspendNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      //Without the dispatch after, this test would PASS errorenously because the test
+                                      //would finish before the notification was posted to all objects that were
+                                      //observing it.
+                                      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                          [expectation fulfill];
+                                      });
+                                  }];
+    
+    [self.activityIndicatorView setAnimatingWithStateOfTask:task];
+    self.activityIndicatorView = nil;
+    
+    [task resume];
+    [task suspend];
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testOperationDidStartNotificationDoesNotCauseCrashForAIVWithOperation {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingOperationDidStartNotification object:nil handler:nil];
+    AFHTTPRequestOperation *operation = [self.operationManager
+                                         HTTPRequestOperationWithRequest:self.request
+                                         success:^(AFHTTPRequestOperation *operation, id responseObject) {
+                                             [expectation fulfill];
+                                         } failure:nil];
+    [self.activityIndicatorView setAnimatingWithStateOfOperation:operation];
+    self.activityIndicatorView = nil;
+    [operation start];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [operation cancel];
+}
+
+- (void)testOperationDidFinishNotificationDoesNotCauseCrashForAIVWithOperation {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingOperationDidFinishNotification object:nil handler:nil];
+    AFHTTPRequestOperation *operation = [self.operationManager
+                                         HTTPRequestOperationWithRequest:self.request
+                                         success:^(AFHTTPRequestOperation *operation, id responseObject) {
+                                             //Without the dispatch after, this test would PASS errorenously because the test
+                                             //would finish before the notification was posted to all objects that were
+                                             //observing it.
+                                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                                  [expectation fulfill];
+                                             });
+
+                                         } failure:nil];
+    [self.activityIndicatorView setAnimatingWithStateOfOperation:operation];
+    self.activityIndicatorView = nil;
+    [operation start];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [operation cancel];
+}
+
+@end

+ 149 - 0
Tests/Tests/AFUIRefreshControlTests.m

@@ -0,0 +1,149 @@
+// AFNetworkReachabilityManagerTests.h
+// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFTestCase.h"
+#import <AFNetworking/UIRefreshControl+AFNetworking.h>
+#import <AFNetworking/AFURLSessionManager.h>
+#import <AFNetworking/AFHTTPRequestOperationManager.h>
+
+@interface AFUIRefreshControlTests : AFTestCase
+@property (nonatomic, strong) NSURLRequest *request;
+@property (nonatomic, strong) UIRefreshControl *refreshControl;
+@property (nonatomic, strong) AFURLSessionManager *sessionManager;
+@property (nonatomic, strong) AFHTTPRequestOperationManager *operationManager;
+@end
+
+@implementation AFUIRefreshControlTests
+
+- (void)setUp {
+    [super setUp];
+    self.refreshControl = [[UIRefreshControl alloc] init];
+    self.request = [NSURLRequest requestWithURL:[self.baseURL URLByAppendingPathComponent:@"delay/1"]];
+    self.sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:nil];
+    self.operationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:self.baseURL];
+}
+
+- (void)tearDown {
+    [super tearDown];
+    [self.sessionManager invalidateSessionCancelingTasks:YES];
+    self.sessionManager = nil;
+}
+
+- (void)testTaskDidResumeNotificationDoesNotCauseCrashForUIRCWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidResumeNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      [expectation fulfill];
+                                  }];
+    
+    [self.refreshControl setRefreshingWithStateOfTask:task];
+    self.refreshControl = nil;
+    
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testTaskDidCompleteNotificationDoesNotCauseCrashForUIRCWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidCompleteNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      //Without the dispatch after, this test would PASS errorenously because the test
+                                      //would finish before the notification was posted to all objects that were
+                                      //observing it.
+                                      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                          [expectation fulfill];
+                                      });
+                                  }];
+    
+    [self.refreshControl setRefreshingWithStateOfTask:task];
+    self.refreshControl = nil;
+    
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testTaskDidSuspendNotificationDoesNotCauseCrashForUIRCWithTask {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingTaskDidSuspendNotification object:nil handler:nil];
+    NSURLSessionDataTask *task = [self.sessionManager
+                                  dataTaskWithRequest:self.request
+                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
+                                      //Without the dispatch after, this test would PASS errorenously because the test
+                                      //would finish before the notification was posted to all objects that were
+                                      //observing it.
+                                      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                          [expectation fulfill];
+                                      });
+                                  }];
+    
+    [self.refreshControl setRefreshingWithStateOfTask:task];
+    self.refreshControl = nil;
+    
+    [task resume];
+    [task suspend];
+    [task resume];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [task cancel];
+}
+
+- (void)testOperationDidStartNotificationDoesNotCauseCrashForUIRCWithOperation {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingOperationDidStartNotification object:nil handler:nil];
+    AFHTTPRequestOperation *operation = [self.operationManager
+                                         HTTPRequestOperationWithRequest:self.request
+                                         success:^(AFHTTPRequestOperation *operation, id responseObject) {
+                                             [expectation fulfill];
+                                         } failure:nil];
+    [self.refreshControl setRefreshingWithStateOfOperation:operation];
+    self.refreshControl = nil;
+    [operation start];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [operation cancel];
+}
+
+- (void)testOperationDidFinishNotificationDoesNotCauseCrashForUIRCWithOperation {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"No Crash"];
+    [self expectationForNotification:AFNetworkingOperationDidFinishNotification object:nil handler:nil];
+    AFHTTPRequestOperation *operation = [self.operationManager
+                                         HTTPRequestOperationWithRequest:self.request
+                                         success:^(AFHTTPRequestOperation *operation, id responseObject) {
+                                             //Without the dispatch after, this test would PASS errorenously because the test
+                                             //would finish before the notification was posted to all objects that were
+                                             //observing it.
+                                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                                                 [expectation fulfill];
+                                             });
+                                             
+                                         } failure:nil];
+    [self.refreshControl setRefreshingWithStateOfOperation:operation];
+    self.refreshControl = nil;
+    [operation start];
+    [self waitForExpectationsWithTimeout:5.0 handler:nil];
+    [operation cancel];
+}
+
+@end

+ 15 - 0
UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m

@@ -91,6 +91,21 @@
     });
     });
 }
 }
 
 
+#pragma mark -
+
+-(void)dealloc
+{
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
+#endif
+    
+    [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil];
+}
+
 @end
 @end
 
 
 #endif
 #endif

+ 15 - 0
UIKit+AFNetworking/UIRefreshControl+AFNetworking.m

@@ -88,6 +88,21 @@
     });
     });
 }
 }
 
 
+#pragma mark -
+
+-(void)dealloc
+{
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
+#endif
+    
+    [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil];
+    [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil];
+}
+
 @end
 @end
 
 
 #endif
 #endif