Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

RKObjectManager now compatible with client's reachability observer changes #717

Closed
wants to merge 1 commit into from

2 participants

@dusek

When changing object manager's client.reachabilityObserver,
my client always asserted in [RKReachabilityObserver
validateIntrospection], because self.isReachabilityDetermined == NO.
I found out that this is probably due to this:

  • object manager's client.reachabilityObserver is assigned to new value
  • object manager still listens to client's old reachability observer
  • old reachability observer sends notification that reachability changed
  • new reachability observer hasn't still determined its reachability
  • object manager processes the notification from old reachability observer, but when doing so asks self.client.reachabilityObserver (a.k.a. the new reachability observer) for reachability details
  • new reachability observer asserts that it is being asked for reachability details when it hasn't determined its reachability

My solution is to simply make object manager always listen to the
current client's current reachability observer by detecting
its changes through KVO.

I am very new to RestKit, so please check I did not miss something :-)
At the very least I don't know whether we shouldn't send a
RKObjectManagerDidBecomeUndeterminedNotification (which does not
yet exist). I also did not write any tests, since the assert did happen asynchronously
from the code that changed the reachability observer (it happened when the reachability
was determined), and I don't know how I would test for something like that.

@dusek dusek RKObjectManager now compatible with client's reachability observer ch…
…anges

When changing object manager's client.reachabilityObserver,
my client always asserted in [RKReachabilityObserver
validateIntrospection], because self.isReachabilityDetermined == NO.
I found out that this is probably due to this:

* object manager's client.reachabilityObserver is assigned to new
  value
* object manager still listens to client's old reachability observer
* old reachability observer sends notification that reachability
  changed
* new reachability observer hasn't still determined its reachability
* object manager processes the notification from old reachability
  observer, but when doing so asks
  self.client.reachabilityObserver (a.k.a. the new reachability
  observer)  for reachability details
* new reachability observer asserts that it is being asked for
  reachability details when it hasn't determined its reachability

My solution is to simply make object manager always listen to the
current client's current reachability observer by detecting
its changes through KVO.
bc211ee
@blakewatters blakewatters was assigned
@blakewatters

Thanks for the contribution here. I have actually just run into a similar issue. Will add some tests and merge.

@blakewatters blakewatters referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@blakewatters blakewatters referenced this pull request from a commit
@dusek dusek Update RKObjectManager to observe changes to the reachability observe…
…r of

the underlying RKClient object. refs #717
e932c31
@blakewatters

Merged to development in e932c31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 6, 2012
  1. @dusek

    RKObjectManager now compatible with client's reachability observer ch…

    dusek authored
    …anges
    
    When changing object manager's client.reachabilityObserver,
    my client always asserted in [RKReachabilityObserver
    validateIntrospection], because self.isReachabilityDetermined == NO.
    I found out that this is probably due to this:
    
    * object manager's client.reachabilityObserver is assigned to new
      value
    * object manager still listens to client's old reachability observer
    * old reachability observer sends notification that reachability
      changed
    * new reachability observer hasn't still determined its reachability
    * object manager processes the notification from old reachability
      observer, but when doing so asks
      self.client.reachabilityObserver (a.k.a. the new reachability
      observer)  for reachability details
    * new reachability observer asserts that it is being asked for
      reachability details when it hasn't determined its reachability
    
    My solution is to simply make object manager always listen to the
    current client's current reachability observer by detecting
    its changes through KVO.
This page is out of date. Refresh to see the latest.
Showing with 28 additions and 0 deletions.
  1. +28 −0 Code/ObjectMapping/RKObjectManager.m
View
28 Code/ObjectMapping/RKObjectManager.m
@@ -84,6 +84,7 @@ - (id)initWithBaseURL:(RKURL *)baseURL {
[errorMapping mapKeyPath:@"" toAttribute:@"errorMessage"];
_mappingProvider.errorMapping = errorMapping;
+ [self addObserver:self forKeyPath:@"client.reachabilityObserver" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name:RKReachabilityDidChangeNotification
@@ -142,6 +143,33 @@ - (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];
+ _networkStatus = RKObjectManagerNetworkStatusUnknown;
+ }
+
+ if (! [newReachabilityObserver isEqual:[NSNull null]]) {
+ _networkStatus = RKObjectManagerNetworkStatusUnknown;
+ [[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);
+ }
+}
+
- (void)reachabilityChanged:(NSNotification *)notification {
BOOL isHostReachable = [self.client.reachabilityObserver isNetworkReachable];
Something went wrong with that request. Please try again.