iOS7 & RESTKit 0.20.3
Below is the URL that I need to hit to get a response from Google Maps APIs (I changed the key):
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=coffee&sensor=true&key=1234&location=0.000000,0.000000&radius=100.000000
When I type the URL above in the browser, I get a JSON back (200 OK)
input is the search string the user provides. I have hard-coded it into the URL above.
The following is what I have tried and get a 404 error:
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/placeautocomplete/json?input=%#&sensor=true&key=1234&location=0.000000,0.000000&radius=100.000000", [input stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:#""
keyPath:#"predictions" statusCodes:statusCodeSet];
I have also tried the following that gives an error Code=1001 "No response descriptors match the response loaded." :
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [TBSRESTMappingProvider googleAutoCompleteMapping];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=coffee&sensor=true&key=1234&location=0.000000,0.000000&radius=100.000000"]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:#""
keyPath:#"predictions" statusCodes:statusCodeSet];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptor]];
What's the best practice to provide the complete URL without hard-coding the input sensor location key and radius ?
How can I fix Code=1001 "No response descriptors match the response loaded." ?
The URL path that you request needs to match against the path pattern you supply to the response descriptor. If you want to work the way you are then set the path pattern to nil (which matches everything).
Best practice would generally be to use an RKObjectManager instance and call getObjectsAtPath:parameters:success:failure: and passing a dictionary of parameters that should be appended to the request URL (built from the base URL, path and parameters).
Related
I use NSURL to load some things from an MySQL Database. Sometimes this is very slow and the app stops running because the Database is not answering.
I thought I could make a timeout, so after e.g. 3 seconds, the app stops loading the NSURL and tries again or does something else like an UIAlertView.
Please help me!
Jannes
PS: I use this code to load these things from the Database:
-(void) loadSomething {
NSError *error;
NSString *urlString = #"http://someip/App/somefile.txt";
NSURL *url = [NSURL URLWithString:urlString];
#try {
NSString *resultString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
}
#catch (NSException *exception) {
NSLog(#"Error");
}
Your request is a synchronous request and this type of request freezes the ui, you should use an asynchronous request to prevent the freeze.
Here is a tutorial on request asynch / synch that should help you.
Otherwise perhaps think to use the framework " AFNETWorking " it greatly simplifies the use of NSURLConnection and NSURLRequest
I have a connection issue that I am unsure how to resolve. I have combed through the documentation for the Errors and for NSURLConnection. This is code that I am using in my iOS version of the same app. It works fine there, but when I brought it to the OS X version of the app, it doesn't work. This is the code:
NSURL* url = [NSURL URLWithString:#"url"];
NSString* data = [NSString stringWithFormat:#"command=retrieve&number=%d", number];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"Starting Command");
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog([NSString stringWithFormat:#"%#",connectionError]);
if ([data length] > 0 && connectionError == nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self parseResponseFromCommandRequest:data];
});
}
}];
NSLog(#"Ending Command");
The error occurs in the NSURLConnection. The output is:
Error Domain=NSPOSIXErrorDomain Code=1 "The operation couldn’t be completed. Operation not permitted" UserInfo=0x610000279dc0 {NSErrorFailingURLStringKey=url, NSErrorFailingURLKey=url}
url is actually a functioning url, but I replaced it here. Like I said, it works fine on iOS, but not on OS X. Is there a Library that I could be missing that is causing this? Any other ideas?
It could be just a matter of setting up the entitlements to allow access. It looks from the error that it fails because it's not permitted, which would indicate the app sandbox is doing it's job. For NSURL you would normally use bookmarks.app-scope or bookmarks.document-scope.
See: Enabling Security-Scoped Bookmark and URL Access
Depending on how your app is using the NSURL, network entitlements may be worth looking into:
com.apple.security.network.server = Allow Incoming Connections
com.apple.security.network.client = Allow Outgoing Connections
I'm trying to understand the restkit 0.22. I got some tutorials from different blogs and youtubes. I ended up with mixed up code.
Could anyone please help me with this, I really need it to work for my project.
I created Core Data Model with entities Songs.xcdatamodeld
I have a json that comes from my mySQL db:
[{"SongID":"1","SongTitle":"Song1","PerformerName":"Performer1","SongURL":"http://mysite/mysongs/1.mp3","PerformerPic":"PerfPic1.png"},
{"SongID":"2","SongTitle":"Song2","PerformerName":"Performer2","SongURL":"http://mysite/mysongs/2.mp3","PerformerPic":"PerfPic2.png"},
{"SongID":"3","SongTitle":"Song3","PerformerName":"Performer3","SongURL":"http://mysite/mysongs/3.mp3","PerformerPic":"PerfPic3.png"}]
in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:http://mysite]];
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Songs" ofType:#"momd"]];
//Initialize managed object store
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL ] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
[RKObjectManager sharedManager].requestSerializationMIMEType = RKMIMETypeJSON;
[RKMIMETypeSerialization registeredMIMETypes];
[objectManager setAcceptHeaderWithMIMEType:#"application/json"];
RKEntityMapping* mapping = [RKEntityMapping mappingForEntityForName:#"Songs"
inManagedObjectStore:[RKObjectManager sharedManager].managedObjectStore];
mapping.identificationAttributes = #[#"songID"];
[mapping addAttributeMappingsFromDictionary:#{#"id" : #"SongID",
#"songTitle" : #"SongTitle",
#"performerName" : #"PerformerName",
#"songURL" : #"SongURL",
#"performerPic" : #"PerformerPic"}];
return YES;
}
in TableView Controller:
- (void)viewDidLoad
{
[super viewDidLoad];
[RKObjectManager.sharedManager getObjectsAtPath:#"/api.php"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
self.Songs = [mappingResult array];
NSLog(#"It Worked: %#", self.Songs);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"It Failed: %#", error);
}];
}
This is the error I'm getting:
GET 'http://mysite/api.php' (200 OK / 0 objects) [request=3.5566s mapping=0.0000s
total=3.5627s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001
"No response descriptors match the response loaded." UserInfo=0xb5920b0
{NSErrorFailingURLStringKey=http://mysite/api.php, NSLocalizedFailureReason=A 200
response was loaded from the URL 'http://mysite/api.php', which failed to match all (0)
response descriptors:, NSLocalizedDescription=No response descriptors match the response
loaded., keyPath=null, NSErrorFailingURLKey=http://mysite/api.php,
NSUnderlyingError=0xb5921b0 "No mappable object representations were found at the key
paths searched."}
First, you don't seem to be creating the managed object contexts as part of your setup code. This will likely cause you issues after you fix your 'main' issue:
Your main issue is quite clearly described in the error message:
which failed to match all (0) response descriptors
I.e. You haven't created any response descriptors.
The Object-mapping guide walks you through the mapping and descriptor creation process (and includes lots more details to boot).
Start with something like:
RKResponseDescriptor *rd = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
then add the mapping to the object manager.
(ensure you're calling createManagedObjectContexts somewhere).
I'm working on an iPhone app that needs to load data from my server in JSON or XML format. Since the app is free, I get huge amount of data and I get crash when launching app due to the long time when loading the data. So I understand that I should not get "all" the JSON at once but I have to load the data "pagened" [ little by little ] ..
I found this project that suits well my needs but can't get succes to modify it to my need :
https://github.com/nmondollot/NMPaginator
The project tooks Twitter api as a data source, what if I need to deal with a simple php file that returns JSON formatted data?
nb: I tried to contact the project developer after I tried to modify, but didn't get answer until now.
Thanks.
The easiest solution could be to just download the data in another thread. This can be done in many ways but one way to do it is by using grand central dispatch (GCD).
Something like this
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSURL *url = [NSURL URLWithString:#"Your_URL"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:req
queue:[NSOperationQueue currentQueue]
completionHandler:
^(NSURLResponse *res, NSData *data, NSError *err) {
// Convert the data to appropriate object
NSString* myString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//You would probably deserialize the json here
//self.tableViewArray = serialiedObjects;
dispatch_async(dispatch_get_main_queue(), ^{
//Reload table view
[self.tableView reloadData];
});
}];
});
I am running a phpmyadmin database and have made a table with 3 columns. Username, Password and Age. In Xcode ive made a login app that uses the username and password to login with
NSString *strURL = [NSString stringWithformat:#"http://localhost/database/login.php?username=%#&password=%#", usernamefield.text, passwordtextfield.text];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
if ([strResult isEqualToString:#"1"])
This code works fine!
Is it then possible to show the third column in the database (AGE) in a text label when pressing login? so the Age of the user logged in will be displayed in a text label at the top bar of the app?
There's a lot that you could do to improve the security (not sending the password as a parameter of a GET request, it might (will) end up on some log somewhere unprotected), reliability (your script might not be the only thing that need to run on localhost) or the responsiveness (not doing a synchronous call) of that code.
But, starting with that code as a minimalistic starting point, you could configure your php script to respond with the age value and dispatch this value to a textfield/window title/whatever you want.
But then how to check if the user is correctly connected? Your script running on localhost could respond with bad authentication with a string.
For example:
NSString *strURL = [NSString stringWithformat:#"http://localhost/database/login.php?username=%#&password=%#", usernamefield.text, passwordtextfield.text];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
if ([strResult isEqualToString:#"auth_error"]){
// do something
} else {
[window setTitle:strResult]
}
But that's really a start.
After that, you might be interested to use JSON to answer the request and then read it with NSJSONSerialization, making your script a little more reliable and RESTful.