Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Update RKObjectManager to observe changes to the reachability observe…

…r of

the underlying RKClient object. refs #717
  • Loading branch information...
commit e932c31cde0f7f1d57e9ce680e6b338bd1d01831 1 parent 5387f0b
@dusek dusek authored blakewatters committed
View
4 Code/Network/RKClient.h
@@ -209,7 +209,7 @@
/**
A dictionary of headers to be sent with each request
*/
-@property (nonatomic, readonly) NSMutableDictionary *HTTPHeaders;
+@property (nonatomic, retain, readonly) NSMutableDictionary *HTTPHeaders;
/**
An optional timeout interval within which the request should be cancelled.
@@ -271,7 +271,7 @@
A set of additional certificates to be used in evaluating server SSL
certificates.
*/
-@property (nonatomic, readonly) NSSet *additionalRootCertificates;
+@property (nonatomic, retain, readonly) NSSet *additionalRootCertificates;
/**
Adds an additional certificate that will be used to evaluate server SSL certs.
View
26 Code/Network/RKClient.m
@@ -65,6 +65,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
+@interface RKClient ()
+@property (nonatomic, retain, readwrite) NSMutableDictionary *HTTPHeaders;
+@property (nonatomic, retain, readwrite) NSSet *additionalRootCertificates;
+@end
+
@implementation RKClient
@synthesize baseURL = _baseURL;
@@ -121,25 +126,24 @@ + (RKClient *)clientWithBaseURL:(NSString *)baseURL username:(NSString *)usernam
- (id)init {
self = [super init];
if (self) {
- _HTTPHeaders = [[NSMutableDictionary alloc] init];
- _additionalRootCertificates = [[NSMutableSet alloc] init];
- _defaultHTTPEncoding = NSUTF8StringEncoding;
+ self.HTTPHeaders = [[NSMutableDictionary alloc] init];
+ self.additionalRootCertificates = [[NSMutableSet alloc] init];
+ self.defaultHTTPEncoding = NSUTF8StringEncoding;
self.cacheTimeoutInterval = 0;
self.runLoopMode = NSRunLoopCommonModes;
- self.serviceUnavailableAlertEnabled = NO;
- self.serviceUnavailableAlertTitle = NSLocalizedString(@"Service Unavailable", nil);
- self.serviceUnavailableAlertMessage = NSLocalizedString(@"The remote resource is unavailable. Please try again later.", nil);
+ self.requestQueue = [RKRequestQueue requestQueue];
+ self.serviceUnavailableAlertEnabled = NO;
+ self.serviceUnavailableAlertTitle = NSLocalizedString(@"Service Unavailable", nil);
+ self.serviceUnavailableAlertMessage = NSLocalizedString(@"The remote resource is unavailable. Please try again later.", nil);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(serviceDidBecomeUnavailableNotification:)
name:RKServiceDidBecomeUnavailableNotification
object:nil];
- // Configure reachability and queue
- [self addObserver:self forKeyPath:@"reachabilityObserver" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- self.requestQueue = [RKRequestQueue requestQueue];
-
+ // Configure observers
+ [self addObserver:self forKeyPath:@"reachabilityObserver" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
[self addObserver:self forKeyPath:@"baseURL" options:NSKeyValueObservingOptionNew context:nil];
- [self addObserver:self forKeyPath:@"requestQueue" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
+ [self addObserver:self forKeyPath:@"requestQueue" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial context:nil];
}
return self;
View
73 Code/ObjectMapping/RKObjectManager.m
@@ -36,6 +36,10 @@
///////////////////////////////////
+@interface RKObjectManager ()
+@property (nonatomic, assign, readwrite) RKObjectManagerNetworkStatus networkStatus;
+@end
+
@implementation RKObjectManager
@synthesize client = _client;
@@ -66,15 +70,13 @@ + (void)setDefaultMappingQueue:(dispatch_queue_t)newDefaultMappingQueue {
}
}
-- (id)initWithBaseURL:(RKURL *)baseURL {
+- (id)init {
self = [super init];
- if (self) {
+ if (self) {
_mappingProvider = [RKObjectMappingProvider new];
_router = [RKObjectRouter new];
- _client = [[RKClient alloc] initWithBaseURL:baseURL];
_networkStatus = RKObjectManagerNetworkStatusUnknown;
-
- self.acceptMIMEType = RKMIMETypeJSON;
+
self.serializationMIMEType = RKMIMETypeFormURLEncoded;
self.mappingQueue = [RKObjectManager defaultMappingQueue];
@@ -83,17 +85,28 @@ - (id)initWithBaseURL:(RKURL *)baseURL {
errorMapping.rootKeyPath = @"errors";
[errorMapping mapKeyPath:@"" toAttribute:@"errorMessage"];
_mappingProvider.errorMapping = errorMapping;
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(reachabilityChanged:)
- name:RKReachabilityDidChangeNotification
- object:_client.reachabilityObserver];
+
+ [self addObserver:self
+ forKeyPath:@"client.reachabilityObserver"
+ options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
+ context:nil];
// Set shared manager if nil
if (nil == sharedManager) {
[RKObjectManager setSharedManager:self];
}
- }
+ }
+
+ return self;
+}
+
+- (id)initWithBaseURL:(RKURL *)baseURL {
+ self = [self init];
+ if (self) {
+ self.client = [[RKClient alloc] initWithBaseURL:baseURL];
+ [self.client release];
+ self.acceptMIMEType = RKMIMETypeJSON;
+ }
return self;
}
@@ -118,12 +131,12 @@ + (RKObjectManager *)managerWithBaseURL:(NSURL *)baseURL {
}
- (void)dealloc {
+ [self removeObserver:self forKeyPath:@"client.reachabilityObserver"];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_router release];
_router = nil;
- [_client release];
- _client = nil;
+ self.client = nil;
[_objectStore release];
_objectStore = nil;
[_serializationMIMEType release];
@@ -142,6 +155,40 @@ - (BOOL)isOffline {
return (_networkStatus == RKObjectManagerNetworkStatusOffline);
}
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if ([keyPath isEqualToString:@"client.reachabilityObserver"]) {
+ [self reachabilityObserverDidChange:change];
+ }
+}
+
+- (void)reachabilityObserverDidChange:(NSDictionary *)change {
+ RKReachabilityObserver *oldReachabilityObserver = [change objectForKey:NSKeyValueChangeOldKey];
+ RKReachabilityObserver *newReachabilityObserver = [change objectForKey:NSKeyValueChangeNewKey];
+
+ if (! [oldReachabilityObserver isEqual:[NSNull null]]) {
+ RKLogDebug(@"Reachability observer changed for RKClient %@ of RKObjectManager %@, stopping observing reachability changes", self.client, self);
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:RKReachabilityDidChangeNotification object:oldReachabilityObserver];
+ }
+
+ if (! [newReachabilityObserver isEqual:[NSNull null]]) {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(reachabilityChanged:)
+ name:RKReachabilityDidChangeNotification
+ object:newReachabilityObserver];
+
+ RKLogDebug(@"Reachability observer changed for client %@ of object manager %@, starting observing reachability changes", self.client, self);
+ }
+
+ // Initialize current Network Status
+ if ([self.client.reachabilityObserver isReachabilityDetermined]) {
+ BOOL isNetworkReachable = [self.client.reachabilityObserver isNetworkReachable];
+ self.networkStatus = isNetworkReachable ? RKObjectManagerNetworkStatusOnline : RKObjectManagerNetworkStatusOffline;
+ } else {
+ self.networkStatus = RKObjectManagerNetworkStatusUnknown;
+ }
+}
+
- (void)reachabilityChanged:(NSNotification *)notification {
BOOL isHostReachable = [self.client.reachabilityObserver isNetworkReachable];
View
2  Tests/Application/UI/RKFetchedResultsTableControllerTest.m
@@ -81,7 +81,6 @@ - (void)bootstrapStoreAndCache {
}
- (void)bootstrapNakedObjectStoreAndCache {
-// RKLogConfigureByName("RestKit/UI", RKLogLevelTrace);
RKManagedObjectStore* store = [RKTestFactory managedObjectStore];
RKManagedObjectMapping *eventMapping = [RKManagedObjectMapping mappingForClass:[RKEvent class] inManagedObjectStore:store];
[eventMapping mapKeyPath:@"event_id" toAttribute:@"eventID"];
@@ -1380,7 +1379,6 @@ - (void)testShowTheEmptyImageAfterLoadingAnEmptyCollectionIntoAnEmptyFetch {
tableController.autoRefreshFromNetwork = YES;
[tableController.cache invalidateAll];
-// RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
[RKTestNotificationObserver waitForNotificationWithName:RKTableControllerDidFinishLoadNotification usingBlock:^{
[tableController loadTable];
}];
View
1  Tests/Logic/CoreData/RKManagedObjectMappingOperationTest.m
@@ -456,7 +456,6 @@ - (void)testMappingAPayloadContainingRepeatedObjectsPerformsAcceptablyWithFetchR
}
- (void)testMappingAPayloadContainingRepeatedObjectsPerformsAcceptablyWithInMemoryMappingCache {
- RKLogConfigureByName("RestKit/CoreData/Cache", RKLogLevelTrace);
RKManagedObjectStore *store = [RKTestFactory managedObjectStore];
store.cacheStrategy = [RKInMemoryManagedObjectCache new];
View
1  Tests/Logic/Network/RKRequestQueueTest.m
@@ -257,7 +257,6 @@ - (void)testShouldRemoveItemsFromTheQueueWithAnUnmappableResponse {
}
- (void)testThatSendingRequestToInvalidURLDoesNotGetSentTwice {
- RKLogConfigureByName("RestKit/Network*", RKLogLevelTrace);
RKRequestQueue *queue = [RKRequestQueue requestQueue];
NSURL *URL = [NSURL URLWithString:@"http://bix.gg/RKRequestQueueExample"];
RKRequest *request = [RKRequest requestWithURL:URL];
View
32 Tests/Logic/ObjectMapping/RKObjectManagerTest.m
@@ -87,6 +87,7 @@ - (void)tearDown {
}
- (void)testShouldSetTheAcceptHeaderAppropriatelyForTheFormat {
+
assertThat([_objectManager.client.HTTPHeaders valueForKey:@"Accept"], is(equalTo(@"application/json")));
}
@@ -376,4 +377,35 @@ - (void)testInitializationOfRoutedPathViaSendObjectMethodUsingBlock
[responseLoader waitForResponse];
}
+- (void)testThatInitializationOfObjectManagerInitializesNetworkStatusFromClient {
+ RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"];
+ id mockObserver = [OCMockObject partialMockForObject:observer];
+ BOOL yes = YES;
+ [[[mockObserver stub] andReturnValue:OCMOCK_VALUE(yes)] isReachabilityDetermined];
+ [[[mockObserver stub] andReturnValue:OCMOCK_VALUE(yes)] isNetworkReachable];
+ RKClient *client = [RKTestFactory client];
+ client.reachabilityObserver = mockObserver;
+ RKObjectManager *manager = [[RKObjectManager alloc] init];
+ manager.client = client;
+ assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline)));
+}
+
+- (void)testThatMutationOfUnderlyingClientReachabilityObserverUpdatesManager {
+ RKObjectManager *manager = [RKTestFactory objectManager];
+ RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"];
+ assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline)));
+ manager.client.reachabilityObserver = observer;
+ assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusUnknown)));
+}
+
+- (void)testThatReplacementOfUnderlyingClientUpdatesManagerReachabilityObserver {
+ RKObjectManager *manager = [RKTestFactory objectManager];
+ RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"];
+ RKClient *client = [RKTestFactory client];
+ client.reachabilityObserver = observer;
+ assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline)));
+ manager.client = client;
+ assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusUnknown)));
+}
+
@end
Please sign in to comment.
Something went wrong with that request. Please try again.