23

I'm fairly new to Objective-C and XCode, but even newer to RestKit, though been programming in Java for 12 years.

I have an IOS app connected to RestKit and an action to load from a rest server works only the first time, if I go back in the navigation controller and try the same operation again, the loadObjectsAtResourcePath:delegate method is called, but none of the delegate methods ever get called (and I implemented all of them just to log when they happen).

I feel I have missed something fundamental with Restkit, and perhaps the async nature of it, because the mapping is clearly working fine the first time, so the subsequent call must be getting lost in an async queue.

I have googled this, and seen similar people getting stuck with something similar, but tried them all and doesn't seem to make a difference. Caching is disabled, the objectLoaderDidLoadUnexpectedResponse and didFailWithError never get called, it's getting dropped to the floor.

Code Source:

My XCode project is up on github here

The specific View Controller doing the load call is here (see setUpRestKit method)

The sequence of calls goes like this:

  • User fills in hostname, and port, and clicks connect
  • ESRKConnectionViewController.m gets the call via prepareForSegue and sets up the shared RKClient with this address (though I find out later the RKClient isn't used much, the RKOBjectManager seems to take just a baseURL, so a bit redundant there)
  • ESRKServerViewController.m then sets the mapping on the RKObjectManager and invokes the loadObjectsAtResourcePath passing itself as a delegate (yes I realise probably these mappings should be configured at the start in the App Delegate, but I can't see how setting this up again is anything more than just redundant code)
  • the objectLoader:didLoadObjects callback is then in charge of taking the mapped object and configuring the model for the table view - this is fired only once.

Enabling the logs, this is the pattern I see, with annotations on when the first call completes, and when the second one starts etc (timestamps trimmed for clarity here):

ElasticSearchHeadIOS[25064:fb03] I restkit:RKLog.m:32 RestKit initialized...
ElasticSearchHeadIOS[25064:fb03] I restkit.support:RKCache.m:178 Invalidating cache at path: /Users/paulsmith/Library/Application Support/iPhone Simulator/5.1/Applications/BDB8B59F-8307-4F18-A4E7-C55849618D77/Library/Caches/RKClientRequestCache-localhost/SessionStore
ElasticSearchHeadIOS[25064:fb03] I restkit.network.reachability:RKReachabilityObserver.m:155 Reachability observer initialized with hostname localhost
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKClient.m:271 Reachability observer changed for client <RKClient: 0x80756e0>, suspending queue <RKRequestQueue: 0x8082600 name=(null) suspended=YES requestCount=0 loadingCount=0/5> until reachability to host 'localhost' can be determined
ElasticSearchHeadIOS[25064:fb03] Connecting to http://localhost:9200/ -- http://localhost:9200/ -- http://localhost:9200/
ElasticSearchHeadIOS[25064:fb03] I restkit.support:RKCache.m:178 Invalidating cache at path: /Users/paulsmith/Library/Application Support/iPhone Simulator/5.1/Applications/BDB8B59F-8307-4F18-A4E7-C55849618D77/Library/Caches/RKClientRequestCache-localhost/SessionStore
ElasticSearchHeadIOS[25064:fb03] I restkit.network.reachability:RKReachabilityObserver.m:155 Reachability observer initialized with hostname localhost
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKClient.m:271 Reachability observer changed for client <RKClient: 0x8087840>, suspending queue <RKRequestQueue: 0x8087a40 name=(null) suspended=YES requestCount=0 loadingCount=0/5> until reachability to host 'localhost' can be determined
ElasticSearchHeadIOS[25064:fb03] I restkit.network.reachability:RKReachabilityObserver.m:369 Network availability has been determined for reachability observer <RKReachabilityObserver: 0x8088980 host=localhost isReachabilityDetermined=YES isMonitoringLocalWiFi=1039984 reachabilityFlags=-R -----ld>
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKClient.m:401 Reachability to host 'localhost' determined for client <RKClient: 0x8087840>, unsuspending queue <RKRequestQueue: 0x8087a40 name=(null) suspended=YES requestCount=1 loadingCount=0/5>
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKRequest.m:435 Sending asynchronous GET request to URL http://localhost:9200/_cluster/state.
ElasticSearchHeadIOS[25064:fb03] T restkit.network:RKRequest.m:381 Prepared GET URLRequest '<NSMutableURLRequest http://localhost:9200/_cluster/state>'. HTTP Headers: {
    Accept = "application/json";
    "Content-Length" = 0;
}. HTTP Body: .
ElasticSearchHeadIOS[25064:fb03] I restkit.network.reachability:RKReachabilityObserver.m:369 Network availability has been determined for reachability observer <RKReachabilityObserver: 0x6c5c530 host=localhost isReachabilityDetermined=YES isMonitoringLocalWiFi=1039984 reachabilityFlags=-R -----ld>
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKClient.m:401 Reachability to host 'localhost' determined for client <RKClient: 0x80756e0>, unsuspending queue <RKRequestQueue: 0x8082600 name=(null) suspended=YES requestCount=0 loadingCount=0/5>
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKResponse.m:195 NSHTTPURLResponse Status Code: 200
ElasticSearchHeadIOS[25064:fb03] D restkit.network:RKResponse.m:196 Headers: {
    "Content-Length" = 4462;
    "Content-Type" = "application/json; charset=UTF-8";
}
 ElasticSearchHeadIOS[25064:fb03] T restkit.network:RKResponse.m:203 Read response body: {"cluster_name":"paul","master_node":"FGewvE3-TEKjXugOGJpWmQ","blocks":{},"nodes":{"FGewvE3-TEKjXugOGJpWmQ":{"name":"Namor the Sub-Mariner","transport_address":"inet[/192.168.0.12:9300]","attributes":{}}},"metadata":{"templates":{},"indices":{"melpaul":{"state":"open","settings":{"index.number_of_replicas":"1","index.number_of_shards":"5","index.version.created":"190299"},"mappings":{"project":{"properties":{"projectAddress":{"type":"string"},"id":{"type":"string"},"suburb":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"postalAddress":{"type":"string"},"ownerOrganizationID":{"type":"long"},"shortName":{"type":"string"},"deliveryAddress":{"type":"string"},"country":{"type":"string"}}},"organization":{"properties":{"id":{"type":"string"},"tradingName":{"type":"string"},"name":{"type":"string"},"extParticipant":{"type":"string"},"code":{"type":"string"}}},"task":{"properties":{"aggregateCount":{"type":"long"},"dueDateIso":{"type":"string"},"assignedByUser":{"type":"string"},"pertinent":{"type":"boolean"},"assignedByUserId":{"type":"long"},"assignedBy":{"type":"string"},"projectId":{"type":"long"},"type":{"type":"string"},"id":{"type":"string"},"creationDate":{"type":"long"},"assignedToUserId":{"type":"long"},"description":{"type":"string"},"featureId":{"type":"string"},"aggregated":{"type":"boolean"},"assignedToUser":{"type":"string"},"projectName":{"type":"string"},"dueDate":{"type":"long"},"referenceLabel":{"type":"string"}}},"user":{"properties":{"sortlastName":{"type":"string"},"position":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"accessEnabled":{"type":"string"},"orgName":{"type":"string"},"directoryVisibility":{"type":"string"},"id":{"type":"string"},"orgId":{"type":"string"},"orgTradingName":{"type":"string"},"title":{"type":"string"},"divisionName":{"type":"string"},"email":{"type":"string"},"sortfirstName":{"type":"string"},"userName":{"type":"string"},"extParticipant":{"type":"string"},"firstName":{"type":"string"},"accountUnlocked":{"type":"string"},"mobile":{"type":"string"}}}},"aliases":[]}}},"routing_table":{"indices":{"melpaul":{"shards":{"0":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":0,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":0,"index":"melpaul"}],"1":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":1,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":1,"index":"melpaul"}],"2":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":2,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":2,"index":"melpaul"}],"3":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":3,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":3,"index":"melpaul"}],"4":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":4,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":4,"index":"melpaul"}]}}}},"routing_nodes":{"unassigned":[{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":0,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":1,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":2,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":3,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":4,"index":"melpaul"}],"nodes":{"FGewvE3-TEKjXugOGJpWmQ":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":0,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":1,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":2,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":3,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":4,"index":"melpaul"}]}},"allocations":[]}
 ElasticSearchHeadIOS[25064:1400b] D restkit.network:RKObjectLoader.m:262 Beginning object mapping activities within GCD queue labeled: org.restkit.ObjectMapping
 ElasticSearchHeadIOS[25064:1400b] D restkit.network:RKObjectLoader.m:250 No object mapping provider, using mapping provider from parent object manager to perform KVC mapping
 ElasticSearchHeadIOS[25064:1400b] T restkit.network:RKObjectLoader.m:187 bodyAsString: {"cluster_name":"paul","master_node":"FGewvE3-TEKjXugOGJpWmQ","blocks":{},"nodes":{"FGewvE3-TEKjXugOGJpWmQ":{"name":"Namor the Sub-Mariner","transport_address":"inet[/192.168.0.12:9300]","attributes":{}}},"metadata":{"templates":{},"indices":{"melpaul":{"state":"open","settings":{"index.number_of_replicas":"1","index.number_of_shards":"5","index.version.created":"190299"},"mappings":{"project":{"properties":{"projectAddress":{"type":"string"},"id":{"type":"string"},"suburb":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"postalAddress":{"type":"string"},"ownerOrganizationID":{"type":"long"},"shortName":{"type":"string"},"deliveryAddress":{"type":"string"},"country":{"type":"string"}}},"organization":{"properties":{"id":{"type":"string"},"tradingName":{"type":"string"},"name":{"type":"string"},"extParticipant":{"type":"string"},"code":{"type":"string"}}},"task":{"properties":{"aggregateCount":{"type":"long"},"dueDateIso":{"type":"string"},"assignedByUser":{"type":"string"},"pertinent":{"type":"boolean"},"assignedByUserId":{"type":"long"},"assignedBy":{"type":"string"},"projectId":{"type":"long"},"type":{"type":"string"},"id":{"type":"string"},"creationDate":{"type":"long"},"assignedToUserId":{"type":"long"},"description":{"type":"string"},"featureId":{"type":"string"},"aggregated":{"type":"boolean"},"assignedToUser":{"type":"string"},"projectName":{"type":"string"},"dueDate":{"type":"long"},"referenceLabel":{"type":"string"}}},"user":{"properties":{"sortlastName":{"type":"string"},"position":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"accessEnabled":{"type":"string"},"orgName":{"type":"string"},"directoryVisibility":{"type":"string"},"id":{"type":"string"},"orgId":{"type":"string"},"orgTradingName":{"type":"string"},"title":{"type":"string"},"divisionName":{"type":"string"},"email":{"type":"string"},"sortfirstName":{"type":"string"},"userName":{"type":"string"},"extParticipant":{"type":"string"},"firstName":{"type":"string"},"accountUnlocked":{"type":"string"},"mobile":{"type":"string"}}}},"aliases":[]}}},"routing_table":{"indices":{"melpaul":{"shards":{"0":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":0,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":0,"index":"melpaul"}],"1":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":1,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":1,"index":"melpaul"}],"2":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":2,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":2,"index":"melpaul"}],"3":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":3,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":3,"index":"melpaul"}],"4":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":4,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":4,"index":"melpaul"}]}}}},"routing_nodes":{"unassigned":[{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":0,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":1,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":2,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":3,"index":"melpaul"},{"state":"UNASSIGNED","primary":false,"node":null,"relocating_node":null,"shard":4,"index":"melpaul"}],"nodes":{"FGewvE3-TEKjXugOGJpWmQ":[{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":0,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":1,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":2,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":3,"index":"melpaul"},{"state":"STARTED","primary":true,"node":"FGewvE3-TEKjXugOGJpWmQ","relocating_node":null,"shard":4,"index":"melpaul"}]}},"allocations":[]}
 ElasticSearchHeadIOS[25064:1400b]  willMapData
 ElasticSearchHeadIOS[25064:fb03] did finish loading

