I come from a Swift background; therefore, am used to Alamofire. I am trying to learn Objective-C and have been plying with AFNetworking.
The following is a simple method that calls the Yelp search API to find business in the vicinity.
- (void) getBusinesses: (NSString *) usingToken{
NSString *starbucks = #"Starbucks";
NSString *latitude = #""; //enter latitude
NSString *longitude = #""; //enter longitude
NSString *URLString = [NSString stringWithFormat:#"https://api.yelp.com/v3/businesses/search?term=%#&latitude=%#&longitude=%#", starbucks, latitude, longitude];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
AFHTTPRequestSerializer *request = [[AFHTTPRequestSerializer alloc] requestWithMethod:#"GET" URLString:URLString parameters:nil error:nil];
NSString *bearerToken = [NSString stringWithFormat: #"Bearer %#", usingToken];
[request setValue: bearerToken forHTTPHeaderField:#"Authorization"];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error){
if (error){
NSLog(#"*** Failed!");
} else {
NSLog(#"*** Succeeded!");
}
}];
dataTask.resume;
}
When running this code I get the following error:
Incorrect NSStringEncoding value 0x0000 detected. Assuming NSASCIIStringEncoding. Will stop this compatibility mapping behavior in the near future.
I have tested the above Yelp URL with my valid access token on Postman and it works perfectly.
If someone could point me in the right direction to figure out what is going on I'd appreciate it!
P.S. this is the documentation for the Yelp search endpoint
Related
Here is my objective-c code to obtain access token from SoundCloud:
- (void) authoriseSoundcloud {
NSString *apiUrl = #"https://api.soundcloud.com/oauth2/token";
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[ NSURL URLWithString:apiUrl]];
NSString * params = [NSString stringWithFormat:#"client_id=%#&client_secret=%#grant_type=password&username=%#&password=%#",client,secretKey,fldUsername.text,fldPassword.text ];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSession *defaultSession = [NSURLSession sharedSession];
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(#"Response:%# %#\n", response, error);
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
}
}];
[dataTask resume];
}
However, I always get the result 401- {"error":"invalid_client"}.
However, that client ID works perfectly with those requests, that does not need authorization and I have checked multiple times, that my client ID and secret are correct.
As there is not much samples for iOS to use those parameters in HTTP post body, I assume that maybe my parameters list is incorrect. Any ideas from Soundcloud engineers?
Just a typo mistake, simply add "&" between "client_secret=%#" and "grant_type", like this :
NSString * params = [NSString stringWithFormat:#"client_id=%#&client_secret=%#&grant_type=password&username=%#&password=%#",client,secretKey,fldUsername.text,fldPassword.text ];
Work like a charm :)
I am working on a Mac app in objective-c which will use the eBay API to access the eBay functionality, including trading. I have successfully retrieved items and categories, but for trading, I need the session ID and token, which I have not been able to do.
I have made many changes after reading various posts and the documentation, but always get this error after responding to the challenge:
error: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x6080000585a0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://api.sandbox.ebay.com/ws/api.dll, NSErrorFailingURLKey=https://api.sandbox.ebay.com/ws/api.dll, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.}
After making the call, I get the challenge callback and handle it here:
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *credential))completionHandler{
NSLog(#"didReceiveChallenge: %#", challenge);
NSURLCredential* credential = [NSURLCredential credentialWithUser:sandBoxUserID password:sandBoxPassword persistence:NSURLCredentialPersistenceForSession];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}
The call for the session ID is here:
-(void) retrieveSessionID{
// retrieve a session ID for this user for this app
// headers for auth
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSMutableString* urlString = [[NSMutableString alloc]initWithCapacity:200];
[urlString appendString:sandBoxEndPoint];
NSString* callname = #"GetSessionID";
NSString* version = #"768";
NSString* contentType = #"text/xml";
NSString* siteID = #"0";
NSMutableDictionary* headersDictionary = [[NSMutableDictionary alloc]initWithCapacity:10];
[headersDictionary setObject:contentType forKey:#"Content-Type"];
[headersDictionary setObject:sandBoxAppID forKey:#"X-EBAY-API-APP-NAME"];
[headersDictionary setObject:devID forKey:#"X-EBAY-API-DEV-NAME"];
[headersDictionary setObject:sandBoxCertID forKey:#"X-EBAY-API-CERT-NAME"];
[headersDictionary setObject:callname forKey:#"X-EBAY-API-CALL-NAME"];
[headersDictionary setObject:version forKey:#"X-EBAY-API-COMPATIBILITY-LEVEL"];
[headersDictionary setObject:siteID forKey:#"X-EBAY-API-SITEID"];
configuration.HTTPAdditionalHeaders = headersDictionary;
NSLog(#"configuration.HTTPAdditionalHeaders: %#", configuration.HTTPAdditionalHeaders);
NSLog(#"urlString: %#", urlString);
NSURL *eBayUrl = [NSURL URLWithString:urlString];
NSLog(#"eBayUrl: %#", eBayUrl);
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:eBayUrl];
request.HTTPMethod = #"GET";
NSXMLElement *root = [[NSXMLElement alloc] initWithName:#"GetSessionIDRequest"];
[root addAttribute:[NSXMLNode attributeWithName:#"xmnls" stringValue:#"urn:ebay:apis:eBLBaseComponents"]];
NSXMLElement *childElement1 = [[NSXMLElement alloc] initWithName:#"RuName"];
childElement1.stringValue = sandBoxRuName;
[root addChild:childElement1];
NSXMLDocument *xmlRequest = [NSXMLDocument documentWithRootElement:root];
NSData* xmlRequestAsData = [xmlRequest XMLData];
request.HTTPBody = xmlRequestAsData;
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
NSLog(#"error: %#", error);
NSLog(#"response: %#", response);
self.sessionIDRequestXMLstring = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"self.sessionIDRequestXMLstring: %#", self.sessionIDRequestXMLstring);
[self.delegate receivedSessionIDRequestXMLstring:self.sessionIDRequestXMLstring];
}
];
[dataTask resume];
}
I apologize for the formatting here, but I haven't quite figured out how to use it correctly.
I'm trying to submit a GET request from a web service and I want to pass a JSON argument as a parameter in the HTTP header. I have the following code that performs the get request without the JSON argument. How would I add the JSON argument in the HTTP body to pass the JSON parameter?
Heres is my code that works without the JSON argument:
-(void) getReposByDate:(void (^)(NSMutableArray *))handler
{
//Get credentials
NSDictionary *credentials = [KeychainUserPass load:#"APP NAME"];
NSString *userName = [credentials allKeys][0];
NSString *password = credentials[userName];
//Create request
NSString *requestString = #"SOME WEB SERVICE URL";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSData *userPasswordData = [[NSString stringWithFormat:#"%#:%#", userName, password] dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:#"Basic %#", base64EncodedCredential];
NSURLSessionConfiguration *sessionConfig=[NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders=#{#"Authorization":authString};
self.session=[NSURLSession sessionWithConfiguration:sessionConfig];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSMutableDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"%#", jsonObject);
handler([jsonObject valueForKeyPath:#"name"]);
}];
[dataTask resume];
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
My Code for NSURLConnection with sendSynchronousRequest works fine but how can i change it to an async request? i tried a lot but nothing would work.
if the Request is empty i´ll get an empty Array with [[]] .
How can i catch it for an Alert Message?
Please help ...
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *urlString = #"http://www.xyz.at/sample.php";
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSMutableData *body = [NSMutableData data];
NSString *postWerte = [NSString stringWithFormat:#"id=%#", self.textfeld.text];
[body appendData:[postWerte dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSError *error = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
NSLog(#"Error: %#", error.description);
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
const char *convert = [returnString UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSMutableArray *meinErgebnis = [responseString JSONValue];
NSString *cycle = #"";
NSString *kopfdaten = [NSString stringWithFormat:#"Sendungsart: %#\r\nGewicht: %# kg\r\n\r\n", [[meinErgebnis objectAtIndex:0] objectForKey:#"ParcelTypeDescription"], [[meinErgebnis objectAtIndex:0] objectForKey:#"Weight"]];
cycle = [cycle stringByAppendingString:kopfdaten];
for(int i = 1; i < meinErgebnis.count; i++)
{
NSString *myValue = [NSString stringWithFormat:#"%# PLZ: %#\r\nStatus: %#\r\n\r\n",
[[meinErgebnis objectAtIndex:i] objectForKey:#"EventTimestamp"],
[[meinErgebnis objectAtIndex:i] objectForKey:#"EventPostalCode"],
[[meinErgebnis objectAtIndex:i] objectForKey:#"ParcelEventReasonDescription"]];
cycle = [cycle stringByAppendingString:myValue];
}
self.ergebnis.text = [NSString stringWithFormat:#"%#", cycle];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self.textfeld resignFirstResponder];
You could:
create an NSOperationQueue, and
call sendAsynchronousRequest, placing all of your NSData processing code inside the completion block.
Thus, instead of:
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// now process resulting `data`
Use:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// now process resulting `data`
}];
Alternatively, you could implement the NSURLConnectionDataDelegate methods. For more information on that, see the Using NSURLConnection section of the URL Loading System Programming Guide.
You say "if the request is empty": I assume you mean "if the data returned is empty". And you say it is [[]]. If that's really what you're getting, it sounds like an array with one item (which itself, is an empty array). Or is it [] (which is an empty array)? Or is it nil?
I'm going to assume that the data returned was [], an empty array.
I'd also suggest you consider using NSJSONSerialization, the built in JSON parser, but obviously you can use JSONValue if you really want.
Finally, your implementation is skipping the first entry (NSArray uses a zero-based index). I'm assuming that was unintentional.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"%s: sendAsynchronousRequest error: %#", __FUNCTION__, error);
return;
}
NSError *parseError;
NSArray *meinErgebnis = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (parseError) {
NSLog(#"%s: JSONObjectWithData error: %#", __FUNCTION__, parseError);
return;
}
if ([meinErgebnis count] == 0) {
NSLog(#"%s: meinErgebnis empty", __FUNCTION__);
return;
}
for (NSDictionary *dictionary in meinErgebnis)
{
// now process each dictionary entry in meinErgebnis
}
// etc.
}];
I have made this so far. It's code that will make a json String request with an http Header. When i run this code i get no errors. But i get a Expression result unused warning. I should get a response from the web service after sending this http header.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *nid = #"";
NSString *vocab = #"";
NSString *inturl = #"testoverview";
NSString *mail = #"chh#fbr.dk";
NSString *md5pw = #"4d57e7ef1b7c3f431aca424764e9d786";
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
nid, #"nid",
vocab, #"vocab",
inturl, #"inturl",
mail, #"mail",
md5pw, #"md5pw",nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self]; <-- this line triggers the warning: "Expression result unused"
NSLog(#"jsonString %#", jsonString);
}
Can anybody clarify 2 things for me:
Does this trigger a response as soon as the request to the web service?
If yes, how do i print this result out?
You need to assign the result to a variable like
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:...
for later use (e.g. [con cancel];)
Then you should at least implement the delegate method connection:didFailWithError:. In the class reference I don't see the connection:didFinishLoading... anymore. Can you use the sendSynchronousRequest:returningResponse:error: instead, then you'll have the result, be it positive or negative.
This is how I retrieved the data (this version is without ARC):
- (void) connection :(NSURLConnection *)conn didReceiveData :(NSData *)data {
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self checkAutoMailReply:msg];
[msg release];
}
msg contains the pure response data, no header or such.