0
votes

I am successfully retrieving JSON data from a web service with GET using Restkit's RKObjectManager and RKObjectMapping. Here's my code:

- (void)viewDidLoad
{
    [super viewDidLoad];

    RKURL *baseURL = [RKURL URLWithBaseURLString:@"http://192.168.1.12"];
    RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:baseURL];
    objectManager.client.baseURL = baseURL;

    RKObjectMapping *markerMapping = [RKObjectMapping mappingForClass:[Marker class]];
    [markerMapping mapKeyPath:@"la" toAttribute:@"lat"];
    [markerMapping mapKeyPath:@"lo" toAttribute:@"lon"];
    [markerMapping mapKeyPath:@"des" toAttribute:@"description"];
    [objectManager.mappingProvider setMapping:markerMapping forKeyPath:@"markers"];
}

- (void)sendGet
{
    NSString *lat = @"53.334932";
    NSString *lon = @"-0.543749";
    NSString *dist = @"1000";

    NSDictionary *queryParams;
    queryParams = [NSDictionary dictionaryWithObjectsAndKeys:lat, @"la", lon, @"lo", dist, @"d", nil];
    RKObjectManager *objectManager = [RKObjectManager sharedManager];

    RKURL *URL = [RKURL URLWithBaseURL:[objectManager baseURL] resourcePath:@"/get_markers.php" queryParameters:queryParams];
    [objectManager loadObjectsAtResourcePath:[NSString stringWithFormat:@"%@?%@", [URL resourcePath], [URL query]] delegate:self];
}

The above code is working and I am happily working with the returned data. However, I cannot POST a record to be inserted in the database. I think I can reuse the sharedManager and even possibly the mapping. I do not need to handle any return.

I have tried numerous variations of the following snippets. To no avail.

The first snippet is an attempt to reuse the manager and mapping. Ignoring the mapping scope in this pseudo code the obvious flaw is that I cannot work out how to POST to the correct URL resource (baseURL & '/insert_marker.php'). So I haven't actually tried this:

- (void)postInsert
{  
    Marker *mkr = [Marker alloc];
    mkr.lat = @"53.334933";
    mkr.lon = @"-0.543750";
    mkr.description = @"some words";

    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager.mappingProvider setSerializationMapping:[markerMapping inverseMapping] forClass:[Marker class]];
    [[RKObjectManager objectManager] postObject:mkr delegate:nil];
}

This second snippet runs but crashes the app. Clearly, this is confused between string and url types but the object manager post will not compile with url. I am very confused!

- (void)postInsert
{  
    RKParams* params = [RKParams params];
    [params setValue:@"53.334933" forParam:@"la"];
    [params setValue:@"-0.543750" forParam:@"l0"];
    [params setValue:@"some words" forParam:@"des"];

    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    NSString *URL = [RKURL URLWithBaseURL:[objectManager baseURL] resourcePath:@"/add_marker.php"];
    [objectManager.client post:URL params:params delegate:nil];
}

So, how can I POST with params (hopefully reusing the sharedManager, maybe the mapping and not handling a return)?

1
Could you add the error? - clopez
I am so new to Xcode that I am unsure how to retrieve useful info about the error. It stops in main reporting "Thread1 Signal SIGBRT". Is that any use? - Polly
to show the real exception try using the "All Exception BreakPoint" on the BreakPoint Navigator. - clopez
The error occurs in the Restkit initWithBaseURL function. On the line: NSRange queryCharacterRange = [theResourcePath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"?"]]; This is from the last line of my 2nd snippet (maybe my confusion between string and url?) - Polly
you can just use a string: NSString *baseUrl = @""; [RKObjectManager objectManagerWithBaseURLString:baseUrl]; - clopez

1 Answers

0
votes

As posted in the comments, try using NSStrings instead of RKURL like this:

NSString *baseUrl = @"https://mysite.com"; 
[RKObjectManager objectManagerWithBaseURLString:baseUrl];

If you want to make something more robust, you can also try to make a post using the objectManager instead the client on the objectManager, for example you can use blocks:

- (void) post: (id) myEntity onLoad:(RKObjectLoaderDidLoadObjectBlock) loadBlock onError:(RKRequestDidFailLoadWithErrorBlock)failBlock showingLoader:(BOOL)loaderWillShow{

    RKObjectMapping *mapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[[myEntity class] class]];
    [[RKObjectManager sharedManager] postObject:myEntity usingBlock:^(RKObjectLoader *loader) {
        [self settingsForLoader:loader withMapping:mapping onLoad:loadBlock onError:failBlock showingLoader:loaderWillShow];
    }];

}

//Settings For Loader definition:



- (void) settingsForLoader: (RKObjectLoader *) loader withMapping: (RKObjectMapping *) mapping onLoad:(RKObjectLoaderDidLoadObjectBlock) loadBlock onError:(RKRequestDidFailLoadWithErrorBlock)failBlock showingLoader:(BOOL) loaderWillShow{

    loader.objectMapping = mapping;
    loader.delegate = self;
    loader.onDidLoadObject = loadBlock;

    loader.onDidFailWithError = ^(NSError * error){
       //NSLog(@"%@",error);
    };

    loader.onDidFailLoadWithError = failBlock;
    loader.onDidLoadResponse = ^(RKResponse *response) {
        [self fireErrorBlock:failBlock onErrorInResponse:response disablingLoader:loaderWillShow];
    };

}