AFNetworking : Re-use Method - ios

We know that we can get return value from a normal method, for example :
-(NSString*)ASimpleFunction:(NSString*)str{
return str;
}
Calling this : [self ASimpleFunction:#"abc"] will return "abc".
If I have declared it in singleton class, so that I can use it from anywhere like:
+(NSString*)ASimpleFunction:(NSString*)str{
return str;
}
Calling it: [Singleton ASimpleFunction:#"xyz"] will return "xyz".
Hence above method, declared in Singleton class can be accessed/Re-used from anywhere by class name itself i.e. Singleton.
Similarly, I want to reuse the AFNetworking Method, I will pass NSDictionary of parameters , NSString for URL etc. But the thing is AFNetworking's Success and Failure blocks don't return values. So , I can't get reponseObject on success and error on failure in return.
Am I doing it right writing same code i.e, url, parameters, [success..]/[failure..] block again an again for each networking request?
Or is there is a good suggested architecture is available?
P.S - I have googled a lot for it but found nothing.

Here is how you can create your own helper class and use anywhere you can.
First let's create method to call AFNetworking response, success and failure:
+(void)getWebserviceWithURL:(NSString*)strUrl withParam:(NSDictionary*)dictParam withCompletion:(void(^)(NSDictionary*response))completion withFailure:(void(^)(NSDictionary*response))failure withLoadingText:(NSString*)text
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.responseSerializer = responseSerializer;
[manager GET:strUrl parameters:dictParam success:^(AFHTTPRequestOperation *operation, id responseObject) {
// [[Helper sharedInstance] dismissProgressBar];
completion(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure([NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:error, operation, nil] forKeys:[NSArray arrayWithObjects:#"error",#"operation", nil]]);
// [[Helper sharedInstance] dismissProgressBar];
}];
}
Now you can create your own method and get response, success and failure using the completion block:
- (void)WebSeries:(void(^)(bool status, NSMutableArray *seriesResponseData, NSString *compMessage))completion
{
//NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"data", nil] forKeys:[NSArray arrayWithObjects:#"iComicBookId", nil]];
NSDictionary *dict = [NSDictionary dictionaryWithObject:#"1" forKey:#"fk_iWebSeriesId"];
[Helper postWebserviceWithURL:EPISODESURL withParam:dict withCompletion:^(NSDictionary *response) {
NSLog(#"%#",response);
NSMutableArray *webSeriesData = response[#"data"];
completion(YES, webSeriesData, response[#"msg"]);
} withFailure:^(NSDictionary *response) {
} withLoadingText:#"Loading"];
}
Hope this helps!

Related

Cant parse afnetworking json response to nsdictionary

I am attempting to call an external API with the following afnetworking request code:
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
destination, #"destination",
nil];
[manager POST:baseUrl parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
completion(nil, responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
completion(error, nil);
NSLog(#"error: %#", error);
}];
When I print out the responseObject I get the following which is the json that I expect to see:
However when I attempt to access the code e.g. responseObject[#"code"] I get some strange text:
(__NSCFNumber *) $0 = 0xb00000000000fa33 (long)4003
I then tried to parse this with NSStringwithformat %ld, but that returns:
(__NSCFString *) $1 = 0x000060800005a850 #"-5764607523034170829"
Not sure what's going on here, whether the responseObject has even been parsed properly as an NSDictionary
any help would be appreciated
i'm not sure what is going on here, but I recommend to use Gloss framework for JSON Serializing/Deserializing to map JSON on objects directly.
http://harlankellaway.com/Gloss/
i'm not sure what is happening but it's strange
so i suggest you can Debug it step by step
What i suppose is that the number is a float, try
NSNumber *num = [responseObject objectForKey:#"code"];
int theValue = [num intValue];
This might help.
so what you have to do is, inside you success block,
NSDictionary *result = (NSDictionary *)responseObject;
for(NSDictionary *all in result){
int code = [all objectForKey:#"code"];
}
hope this will help to your.
note : better to use model and add those objects to a mutable array.

singleton class for webservices in ios

I'm new to iOS while I'm developing I am calling web services every where...I want like one single class for get,post,put methods...then call [self post];
[parameters:....]... that means I want to call single methods for all get services and post.. please help me...how it is..
NSURL *url = [NSURL URLWithString:#"https://example.com/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
height, #"user[height]",
weight, #"user[weight]",
nil];
[httpClient postPath:#"/myobject" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
For AFNetworking 2.0 (and also using the new NSDictionary syntax):
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"user[height]": height,
#"user[weight]": weight};
[manager POST:#"https://example.com/myobject" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
From here you can create singleton class - How to create singleton class in objective C
Then you need to create your own method with completion handler and call where you want.
Example: Post Method:
+(void)postWebserviceWithURL:(NSString*)webServiceURL withParam:(NSDictionary*)urlParameters withCompletion:(void(^)(NSDictionary*response))completion {
//Your code goes here
}
here is the related answer.You should create nsobject classes something like webservices and create the singleton instance object like this.
+(WebServices *)sharedInstance{
/* Use this to make it a singleton class */
if (sharedObj==Nil) {
sharedObj=[[WebServices alloc]init];
}
return sharedObj;
/**/
}
using this singleton instance you can call the methods what ever you required.
Eg: [[webservices sharedInstance] post];
With in the method you can use the required web services hits such as post,get and put.
use the Nsnotifiers to consume the responses from the API hits.
+ (instancetype)sharedInstance
{
static CustomClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//Override your constructor for custom initialization if you want
sharedInstance = [[CustomClass alloc] init];
});
return sharedInstance;
}
Then define your methods for CRUD actions.
simply access like
[[CustomClass sharedInstance] POST:...];
[[CustomClass sharedInstance] GET:...];

AFNetworking request returns nil

i have a request which returns information from a php web service. I'm having trouble adding this to a array which can be used in my UICollectionView. It seems like whatever i do i cant return the data. I think it is because i'm returning the array before i've added any objects. I've tried placing the NSLog several places, but without luck. What am i doing wrong?
When i place this NSLog(#"%d", imagesArray.count); beyond the request it returns 0.
ViewDidAppear:
-(void)viewDidAppear:(BOOL)animated {
imagesArray = [[NSMutableArray alloc] init];
[self getImages];
}
getImages method:
-(void)getImages {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:#"http://URL.COM" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseObject options:kNilOptions error:nil];
NSString *theTitle = [[json objectForKey:#"response"] valueForKey:#"title"];
NSString *theUrl = [[json objectForKey:#"response"] valueForKey:#"imageUrl"];
[imagesArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
theTitle, #"title",
theUrl, #"url",
nil]];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSLog(#"%d", imagesArray.count);
}
AFNetworking is Asynchronous, you have to place the log inside the success block. Otherwise the array will always be empty.
One good solution would be to pass a block to your getImages function like that
-(void) getImages:(void (^)(BOOL result))callback {
// your code here then you call callback(YES or NO) inside your success or failure block.
}
[self getImages:^(BOOL result){
if(result)
//we got the images, we can now display them etc.
}];

Changing the architecture to AFNetworking in iOS

I am new to iOS development.
I have an application which uses NSURLConnection methods for http transfers across the network. The application is using JSON classes SBJsonparser and SBJsonWriter classes for parsing the Json and Serialization protocols for coverting the objects to json and deserializing the specified dictionary into instace of objects and using Serialization properties. I have separate classes for each request to API which conforms to serializable protocol.
One of sample classes is as follows
+ (id) deserializeFromDictionary:(NSDictionary *)dictionary {
Class *obj = [super deserializeFromDictionary:dictionary];
return obj;
}
+ (NSArray *) serializableProperties {
static NSArray *properties = nil;
if (properties == nil) {
properties = [[NSArray alloc] initWithObjects:
[SerializableProperty propertyWithExternalName:#"username"
internalName:#"username" internalClass:[NSString class]],
[SerializableProperty propertyWithExternalName:#"pwd"
internalName:#"pwd" internalClass:[NSDate class]],
nil];
}
return properties;
}
- (NSDictionary *) serializeToDictionary {
NSMutableDictionary *userDictionary = [NSMutableDictionary
dictionaryWithDictionary:[super serializeToDictionary]];
return userDictionary;
}
Now I have to replace the whole architecture with AFNetworking
I have replaced the
[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
with the following AFNetworking.
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
/// validates and decodes JSON responses.
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// succes code
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failure code
}];
// 5
[operation start];
My Question is, is this ok or do I need to change the serialization of objects also? Is it possible to replace the serialization protocol with any of the AFNetworking Classes?. If YES, please let me know how to change this.
Thanks in advance.
Your can use the following code.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:urlparameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Success Code
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Failure Code
}];
You can use GET/POST depending on your requirements. Using AFNetworking you don't need to handle JSON parsing manually.

handling the Response with the AFNetworking 2

i am really new to IOS development. i want to develop an application which is dealing with some web services and display in a table view. somehow i found a 3rd party library for do the networking stuffs [AFNetworking 2]. below is my code to get the json response for any given url and parameters.
-(NSDictionary*)getWebServiceResponce:(NSString *)url :(NSDictionary *)object
{
// NSDictionary *parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"47", #"caregiverPersonId", nil];
__block NSDictionary* result=Nil;
__block NSString* person=Nil;
AFSecurityPolicy *policy = [[AFSecurityPolicy alloc] init];
[policy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager setSecurityPolicy:policy];
operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager POST:url
parameters:object
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
person = [responseObject[#"d"]objectForKey:#"PersonId"];
// [self returnedResponce:responseObject];
result = (NSDictionary *) responseObject[#"d"];
NSLog(#"RESULT: %#", result);
NSLog(#"personm: %#", person);
[operation waitUntilFinished];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error description]);
//result = [error];
}
];
return result;
}
this code works perfectly.. but my point is when i put some breakpoints to check what are the values i got for several variables, it shows null. but my log shows the entire json response.
and i want to return my response object as a dictionary. because i want to do some process with the response.. can some one help me with this ?
The problem is that result is nil when it gets returned. AFNetworking uses ObjC's awesome blocks, they get executed asynchronously. Read more about it here.
You should include a callback block in your getWebServiceResponce method. I've thrown together a bit of code but you should really read more about blocks.
-(void)webServiceResponceForURL:(NSString *)url dictionary:(NSDictionary *)object success:(void (^)(NSDictionary *responseObject))success {
// NSDictionary *parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"47", #"caregiverPersonId", nil];
__block NSDictionary* result=Nil;
__block NSString* person=Nil;
AFSecurityPolicy *policy = [[AFSecurityPolicy alloc] init];
[policy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager setSecurityPolicy:policy];
operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager POST:url
parameters:object
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
person = [responseObject[#"d"]objectForKey:#"PersonId"];
// [self returnedResponce:responseObject];
result = (NSDictionary *) responseObject[#"d"];
NSLog(#"RESULT: %#", result);
NSLog(#"personm: %#", person);
//We are executing the block as soon as we have the results.
if (success) {
success(responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error description]);
//result = [error];
}
];
}
Edit:
[self webServiceResponceForURL:#"foo://foo" dictionary:nil success:^(NSDictionary *responseObject) {
//your code here
}
[self webServiceResponceForURL:#"foo://foo" dictionary:nil success:^(NSDictionary *responseObject) {
//your code here
}
Here you will got complete responseObject in form NSDictionary. You can assign responseObject to instance variable. Now This instance Variable will be used at point time. in your case, it will passed on button event.

Resources