how to turn AFNetworking GET request to soap web service request? - ios

The project I'm working on have using AFHTTPRequestOperation to retrieve data from the web service using the down below method but now the company want to change this method and make it a soap request can i modify the current code the project have more than 100 class and so advanced and I'm still beginner can any one help me 2 modify the code to use the soap request and accept the soap message and requests with a simple edit or something plz ,this is the code that exist :
NSString *path = [NSString stringWithFormat:#"*********?mobile=%#&email=%#",mobile,email];
[self.operationManager GET:path parameters:nil success:^void(AFHTTPRequestOperation * operation, id responseObject) {
} failure:^void(AFHTTPRequestOperation * operation, NSError * error) {
}];
I have tried to follow the answer on (How can you use AFNetworking or STHTTPRequest to make a request of a SOAP web service?) but in the part where i call it in the other class that i need to use it in this error showed (No known class method for selector 'dictionaryForNSXMLParser:'). i found the problem i didn't call
NSDictionary *dict = [XMLReader dictionaryForNSXMLParser:parser error:nil];
but he did the same ,he used
NSDictionary *dict = [XMLReader dictionaryForNSXMLParser:parser];but while running the app it crashed in XMLReader.m class on this line
self.errorPointer = *error;
XMLReader *reader = [[XMLReader alloc] initWithError:error];
ther error is EC_Bad_Access.

Related

Snapchat SnapKit Login on iOS 'fetchUserDataWithQuery' always fails with SCOAuth2ClientErrorDomain 403

I'm trying out Snpachat's SnapKit login api, and I've setup my project as described in the documentation/guide. I've allowed the use of all the scopes, i.e. external id, display name and bitmoji in the dashboard and added the required fields in the .plist of my app.
The login and authentication proceed normal and return successfully, but when I try to fetch user data, that request fails every time with the SCOAuth2ClientErrorDomain error.
I'm using the snippet provided within the guide (although that code has a typo and doesn't build as is so I doubt in the validity of that code):
[SCSDKLoginClient loginFromViewController:self completion:^(BOOL success, NSError * _Nullable error) {
NSString *graphQLQuery = [#"{me{displayName, bitmoji{avatar}, externalId}}" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSDictionary *variables = #{#"page": #"bitmoji"};
[SCSDKLoginClient fetchUserDataWithQuery:graphQLQuery
variables:variables
success:^(NSDictionary *resources) {
NSDictionary *data = resources[#"data"];
NSDictionary *me = data[#"me"];
NSString *displayName = me[#"displayName"];
NSDictionary *bitmoji = me[#"bitmoji"];
NSString *bitmojiAvatarUrl = bitmoji[#"avatar"];
} failure:^(NSError * error, BOOL isUserLoggedOut) {
// handle error as appropriate
}];
}];
I've even tried configurin my app without the bitmoji and tried the request without it, it still fails.
[SCSDKLoginClient loginFromViewController:self completion:^(BOOL success, NSError * _Nullable error) {
NSString *graphQLQuery = [#"{me{displayName, externalId}}" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[SCSDKLoginClient fetchUserDataWithQuery:graphQLQuery
variables:nil
success:^(NSDictionary *resources) {
NSDictionary *data = resources[#"data"];
NSDictionary *me = data[#"me"];
NSString *displayName = me[#"displayName"];
} failure:^(NSError * error, BOOL isUserLoggedOut) {
// handle error as appropriate
}];
}];
Anyone have any idea what I might be doing wrong?
Ok, I got it working.
First of all, I re-added the user I was testing with to the demo users in the developer portal. After that, the SCOAuth2ClientErrorDomain error was gone and I was getting the success callback.
But, the response data was an error in the query string. The problem is that they're using a deprecated method stringByAddingPercentEscapesUsingEncoding. I'm not sure what the exact problem is but I've just sent the raw string as a query and I got a valid response.
UPDATE: I think encoding here is not needed. It doesn't make sense for the user of the api to encode the query. The api should handle it internally, and I think that is what might be happening here. So you probably get a double encoded query which then isn't encoded properly and is invalid. I tested encoding with non-deprecated methods for URL queries and it still didn't work. A raw query string is the way to go.

Facebook iOS SDK Graph Api Public Page Feed

Can anyone point me in the direction of a thorough tutorial on how to get a public page's post feed? I'd like to really understand what's going on rather than copying and pasting. Even still I haven't found anything I could copy and paste that works. I've managed to make some headway with the following code but the resulting json is not pretty and making extracting image urls virtually impossible (it doesn't require an appId, which I do actually have entered into the plist anyway). I'd rather be using FBRequestConnection. It doesn't seem like it'd be too challenging but I'm unfamiliar with the sdk and the documentation on this seems a bit wanting.
NSString *pageId = #"##################";
NSString *urlString = [NSString stringWithFormat:#"https://www.facebook.com/feeds/page.php?format=json&id=%#", pageId];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.tags = [[NSArray alloc] initWithObjects:#"#meditation", nil];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
QuoteItem *menuItem = [[QuoteItem alloc] init];
if (data.length > 0 && connectionError == nil)
{
NSDictionary *fbFeed = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSMutableArray *entries = [fbFeed objectForKey:#"entries"];
I was trying to keep it brief, but to further clarify I've tried using the instruction given by facebook here (https://developers.facebook.com/docs/graph-api/reference/v2.2/page/feed#read) by doing the following:
[FBRequestConnection startWithGraphPath:#"/###########9055/feed"
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
/* handle the result
}];
And I get this runtime error: "FBSDKLog: Error for request to endpoint '/164313873599055/feed': An open FBSession must be specified for calls to this endpoint." So I looked up FBSession (which is not mentioned at the destination of the aforementioned link) and tried to remedy the situation but I'm not sure how to set permissions. What I have a tried led to a prompt for the user to allow access to their feed, which is not wanted. I just want the user to see this darn public page feed without having to log in, without seeing anything facebook related in the app.
Which is why I was looking for a thorough tutorial to step a person through the above in one place. These tutorials, I know, do exist for other aspects of iOS development and I was wondering if there was something similar for this case WITHOUT having to write an essay.
I doubt that you had a look in the Facebook docs, because there it's all outlined:
https://developers.facebook.com/docs/graph-api/reference/v2.2/page/feed/#read
The call is
/{page_id}/feed
where {page_id} is the id of the Page you're looking for. You'll need to add an Access Token to the call.

AFNetworking Error - 'Invalid type in JSON write (NSConcreteData)' - when uploading audio file

I am attempting to use AFNetworking to upload an audio file to Cloudinary through a POST call. I have been using AFNetworking to send POST calls to my own server with ease but this is the first time I have tried sending an NSData object through AFNetworking which is where I think the problem lies and am not exactly sure how I need to adjust the call to get it to work.
My Code
I need to send 4 parameters through the post call to the Cloudinary service which I place in to a dictionary....
NSData *audioFile = [[NSData alloc]initWithContentsOfURL:_audioRecorder.url];
NSMutableDictionary *myParam = [NSMutableDictionary dictionary];
[myParam setValue:#(nowTime) forKey:#"timestamp"];
[myParam setValue:audioFile forKey:#"file"];
[myParam setValue:api_key forKey:#"api_key"];
[myParam setValue:finalSignature forKey:#"signature"];
[cloudManager setUpDataCall:#"/upload" withParameters:myParam];
The setUpDataCall goes to a subclass of AFHTTPSessionManager with this code. This is the rest of the post URL if you were curious #"https://api.cloudinary.com/v1_1/karmo/raw"
- (void)setUpDataCall:(NSString *)callURL withParameters:(NSDictionary *)parameters {
[self POST:callURL parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
if ([self.delegate respondsToSelector:#selector(cloudManager:didReturnData:)]){
//Success :)
}
}failure:^(NSURLSessionDataTask *task, NSError *error) {
if ([self.delegate respondsToSelector:#selector(cloudManager:didFailWithError: )]) {
//Error :(
}
}];
}
The Error
I get this error when I try to send the file Invalid type in JSON write (NSConcreteData).
When I add an exception breakpoint it identifies this
[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
Which is in this method in the AFURLRequestSerialization.m class.
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
I have seen a few other stackoverflow questions like the one below but I am not sure if those are still relevant as the code from those posts seem to throw errors in the code as I am guessing AFNetworking has been updated since those posts.
AFNetworking Uploading a file
Any code help or examples would be greatly appreciated. Thanks a bunch for taking the time.
Have you tried the suggestions as explained in the following post's comments?
Error with NSJSONSerialization - Invalid type in JSON write (Menu)

Force app to wait for method completion (data download)

I'm working with an app that requests data from an OAuth2.0 protected server. When I use the GTM OAuth Library to retrieve data, the program continues to run while the data is being downloaded in the background. I need some sort of mechanism to either force my application to wait until the didFinishWithData selector is called,or I need a way to notify my ViewController of the download's completion, so I can then utilize the data immediately.
I've tried conditional blocks, but those aren't doing it for me. I've also tried polling the object whose data I'm interested in, but if I do that, the data never seems to download. I've heard I can somehow utilize the Notification Center to accomplish this task, so I'll look more into that while I'm waiting for replies here.
Here is basically what is going on:
-(void) getAlert{
// Define the URL of the API module we'd like to utilize.
NSURL *url = [[NSURL alloc] initWithString:#"https://access.active911.com/interface/open_api/api/alerts"];
// Constructs a an HTTP request object to send to the server in order to obtain data.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setValue:#"1" forHTTPHeaderField:#"alert_days"];
// This fetcher sends the request along with the authentication header in a recognizable manner.
GTMHTTPFetcher *fetcher = [[GTMHTTPFetcher alloc] initWithRequest:request];
// Attach the OAuth credentials for the fetcher's use.
[fetcher setAuthorizer:auth];
// Execute the operation.
[fetcher waitForCompletionWithTimeout:10];
NSLog(#"About to get alert");
[fetcher beginFetchWithDelegate:self didFinishSelector:#selector(responseHandler:finishedWithData:finishedWithError:)];
NSLog(#"got alert");
}
-(void)responseHandler:(id)valueNotUsed finishedWithData:(NSData *)data finishedWithError:(NSError *)error{
// Retrieve the server data in a usable object
// All that's being done here is conversion to an NSDictionary
// followed by the creation of subdictionaries from that dictionary
// until our final value can be picked directly out of the resulting dict
NSData *jsonData = [[NSData alloc] initWithData:data];
NSError *dictError;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:jsonData //1
options:kNilOptions
error:&dictError];
NSDictionary *token = [json objectForKeyedSubscript:#"message"];
NSArray *alerts = [token objectForKeyedSubscript:#"alerts"];
NSDictionary *alertData = alerts[0];
mapCode = [alertData objectForKeyedSubscript:#"map_code"];
NSString *city = [alertData objectForKeyedSubscript:#"city"];
NSLog(#"Map code: '%#' with city '%#' and access token %#", mapCode, city, accessToken);
}
And I need to pass the mapCode to my view controller.
Thanks for the help!
First off, please rethink about having the UI halt while you fetch results from the server. This can create an extremely bad UX for the app and only should be done if absolutely necessary.
Second, does your responseHandler method work? And do you only need mapCode in the VC that responseHandler is in?
If so, you don't even need to use Notifications. Simply do:
-(void)responseHandler:(id)valueNotUsed finishedWithData:(NSData *)data finishedWithError:(NSError *)error{
...
...
mapCode = [alertData objectForKeyedSubscript:#"map_code"];
[self updateVCWithMapCode:mapCode];
}
That will call the method after the response has been received. Passing it explicitly too so you don't need to have mapCode be a property as well.

Google Places API Autocomplete on iOS

Over the last few days I've been struggling to get Google Places autocomplete to work on my app, and no matter what I do, I always get the REQUEST_DENIED error.
I followed Google's "tutorial" for the implementation, Places API is enabled, API key has the correct bundle ID, I also tested with a Browser ID, with no success.
I am pretty sure it has something to do with the key, though. Curiously, on the Android version of the app, the service will work with the Browser Key. And on the browser, obviously, it works with that key too.
These are the two keys I experimented with:
And this is my implementation code, using AFNetworking:
NSURL *url = [NSURL URLWithString:#"https://maps.googleapis.com/maps/api/place/autocomplete/"];
NSDictionary *params = #{#"input" : [input stringByReplacingOccurrencesOfString:#" " withString:#"+"],
#"location" : [NSString stringWithFormat:#"%f,%f", searchCoordinate.latitude, searchCoordinate.longitude],
#"sensor" : #(true),
// #"language" : #"pt_BR",
// #"types" : #"(regions)",
// #"components" : #"components=country:br",
#"key" : GOOGLE_API_KEY};
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setParameterEncoding:AFFormURLParameterEncoding];
[httpClient getPath:#"json"
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *JSON = [[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil] dictionaryWithoutNulls];
if (completion) {
completion(JSON[#"predictions"]);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *errorResponse) {
NSLog(#"[HTTPClient Error]: %# for URL %#", [errorResponse localizedDescription], [[[operation request] URL] path]);
}];
I know there are some questions like this one here, but some are old, and say that Places API does not work on Android or iOS, which clearly is not the case anymore, since Google itself publishes examples on both platforms, as seen on Places API page: https://developers.google.com/places/documentation/autocomplete
A workaround I'm currently using is Apple's GeoCoding system, which works good when you type the full address, but is terrible with half-typed phrases. This is not good at all, I'd really like to use Google's API.
I got it!
The paramenter sensor should receive either #"true"or #"false", and not #(true)or #(false).
For the record, the API key used is indeed the Browser Key, and not an iOS key.
You should init httpClient with base URL #"https://maps.googleapis.com/" and get path /maps/api/place/autocomplete/json. Base URL - host only, it does not take other parts of path, so in your case you get request to URL "https://maps.googleapis.com/json".
https://maps.googleapis.com/maps/api/geocode/json?address="%#","%#"&sensor=false,yourAddress,your c

Resources