Ok the table view showing the mapped data that has come back from the above calls is now done, and I can see the results correctly on screen.

I click back on the Navigation controller, try the same request again, and here's what the logs do. The logs here start just after I click the connect button and start the same calls as above (no other logs occur between the above block and this one below).

I restkit.support:RKCache.m:178 Invalidating cache at path: /Users/paulsmith/Library/Application Support/iPhone Simulator/5.1/Applications/BDB8B59F-8307-4F18-A4E7-C55849618D77/Library/Caches/RKClientRequestCache-localhost/SessionStore
I restkit.network.reachability:RKReachabilityObserver.m:155 Reachability observer initialized with hostname localhost
D restkit.network:RKClient.m:271 Reachability observer changed for client <RKClient: 0x808ce90>, suspending queue <RKRequestQueue: 0x80834c0 name=(null) suspended=YES requestCount=0 loadingCount=0/5> until reachability to host 'localhost' can be determined
D restkit.network:RKClient.m:256 Reachability observer changed for RKClient <RKClient: 0x80756e0>, disposing of previous instance: <RKReachabilityObserver: 0x6c5c530 host=localhost isReachabilityDetermined=YES isMonitoringLocalWiFi=1039984 reachabilityFlags=-R -----ld>
Connecting to http://localhost:9200/ -- http://localhost:9200/ -- http://localhost:9200/
I restkit.support:RKCache.m:178 Invalidating cache at path: /Users/paulsmith/Library/Application Support/iPhone Simulator/5.1/Applications/BDB8B59F-8307-4F18-A4E7-C55849618D77/Library/Caches/RKClientRequestCache-localhost/SessionStore
I restkit.network.reachability:RKReachabilityObserver.m:155 Reachability observer initialized with hostname localhost
D restkit.network:RKClient.m:271 Reachability observer changed for client <RKClient: 0x81b0bc0>, suspending queue <RKRequestQueue: 0x81b0d20 name=(null) suspended=YES requestCount=0 loadingCount=0/5> until reachability to host 'localhost' can be determined
D restkit.network:RKClient.m:256 Reachability observer changed for RKClient <RKClient: 0x81b0bc0>, disposing of previous instance: <RKReachabilityObserver: 0x81b1c80 host=localhost isReachabilityDetermined=NO isMonitoringLocalWiFi=1039984 reachabilityFlags=-- ------->
I restkit.network.reachability:RKReachabilityObserver.m:369 Network availability has been determined for reachability observer <RKReachabilityObserver: 0x807f2f0 host=localhost isReachabilityDetermined=YES isMonitoringLocalWiFi=1039984 reachabilityFlags=-R -----ld>
D restkit.network:RKClient.m:401 Reachability to host 'localhost' determined for client <RKClient: 0x808ce90>, unsuspending queue <RKRequestQueue: 0x80834c0 name=(null) suspended=YES requestCount=0 loadingCount=0/5>

