AFNetworking 3.0 GET request save into class in iOS - ios

After searching the internet for how to use AFNetworking 3.0 to save the response object inside a custom class, all that I found is the basic usage of AFNetworking library with GET requests such as GET request using AFNetworking and saving response and AFNetworking send array in JSON parameters of GET request.
Code:
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
listOfEventsObjects = [#[] mutableCopy];
self.tableView.delegate = self;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:#"http://api.com.getevents.php" parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSArray *h = [responseObject objectForKey:#"events"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:h options:0 error:&error];
NSArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
for (int i = 0 ; i < [json count]; i++) {
geeksEvent *h1 = [geeksEvent new];
//h1.eventId = [];
//h1.eventId = [[json valueForKey:#"eventId"] intValue];
//NSLog(#"json data is: %#",h1);
}
// events = [responseObject objectForKey:#"events"];
if ([responseObject isKindOfClass:[NSArray class]]) {
// NSArray *responseArray = responseObject;
NSLog(#"array");
/* do something with responseArray */
} else if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSLog(#"dictionary");
NSDictionary *responseDict = responseObject;
// NSDictionary *responseDict = responseObject;
/* do something with responseDict */
}
// AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
//
// responseSerializer = [AFJSONResponseSerializer serializer];
// responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json; charset=UTF-8", nil];
//
// // NSArray *data = (responseObject *) NSArray;
// NSError *error;
// NSData *data = (NSData *) responseObject;
// // NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:errno error:&error];
//
//
// NSLog(#"JSon arrays is: %#",data);
//NSDictionary *jsonDict = (NSDictionary *) responseObject;
//
// NSLog(#"%lu",(unsigned long)events.count);
//
// for (int i = 0; i < [events count]; i ++) {
//
// geeksEvent *event = [events objectAtIndex:i];
//
//
// NSLog(#"event %d is %#",i,event);
//
//
// #try {
//
// event.eventId = [[events valueForKey:#"eventId"]intValue];
//
// event.eventTitle = [[events valueForKey:#"eventTitle"] componentsJoinedByString:#""];
//
// event.eventShortDiscription = [[event valueForKey:#"eventShortDesc"] componentsJoinedByString:#""];
// event.eventDescription = [[event valueForKey:#"eventDescription"] componentsJoinedByString:#""];
//
// event.eventDate = [events valueForKey:#"eventDate"];
// event.eventTime = [events valueForKey:#"eventTime"];
// event.eventUrl = [events valueForKey:#"eventUrl"];
//
// [listOfEventsObjects addObject:event];
//
// } #catch (NSException *exception) {
//
// NSLog(#"%#",exception);
//
// } #finally {
//
// }
//
// }
[self.tableView reloadData];
I cannot figure out how to save the response object into custom class.
geeksEvent ## custom class:
.h
#import <Foundation/Foundation.h>
#interface GeeksLocations : NSObject
#property (nonatomic) int geeksBranchId;
#property(nonatomic) double *geeksLongtitude;
#property (nonatomic) double *geeksLatitude;
#property (nonatomic,strong) NSString *geeksAddress;
#property (nonatomic,strong) NSString *geeksMobile;
#property (nonatomic,strong) NSString *geeksTel;
#property (nonatomic,strong) NSString *geeksOpenDays;
#property (nonatomic,strong) NSDate *geeksOpenTime;
#end
.m
#import "GeeksLocations.h"
#implementation GeeksLocations
#synthesize geeksBranchId;
#synthesize geeksLongtitude;
#synthesize geeksLatitude;
#synthesize geeksMobile;
#synthesize geeksTel;
#synthesize geeksAddress;
#synthesize geeksOpenDays;
#synthesize geeksOpenTime;
#end
Response
{"success":1,"events":[{"eventId":"1","eventTitle":"Open Wings Tuesday","eventShortDesc":"we are offering open wings all the day","eventDiscription":null,"eventDate":"2016-05-22","eventTime":"12:49:00","eventUrl":"http://www.code-bee.net/geeks/images/cover-7.jpg"},{"eventId":"2","eventTitle":"Testing","eventShortDesc":"Testing","eventDiscription":null,"eventDate":"2016-05-22","eventTime":"12:49:00","eventUrl":"http://www.code-bee.net/geeks/images/cover-8.jpg"}]

Add all events to an array, you will then have an array of dictionaries. Also make a new array which will hold your new instances.
Now:
for (NSDictionary *dictionary in myArrayContainingAllEvents){
GeeksLocation *location = [GeeksLocation alloc] initWithDictionary:dictionary];
[newArrayForInstances addObject: location];
}
In the GeeksLocation class add the following initializer:
-(instanceType)initWithDictionary: (NSDictionary *) dictionary{
self = [super init];
if(self){
self.geeksAddress = [dictionary objectForKey:address];
self..... = [dictionary objectForKey:.......];
}
return self;
}
Hope this helps

Related

AFnetworking 3 or 4 GET ResponseObject how to have responseString and ResponseData

Hello I would like to know how it's possible to have responseString and responseObject with the new version of AFNetworking.
When I made GET operation I have success response with NSURLSessionDataTask and id responseData.
And I would like to have responseString and responseObject.
Thanks for your help.
there is my code not the full code but it's like that
void(^wsFailure)(NSURLSessionDataTask *, NSError *) = ^(NSURLSessionDataTask *failedOperation, NSError *error) {
NSLog(#"failed %#",failedOperation);
[self failedWithOperation:failedOperation error:error];
};
void (^wsSuccess)(NSURLSessionDataTask *, id) = ^(NSURLSessionDataTask * _Nonnull succeedOperation, id _Nullable responseObject) {
NSLog(#"responseData: %#", responseObject);
NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"responseData: %#", str);
}}
AFHTTPResponseSerializer *responseSerializer = [self responseSerializerFromResponseType];
AFHTTPRequestSerializer *requestSerializer = [self requestSerializerFromRequestType];
operationManager.requestSerializer = requestSerializer;
operationManager.responseSerializer = responseSerializer;
- (AFHTTPResponseSerializer *)responseSerializerFromResponseType{
if ([self.request.parameters[#"responseType"] isEqualToString:#"xml"]) {
return [AFXMLParserResponseSerializer serializer];
}
else if ([self.request.parameters[#"responseType"] isEqualToString:#"html"]) {
return [AFHTTPResponseSerializer serializer];
}}
Quickly done, I implemented my own ResponseSerializer, which is just a way to encapsulate a AFNetworkingSerializer (~AFHTTPResponseSerializer which is the superclass of the other ones, and respects the AFURLResponseSerialization protocol) which will return a custom serialized object, which will have the 2 properties you want in addition to the NSDictionary/NSArray serialized object: a NSData and a NSString.
.h
#interface CustomResponseSerializer : NSObject <AFURLResponseSerialization>
-(id)initWithResponseSerializer:(id<AFURLResponseSerialization>)serializer;
#end
.m
#interface CustomResponseSerializer()
#property (nonatomic, strong) id<AFURLResponseSerialization> serializer;
#end
#implementation CustomResponseSerializer
-(id)initWithResponseSerializer:(id<AFURLResponseSerialization>)serializer {
self = [super init];
if (self)
{
_serializer = serializer;
}
return self;
}
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response data:(nullable NSData *)data error:(NSError * _Nullable __autoreleasing * _Nullable)error {
id serialized = nil;
if ([_serializer respondsToSelector:#selector(responseObjectForResponse:data:error:)]) {
NSError *serializationError = nil;
serialized = [_serializer responseObjectForResponse:response data:data error:&serializationError];
}
//You could put NSError *serializationError = nil; before, and set it into the `CustomSerializedObject` `error` property, I didn't check more about AFNetworking and how they handle a parsing error
return [[CustomSerializedObject alloc] initWithData:data
string:[[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding]
object:serialized];
}
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
[coder encodeObject:self.serializer forKey:NSStringFromSelector(#selector(serializer))];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
self = [self init];
if (!self) {
return nil;
}
self.serializer = [coder decodeObjectForKey:NSStringFromSelector(#selector(serializer))];
return self;
}
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
CustomResponseSerializer *serializer = [[CustomResponseSerializer allocWithZone:zone] init];
serializer.serializer = [self.serializer copyWithZone:zone];
return serializer;
}
#end
And the object:
#interface CustomSerializedObject: NSObject
#property (nonatomic, strong) NSData *rawData;
#property (nonatomic, strong) NSString *string;
#property (nonatomic, strong) id object;
#property (nonatomic, strong) NSError *error; //If needed
-(id)initWithData:(NSData *)data string:(NSString *)string object:(id)object;
#end
#implementation CustomSerializedObject
-(id)initWithData:(NSData *)data string:(NSString *)string object:(id)object {
self = [super init];
if (self)
{
_rawData = data;
_string = string;
_object = object;
}
return self;
}
#end
How to use:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"https://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
CustomResponseSerializer *responseSerializer = [[CustomResponseSerializer alloc] initWithResponseSerializer:[AFJSONResponseSerializer serializer]];
[manager setResponseSerializer: responseSerializer];
NSURLSessionDataTask *task = [manager dataTaskWithRequest:request
uploadProgress:nil
downloadProgress:nil
completionHandler:^(NSURLResponse * _Nonnull response, CustomSerializedObject * _Nullable responseObject, NSError * _Nullable error) {
NSLog(#"Response: %#", response);
NSLog(#"ResponseObject data: %#", responseObject.rawData); //If you want hex string ouptut see https://stackoverflow.com/questions/1305225/best-way-to-serialize-an-nsdata-into-a-hexadeximal-string
NSLog(#"ResponseObject str: %#", responseObject.string);
NSLog(#"ResponseObject object: %#", responseObject.object);
NSLog(#"error: %#", error);
}];
[task resume];

Instance of ViewController returns nil

I have the instance of HomeViewController as follows. I am trying to access its properties, which hold dataset. However, whenever I check in the other class -GlobalFunctions all of the HomeViewController properties are nil.
HomeViewController.h
#property (nonatomic, strong) NSMutableArray *pTempElements;
+(HomeViewController*) homeDataInstance;
HomeViewController.m
+(HomeViewController*) homeDataInstance {
static HomeViewController *dataInstance;
#synchronized(self) {
if(!dataInstance){
dataInstance = [[HomeViewController alloc] init];
}
}
return dataInstance;
}
-(void)loadFromURL {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Settings" ofType:#"plist"];
NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:path];
NSString *PRODUCT_ALL_URL = [settings objectForKey: #"PRODUCT_ALL_URL"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:PRODUCT_ALL_URL parameters:nil progress: nil success:^(NSURLSessionTask * _Nonnull operation, id responseObject) {
if(responseObject != NULL) {
ProductData *dicItem = [[ProductData alloc]init];
for ( id jsonItem in responseObject)
{
dicItem = [[ProductData alloc]initWithDictionary:jsonItem];
[self.pElements addObject:dicItem];
}
self.pTempElements = pElements;
[self.productCollectionView reloadData];
}
} failure:^(NSURLSessionTask * _Nullable operation, NSError * _Nonnull error) {
}];
}
GlobalFunctions.m
HomeViewController *restaurantData = [HomeViewController homeDataInstance];
// the following is nil
NSLog(#"%#", restaurantData.pTempElements);
restaurantData is all nil as follows in the GlobalFunctions class.
From the code snippet and screenshot you have shared, we can clearly see that your instance is successfully created.
The property values are showing nil because you have not assigned any values to them. Try assigning initial values to those properties.
For UI related properties either you should map them in your .xib or .storyboard file so that they are initialised with some value or initialize them in your code somewhere before using them.
e.g In your case: productCollectionView and categoryCollectionView
Similarly incase of other properties.
Hope my answer helps!
your problem is with singleton object. try this class method:
+(instancetype)sharedInstance{
static storeViewController *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[storeViewController alloc] init];
});
return sharedInstance;
}
Try like this!
#import "WebService.h"
static WebService *webService;
#implementation WebService
+(WebService *)sharedWebService{
if(!webService){
webService = [[WebService alloc] init];
}
return webService;
}
In .h file
#import <Foundation/Foundation.h>
#interface WebService : NSObject
+(WebService *)sharedWebService;
#property (nonatomic, strong) NSMutableArray *pTempElements;
Try this funtion using block
-(void)loadFromURLWithCallback:(void(^)(NSArray *pTempElements))callback {
// add this condition if your dont need to refresh data
if (self.pElements) {
callback(self.pElements)
[self.productCollectionView reloadData];
return;
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"Settings" ofType:#"plist"];
NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:path];
NSString *PRODUCT_ALL_URL = [settings objectForKey: #"PRODUCT_ALL_URL"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:PRODUCT_ALL_URL parameters:nil progress: nil success:^(NSURLSessionTask * _Nonnull operation, id responseObject) {
if(responseObject != NULL) {
ProductData *dicItem = [[ProductData alloc]init];
for ( id jsonItem in responseObject)
{
dicItem = [[ProductData alloc]initWithDictionary:jsonItem];
[self.pElements addObject:dicItem];
}
self.pTempElements = pElements;
[self.productCollectionView reloadData];
callback(elf.pTempElements)
}
} failure:^(NSURLSessionTask * _Nullable operation, NSError * _Nonnull error) {
callback(nil);
}];
}
calling of method
[self loadFromURLWithCallback:^(NSArray *pTempElements) {
}];

client server json response

I need to display particular object for key(currency) using post method after getting response from web.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController{
NSMutableData *mutableData;
NSMutableString *arr;
#define URL #"website"
// change this URL
#define NO_CONNECTION #"No Connection"
#define NO_VALUES #"Please enter parameter values"
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(IBAction)sendDataUsingPost:(id)sender{
[self sendDataToServer :#"POST"];
}
-(IBAction)sendDataUsingGet:(id)sender{
[self sendDataToServer : #"GET"];
}
-(void) sendDataToServer : (NSString *) method{
NSString *Branchid=#"3";
serverResponse.text = #"Getting response from server...";
NSURL *url = nil;
NSMutableURLRequest *request = nil;
if([method isEqualToString:#"GET"]){
NSString *getURL = [NSString stringWithFormat:#"%#?branch_id=%#", URL, Branchid];
url = [NSURL URLWithString: getURL];
request = [NSMutableURLRequest requestWithURL:url];
NSLog(#"%#",getURL);
}else{ // POST
NSString *parameter = [NSString stringWithFormat:#"branch_id=%#",Branchid];
NSData *parameterData = [parameter dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: URL];
NSLog(#"%#", parameterData);
request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:parameterData];
arr= [NSMutableString stringWithUTF8String:[parameterData bytes]];
NSLog(#"responseData: %#", arr);
//NSLog(#"%#",[[arr valueForKey:#"BranchByList"]objectForKey:#"currency"]);
}
[request setHTTPMethod:method];
[request addValue: #"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//NSLog(#"%#",[connection valueForKeyPath:#"BranchByList.currency"]);
if( connection )
{
mutableData = [NSMutableData new];
//NSLog(#"%#",[connection valueForKeyPath:#"BranchByList.currency"]);
}
}
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response
{
[mutableData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
serverResponse.text = NO_CONNECTION;
return;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableString *responseStringWithEncoded = [[NSMutableString alloc] initWithData: mutableData encoding:NSUTF8StringEncoding];
//NSLog(#"Response from Server : %#", responseStringWithEncoded);
NSLog(#"%#",responseStringWithEncoded );
NSLog(#"%#",[responseStringWithEncoded valueForKeyPath:#"BranchByList.currency"] );
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[responseStringWithEncoded dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
serverResponse.attributedText = attrStr;
// NSLog(#"%#",attrStr);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
i got response branch_id=3 but i want to show to "currency" but i tried lot but failure.
my response like this I need to display only currency.....
Response from Server :
{"BranchByList":
[
{"id":"342","flag_image":"http:\/\/demo.techzarinfo.com\/newant‌​ara\/images\/flags\/USD.png","units":"1","code":"USD B","currency":"US DOLLAR BIG","buy":"4.36","sell":"4.395","updated":"2016-04-11 03:24:24"
},
{"id":"342","flag_image":"http:\/\/demo.techzarinfo.com\/newantara\/i‌​mages\/flags\/USD.png","units":"1","code":"USD B","currency":"US DOLLAR BIG","buy":"4.36","sell":"4.395","updated":"2016-04-11 03:24:24"
}
]};
Your response structure is:
-Dictionary
--Array
---Dictionary Objects
You need to convert your Data into NSDictionary to parse it.
Following code will do that for you:
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData: mutableData
options:kNilOptions
error:&error]; //Now we got top level dictionary
NSArray* responseArray = [json objectForKey:#"BranchByList"]; //Now we got mid level response array
//Get Embeded objects from response Array:
NSDictionary *priceDic = [responseArray objectAtIndex:0]; //Getting first object since you arent telling what the second object is for
NSString *buyingPrice = [priceDic objectForKey: #"buy"]; //Buying price
NSString *sellingPrice = [priceDic objectForKey:#"sell"]; //Selling price
NSString *currency = [priceDic objectForKey:#"currency"]; //Currency
Though this is only sticking to the point and getting the job done.
Proper way to get the job done would be to create a model class for response. Create a class inherited from NSObject and use it as model for this response. Add a initWithDic: method to that class, Pass it your response dic as parameter and delegate all this dictionary parsing to that method.
Also, NSURLConnection is deprecated since iOS 9.0. You should use NSURLSession instead.
Try This May be it will help you:-
NSString *str=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"str : %#",str);
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
NSMArray *array1 = [dict6 objectForKey:#"BranchByList"];
NSLog(#"DICT : %#",array1);
NSDictionary *Dict3 = [array1 objectAtIndex:0];
NSString *Str1 = [dict3 objectForKey:#"currency"];
NSLog(#"Str1 : %#",Str1);
- (id)cleanJsonToObject:(id)data
{
NSError* error;
if (data == (id)[NSNull null])
{
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]])
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
} else
{
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = (int)array.count-1; i >= 0; i--)
{
id a = array[i];
if (a == (id)[NSNull null])
{
[array removeObjectAtIndex:i];
} else
{
array[i] = [self cleanJsonToObject:a];
}
}
return array;
} else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys])
{
id d = dictionary[key];
if (d == (id)[NSNull null])
{
dictionary[key] = #"";
} else
{
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
} else
{
return jsonObject;
}
}

JSON parsing with AFNetworking and model Class

I am bit confused in fetching data and displaying data from json into my App using Model.
I am having this kind of json data :
{
result
[
{
key : value
key : value
key : value
}
{
key : value
key : value
key : value
}
]
}
I am trying this kind of code:
json = [[NSMutableArray alloc]init];
NSError *writeError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&writeError];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&writeError];
json = dic[#"Result"];
int i;
for (i = 0; i <= json.count; i++)
{
NSMutableArray *array = json[i];
[json enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop)
{
// Dim = [[DimEntityFull alloc]initWithJSONDictionary:obj];
saveSearch = [[SaveSearchMaster alloc]initWithJSONDictionary:obj];
} ];
}
I am using "AFNetworking" and I am trying to fetch data and store into model class and then display to custom cell labels.
How can I get it.
Thank You.
In your view controller
- (void)viewDidLoad
{
[super viewDidLoad];
[self getUsersList];
}
-(void)getUsersList
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
[manager POST:[NSString stringWithFormat:#"http://www.yourdomainname.com/getUserList"] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
//we will add Modal class objects of users in this array
usersArray=[[NSMutableArray alloc]init];
//getting result dictionary from response
NSDictionary *resultDictinary = [responseObject objectForKey:#"result"];
for (NSDictionary *userDictionary in resultDictinary)
{
//allocating new user from the dictionary
User *newUSer=[[User alloc]initWithDictionary:userDictionary];
[usersArray addObject:newUSer];
}
//in users array, you have objects of User class
//reload your tableview data
[self.TableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Now Create New file Called 'User'
in User.h
#interface User : NSObject
{
NSString *userID;
NSString *firstName;
NSString *lastName;
}
#property (nonatomic, retain)NSString *userID;
#property (nonatomic, retain)NSString *firstName;
#property (nonatomic, retain)NSString *lastName;
-(id)initWithDictionary:(NSDictionary *)sourceDictionary;
#end
in User.m
#import "User.h"
#implementation User
#synthesize userID,firstName,lastName;
-(id)initWithDictionary:(NSDictionary *)sourceDictionary
{
self = [super init];
if (self != nil)
{
self.firstName=[sourceDictionary valueForKey:#"firstName"];
self.lastName=[sourceDictionary valueForKey:#"lastName"];
self.userID=[sourceDictionary valueForKey:#"userID"];
}
return self;
}
#end
in your numberOfRowsInSectionmethod
return usersArray.count;
in your cellForRowAtIndexPath method
User *user=(User *)[usersArray objectAtIndex:indexPath.row];
yourLabel.text=user.firstName;

Why is there a long delay between json data being retrieved and viewcontroller being displayed

I have a problem with a long delay between a JSON data retrieval and the starting of a UITableViewController.
The method below uses a hardcoded query that is called from the UITableViewControllers initializer, and retrieves and displays the data within 2 seconds.
- (void)productsQuery
{
NSString *requestString = #"http://192.168.2.10/testQueries.php?Product_Description=tea";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSArray *returnedItems =
[NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
for (int i = 0; i < [returnedItems count]; i++) {
NSDictionary *item = [returnedItems objectAtIndex:i];
NSNumber *nBay = [item objectForKey:#"Bay_Number"];
NSNumber *nShelf = [item objectForKey:#"Shelf_Number"];
NSNumber *coordX = [item objectForKey:#"CoordinateX"];
NSNumber *coordY = [item objectForKey:#"CoordinateY"];
TNWProduct *product =[[TNWProduct alloc]
initWithProductDescription:[item objectForKey:#"Product_Description"]
aisleNumber:[item objectForKey:#"Aisle_Number"]
bay:[nBay intValue]
shelf:[nShelf intValue]
nonAisleLocation:[item objectForKey:#"Location_Description"]
coordinateX:[coordX intValue]
coordinateY:[coordY intValue]];
[self.productList addObject:product];
}
NSLog(#"%#", self.productList);
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[dataTask resume];
}
The method was then adapted and moved to a UIView controller so that the query could be input by the user.
The JSON data is still retrieved and added to the NSMutableArray _productList in 2 seconds, as it shows in the console from the NSLog call, but then appears to do nothing for 5-15 seconds until starting the ProductListViewController.
#interface TNWSearchViewController () <UITextFieldDelegate>
#property (weak, nonatomic) NSString *userQuery;
#property (weak, nonatomic) IBOutlet UIToolbar *toolbar;
#property (weak, nonatomic) IBOutlet UITextView *informationMessages;
#property (nonatomic) NSURLSession *session;
#property (nonatomic, strong) NSMutableArray *productList;
#property (nonatomic, strong) NSArray *returnedItems;
#end
#implementation TNWSearchViewController
.
.
.
.
- (void)productQuery:(NSString *)query
{
if ([_productList count] > 0 ) {
[_productList removeAllObjects];
}
NSMutableString *requestString = [#"http://192.168.2.10/testQueries.php?Product_Description=" mutableCopy];
[requestString appendString:query];
NSString *escapedRequestString = [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", escapedRequestString);
NSURL *url = [NSURL URLWithString:escapedRequestString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
_returnedItems =
[NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
//NSLog(#"Returned items = %#", _returnedItems);
for (int i = 0; i < [_returnedItems count]; i++) {
NSDictionary *item = [_returnedItems objectAtIndex:i];
//NSLog(#"Item = %#", item);
NSNumber *nBay = [item objectForKey:#"Bay_Number"];
NSNumber *nShelf = [item objectForKey:#"Shelf_Number"];
NSNumber *coordX = [item objectForKey:#"CoordinateX"];
NSNumber *coordY = [item objectForKey:#"CoordinateY"];
TNWProduct *product =[[TNWProduct alloc]
initWithProductDescription:[item objectForKey:#"Product_Description"]
aisleNumber:[item objectForKey:#"Aisle_Number"]
bay:[nBay intValue]
shelf:[nShelf intValue]
nonAisleLocation:[item objectForKey:#"Location_Description"]
coordinateX:[coordX intValue]
coordinateY:[coordY intValue]];
NSLog(#"%#", product);
[_productList addObject:product];
}
NSLog(#"Product list = %#", self.productList);
if ( [_productList count] > 0 ) {
TNWProductListViewController *plvc =
[[TNWProductListViewController alloc] initWithStyle:UITableViewStylePlain];
plvc.productList = [self.productList mutableCopy];
[self.navigationController pushViewController:plvc animated:YES];
} else {
_informationMessages.text = #"No matches found";
}
}];
[dataTask resume];
}
Moving the code blocks from the for loop and the if/else statement below [dataTask resume] result in the app loading the UITableView as expected, but the data from _returnedItems is no longer accessible.
Assistance appreciated.
for (int i = 0; i < [_returnedItems count]; i++) {
.
.
.
} else {
_informationMessages.text = #"No matches found";
}
Moving the creation and call of the ViewController to the dispatch_async block as below fixed the issue.
Thanks Fonix.
dispatch_async(dispatch_get_main_queue(), ^{
if ( [[[TNWProductList productsStore] allProducts] count] > 0 ) {
TNWProductListViewController *plvc =
[[TNWProductListViewController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:plvc animated:YES];
} else {
_informationMessages.text = #"No matches found";
}

Resources