Here is a Jing screencast of what it looks like in the simulator (you can see the break points of the delegate methods getting called the first time around, but then nothing the 2nd)

Chris
  • 5,584
  • 9
  • 40
  • 58
tallpsmith
  • 287
  • 2
  • 8
  • 1
    So, after just trying to debug into RestKit to understand what is happening, I decide to just refactor a bit while I see if the community answers. My first refactor was to pull out the mapping definitions from the Server view controller and put it in the Connection View controller which is setup just once, and then lookup the relevant mapping I want to bind it to the root key path. THIS WORKS! WTF? You can see my subsequent changes in this git commit hash: https://github.com/tallpsmith/ElasticSearchIOSHead/commit/041d3eeb37608f07880a0dfb3f65934aae2ba5f0 Anyone tell me WHY this works? – tallpsmith May 05 '12 at 10:49
  • You are loosing the delegate somewhere, let me check your code – clopez Sep 14 '12 at 17:45

2 Answers2

1

This is a retain problem. You are creating a local copy of an object and not assigning it to anything that causes it to be retained. This is probably RKObjectManager or the like. Create a property such as myObjectManager and assign like this self.myObjectManager = [[RkObjectManager alloc] init];

Make sure you study and understand memory management. Use ARC, but you will still need a basic understanding of memory management!

HTH

1

I also find this method in documentation: loadObjectsAtResourcePath:usingBlock: but I can't use it because it tells me: No visible @interface for 'RKObjectManager' declares ... If you are trying to target Core Data, then you'll want to use RKManagedObjectRequestOperation and managedObjectRequestOperationWithRequest:success:failure: . There are additional examples available in the .... Restkit Post Not sending Object · 1 · PUT request , change headers and save ...