View is not populating data AFNetworking - ios

I am using AFNetworking, my success block works fine, but my view is always loaded first. I am not using table view for my view, there are only labels, and images that need to be refreshed. What should i do now ?
-(void)myVenusWithClubDetail :(NSString *)IDs completionHandler:(void (^)(id array))success
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *link = [NSString stringWithFormat:#"%#",KWSURLVenuDetail];
NSLog(#"%#",IDs);
NSDictionary *params = #{#"Id" : IDs};
NSLog(#"%#",link);
[manager POST:link parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
ClubDetailDC *clubDC = [[ClubDetailDC alloc] init];
clubDC.cDVenuID = [[responseObject objectForKey:#"Id"]integerValue];
clubDC.cDCatID = [[responseObject objectForKey:#"cat_id"]integerValue];
clubDC.cDName = [responseObject objectForKey:#"name"];
clubDC.cDHeadLine = [responseObject objectForKey:#"headline"];
clubDC.cDImage = [responseObject objectForKey:#"image"];
clubDC.cDLong = [responseObject objectForKey:#"long"];
clubDC.cDLat = [responseObject objectForKey:#"lat"];
clubDC.cDAddress = [responseObject objectForKey:#"address"];
clubDC.cDSummary = [responseObject objectForKey:#"summary"];
clubDC.cDStat = [responseObject objectForKey:#"stat"];
clubDC.cDUS = [responseObject objectForKey:#"us"];
clubDC.cDImage = [self loadClubDetailImages:clubDC.cDImage];
[dataArray addObject:clubDC];
success(dataArray);
if (dataArray.count == 0)
{
ALERT_VIEW(#"Please check your internet connection.");
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
ALERT_VIEW(#"Error while loading data.")
}];
}
and my venuVC.m is like this where i want to show data
-(void)reloadView
{
clubDetail = [[ClubDetailDC alloc] init];
venu_dataArray = [[NSMutableArray alloc] init];
upcomingArray = [[NSMutableArray alloc] init];
GET_DBHANDLER
// venu_dataArray = [dbHandler get_club_detail:venuID];
NSString *strVenuID = [NSString stringWithFormat:#"%d",venuID];
NSLog(#"%#",strVenuID);
[dbHandler myVenusWithClubDetail:strVenuID completionHandler:^(id array)
{
venu_dataArray = array;
// NSLog(#"%d",array.count);
}];
}
-(void)viewWillAppear:(BOOL)animated
{
[self reloadView];
for (clubDetail in venu_dataArray)
{
lblDescription.text = [ NSString stringWithFormat:#"Neighborhood:%# Information on whats happening tonight", clubDetail.cDAddress];
[imgClub setImageWithURL:[NSURL URLWithString:clubDetail.cDImage]];
}
UIFont* font_name = [UIFont fontWithName:#"Corbel" size:17];
UIFont* bold_font = [UIFont fontWithName:#"Corbel-Bold" size:17];
lbl_upcomingEvents.font = font_name;
lbl_Unighted.font = bold_font;
lblDescription.font = [UIFont fontWithName:#"Corbel" size:11];
lblCheckIn.font = [UIFont fontWithName:#"Corbel" size:13];
lblCount.font = [UIFont fontWithName:#"Corbel" size:12];
lblGoodEmotion.font = [UIFont fontWithName:#"Corbel" size:14];
lblHotEmotion.font = [UIFont fontWithName:#"Corbel" size:14];
}
My problem is that view is loaded first, then I get the data from success block. Can anyone help?
Thanks.

you can do this in two ways either you write function in in your view, code will be like this
-(void)myVenusWithClubDetail :(NSString *)IDs completionHandler:(void (^)(id array))success
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *link = [NSString stringWithFormat:#"%#",KWSURLVenuDetail];
NSLog(#"%#",IDs);
NSDictionary *params = #{#"Id" : IDs};
NSLog(#"%#",link);
[manager POST:link parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
ClubDetailDC *clubDC = [[ClubDetailDC alloc] init];
clubDC.cDVenuID = [[responseObject objectForKey:#"Id"]integerValue];
clubDC.cDCatID = [[responseObject objectForKey:#"cat_id"]integerValue];
clubDC.cDName = [responseObject objectForKey:#"name"];
clubDC.cDHeadLine = [responseObject objectForKey:#"headline"];
clubDC.cDImage = [responseObject objectForKey:#"image"];
clubDC.cDLong = [responseObject objectForKey:#"long"];
clubDC.cDLat = [responseObject objectForKey:#"lat"];
clubDC.cDAddress = [responseObject objectForKey:#"address"];
clubDC.cDSummary = [responseObject objectForKey:#"summary"];
clubDC.cDStat = [responseObject objectForKey:#"stat"];
clubDC.cDUS = [responseObject objectForKey:#"us"];
clubDC.cDImage = [self loadClubDetailImages:clubDC.cDImage];
for (clubDetail in venu_dataArray)
{
lblDescription.text = [ NSString stringWithFormat:#"Neighborhood:%# Information on whats happening tonight", clubDetail.cDAddress];
[imgClub setImageWithURL:[NSURL URLWithString:clubDetail.cDImage]];
}
[dataArray addObject:clubDC];
success(dataArray);
if (dataArray.count == 0)
{
ALERT_VIEW(#"Please check your internet connection.");
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
ALERT_VIEW(#"Error while loading data.")
}];
}
or if you want to use your function in separete class then do like this in your success block
[dbHandler myVenusWithClubDetail:strVenuID completionHandler:^(id array)
{
venu_dataArray = array;
// NSLog(#"%d",array.count);
for (clubDetail in venu_dataArray)
{
lblDescription.text = [ NSString stringWithFormat:#"Neighborhood:%# Information on whats happening tonight", clubDetail.cDAddress];
[imgClub setImageWithURL:[NSURL URLWithString:clubDetail.cDImage]];
}
}];

Since venue_dataArray is local in reloadView method, you wont be able to iterate it in viewWillAppear.
So I guess, you should move your label assigning code to success block like below:
[dbHandler myVenusWithClubDetail:strVenuID completionHandler:^(id array)
{
venu_dataArray = array;
// NSLog(#"%d",array.count);
for (clubDetail in venu_dataArray)
{
lblDescription.text = [ NSString stringWithFormat:#"Neighborhood:%# Information on whats happening tonight", clubDetail.cDAddress];
[imgClub setImageWithURL:[NSURL URLWithString:clubDetail.cDImage]];
}
}];

Can you post your success function too? If you set the text on your labels and image on your uiimageview everything should be updated accordingly.
Your success function could look something like:
- (void)updateViewsWithData:(NSMutableArray *)dataArray {
var clubDC = dataArray[0];
self.yourLabel.text = clubDC.cDSummary;
self.addressLabel.text = clubDC.cDAddress;
self.imageView.image = clubDC.cDImage;
}
You have to AFNetworking library or something similar to download the image first because I am pretty sure that what you got is the url of the image.
Please comment if you have any more question.

In your code,
clubDC.cDImage = [self loadClubDetailImages:clubDC.cDImage];
This line will fetch the image from server or local directory depending upon how you implemented it. There will be expected delay in getting the image.
self.imageView.image = clubDC.cDImage;
there will be chance that image is not fully downloaded when you are executing above code.

Related

Obj-c: Data inside AFNetworking loads after everything in viewDidLoad...?

I'm loading data in my ViewController inside of an AFNetworking request. However doing this causes the data inside of that method to load 2-3 seconds after everything else inside of my viewDidLoad has already loaded. WHY? How can I make it so that this data all appears on the screen at the same time? I've seen a few variations of this question on stack and none of the suggested fixes seem to work for me. See code below.
ViewController.m
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"map" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
dispatch_async(dispatch_get_main_queue(), ^{
self.mapuserData = (NSMutableArray *)responseObject;
[self.tableView reloadData];
[operation responseString];
if ([self.mapuserData count] > 0 ) {
NSString *thisUserId = [self.mapuserData objectForKey:#"users_name"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"node_title CONTAINS[cd] %#",
thisUserId];
NSArray *resultArray = [self.acceptedFriends filteredArrayUsingPredicate:predicate];
NSLog(#"RESULT %#", resultArray);
if ([resultArray count] > 0) {
NSLog(#"Executed!");
self.addFriend.hidden = YES;
self.orangeFriendCircle.hidden = YES;
} else {
self.addFriend.hidden = NO;
self.orangeFriendCircle.hidden = NO;
}
self.username.text = self.mapuserData[#"users_name"];
self.userBio.text = self.mapuserData[#"userbio"];
NSString *thirdLink = self.mapuserData[#"photo_path"];
NSString *ImageURLTwo = thirdLink;
NSData *imageDataTwo = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURLTwo]];
self.userPhoto.image = [[UIImage alloc] initWithData:imageDataTwo];
self.supervisionLabel.text = [self.mapuserData objectForKey:#"supervision"];
self.propertyLabel.text = [self.mapuserData objectForKey:#"property type"];
self.childrenLabel.text = [self.mapuserData objectForKey:#"children"];
self.specialLabel.text = [self.mapuserData objectForKey:#"special skills"];
self.emergencyLabel.text = [self.mapuserData objectForKey:#"emergency"];
self.username.text = [self.mapuserData objectForKey:#"first name"];
self.userBio.text = [self.mapuserData objectForKey:#"userbio"];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];

JSON to NSMutableArray iOS

As a response to a request I get JSON:
{
"letters": {
"A": 0,
"B": 1,
"C": 2,
"D": 3,
"E": 4,
...
}
}
That's my code to acquire this JSON:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Handle error
}];
I want to fill array with keys (not values) like this:
array[0] = "A"
array[1] = "B"
...?
NSMutableArray *parts = [NSMutableArray new];
NSDictionary *allletters = [responseObject objectForKey:#"letters"];
for (NSString *key in [allletters allKeys])
{
NSString *value = [allletters objectForKey: key];
[parts insertObject:key atIndex:[val intValue]];
}
I haven't tested the code. But it should be something similar to this:
NSDictionary *responseDictionary = (NSDictionary*)responseObject;
NSDictionary *letters = [responseDictionary objectForKey:"letters"];
NSMutableArray *lettersArray = [[NSMutableArray alloc]init];
if ( letters ){
for (NSInteger i = 0; i < letters; ++i)
{
[lettersArray addObject:[NSNull null]];
}
[letters enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
usingBlock:^(id key, id object, BOOL *stop) {
[lettersArray replaceObjectAtIndex:[key integerValue] withObject:object]
}]
}
try the following code
NSDictionary *letters = [responseObject objectForKey:"letters"];
NSArray *lettersArray = [letters allKeys];
As you are already using the JSON response serializer, responseObject should be a dictionary.
To get all keys of the sub dictionary letters, do
NSArray *letters = [reponseObject[#"letters"] allKeys];
No need for a mutable array here. But if you want it mutable , do
NSMutableArray *letters = [[reponseObject[#"letters"] allKeys] mutableCopy];

Fetch json data UIViewController

I'm trying to fetch json data from UIViewcontroller in objective-c.But it's not change anything in view.
what should I do ?
- (void)api {
NSLog(#"test");
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:YES];
NSString *urlPath = [NSString stringWithFormat:#"http://test.com/api/index.php"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"process":#"musteri_detay",#"id": self.customerId,#"where":#""};
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[manager setSecurityPolicy:securityPolicy];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:urlPath parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSError *error = nil;
NSData *jsonData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.customerCards = [NSMutableArray array];
NSArray *customersArray = [dataDictionary objectForKey:#"musteri_list"];
for (NSDictionary *customersDictionary in customersArray) {
ApiClass *customer = [ApiClass customersWithTitle:[customersDictionary objectForKey:#"adi"]];
customer.tel = [customersDictionary objectForKey:#"tel1"];
customer.grubu = [customersDictionary objectForKey:#"grubu"];
customer.adres = [customersDictionary objectForKey:#"adres"];
NSNumber *customerType = [customersDictionary objectForKey:#"kayit_tipi"];
/*
if (customerType == 1) {
customer.kayitTipi_string = #"Müşteri";
} else if (customerType == 2) {
customer.kayitTipi_string = #"Kişi";
} else if (customerType == 10) {
customer.kayitTipi_string = #"Bayi";
} else if (customerType == 20) {
customer.kayitTipi_string = #"Aday";
} else {
customer.kayitTipi_string = #"";
}
*/
[self.customerCards addObject:customer];
}
NSLog(#"Get data %#",dataDictionary);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
This is getDetails.
-(void) getDetails {
ApiClass *customers = [self.customerCards objectEnumerator];
//self.kayitTipi.text = customers.kayitTipi_string;
self.Adi.text = customers.adi;
self.faliyetAlani.text = customers.grubu;
}
And This is my viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"ID: %#",self.customerId);
[self api];
[self getDetails];
// Do any additional setup after loading the view.
}
When I start the debuging its going api method.And [manager POST:urlPath parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
after this line its going the end of method.Then going to viewdidload again.And going to getdetails method.After turn back the api method.And fetching data.But its not changing anything.

Ui view freez for long time

I am working on afnetworking, i have web service that takes too much time to load data and i want that UI do not freeze, i used this tutorial to run webservice on background so that i can work on other views as well, but not sucess till yet.
-(void) getArticles :(NSString*)stateAbbre completionHandler:(void (^)(id array))success
{
[MyCommonFunctions showGlobalProgressHUDWithTitle:#"Loading"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *link = [NSString stringWithFormat:#"http://cloud.ilmasoft.com/depilex/depilexs/get_articles_ios.php"];
NSLog(#"%#",link);
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager GET:link parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
NSDictionary *returnedDealDict = responseObject ;
NSArray *returnArray = [returnedDealDict objectForKey:#"Result"];
for(NSDictionary *dealDict in returnArray)
{
ArticlesDC *articles = [[ArticlesDC alloc] init];
articles.articlesID = [[dealDict objectForKey:#"id"]intValue ];
articles.articleTitle = [dealDict objectForKey:#"title" ];
articles.articleDetail = [dealDict objectForKey:#"details" ];
articles.articleDate = [dealDict objectForKey:#"date" ];
articles.articlePic = [dealDict objectForKey:#"pic" ];
articles.articleThumbPath = [dealDict objectForKey:#"thumb_path" ];
articles.articleStatus = [dealDict objectForKey:#"status" ];
[dataArray addObject:articles];
[MyCommonFunctions dismissGlobalHUD];
}
success(dataArray);
// [MBProgressHUD hideHUDForView:self.view animated:YES];
if (dataArray.count == 0)
{
ALERT_VIEW(#"Please check your internet connection.");
// [MBProgressHUD hideHUDForView:self.view animated:YES];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
ALERT_VIEW(#"Error occured while loading data.");
// [MBProgressHUD hideHUDForView:self.view animated:YES];
}];
}
and in my view did load method
[self getArticles:nil completionHandler:^(id array) {
articlesArray = array;
[tblView reloadData];
for (ArticlesDC *article in articlesArray)
{
NSString *stringWithoutSpace = [[NSString stringWithFormat:#"http://cloud.ilmasoft.com/depilex/admin/%#", article.articleThumbPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString: stringWithoutSpace]];
UIImage *imgOne = [UIImage imageWithData:imageData];
NSString *stringforImg = [[NSString stringWithFormat:#"http://cloud.ilmasoft.com/depilex/admin/%#", article.articlePic] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *imageDta = [NSData dataWithContentsOfURL:[NSURL URLWithString: stringforImg]];
UIImage *imgTwo = [UIImage imageWithData:imageDta];
[dbHandler insertArticlesIntoSqlite:article.articleTitle andDetail:article.articleDetail anddate:article.articleDate andImage:[MyCommonFunctions saveImageInDocuments:imgTwo] andThumb:[MyCommonFunctions saveImageInDocuments:imgOne]];
[defaults setInteger:1 forKey:#"getArticlesOffline"];
[defaults synchronize];
}
}];
The problem is not AF, it's that at the end of that process you call dataWithContentsOfURL twice and this runs directly on the main thread to download some images. You need to move that download to a background thread.

Afnetworking late response

I am new to AfNetworking, i want to get array after running my function but i always get crash as it loads data into array very late, is there any way to stop it till it loads all data into array?
-(void) getModelDetails :(NSString*)brandName completionHandler:(void (^)(id array))success
{
NSString *brand = [brandName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *link = [NSString stringWithFormat:#"http://phablet-fix.com/mob/get-model-details.php?model=%#",brand];
NSLog(#"%#",link);
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager GET:link parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
NSDictionary *returnedDealDict = responseObject ;
NSArray *returnArray = [returnedDealDict objectForKey:#"modeldetails"];
for(NSDictionary *dealDict in returnArray)
{
model = [[ModelDC alloc] init];
model.modelID = [[dealDict objectForKey:#"id"] intValue];
model.model = [dealDict objectForKey:#"model"];
model.mDeviceBrand = [dealDict objectForKey:#"device_brand"];
model.mDeviceType = [dealDict objectForKey:#"device_type"];
model.mProtectionPlanAvilable = [dealDict objectForKey:#"protection_plan_available"];
model.mSilverPlan1year = [dealDict objectForKey:#"silver_plan_price_1year"];
model.mSilverPlan2Year = [dealDict objectForKey:#"silver_plan_price_2year"];
model.mSilverPlan3Year = [dealDict objectForKey:#"silver_plan_price_3year"];
model.mGoldPlan1year = [dealDict objectForKey:#"gold_plan_price_1year"];
model.mGoldPlan2year = [dealDict objectForKey:#"gold_plan_price_2year"];
model.mGoldPlan3Year = [dealDict objectForKey:#"gold_plan_price_3year"];
[dataArray addObject:model];
}
success(dataArray);
[MBProgressHUD hideHUDForView:self.view animated:YES];
if (dataArray.count == 0)
{
ALERT_VIEW(#"Please check your internet connection.");
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
else
{
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
ALERT_VIEW(#"Error occured while loading data.");
[MBProgressHUD hideHUDForView:self.view animated:YES];
}];
}
and in my tableview i get zero data into my array
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath :(NSIndexPath *)indexPath
{
model = [planArray objectAtIndex:indexPath.row];
lblselectYourDevice.text = model.selectedModel;
tblView.hidden = YES;
modelDetailArray = [[NSMutableArray alloc] init];
[self getModelDetails:model.selectedModel completionHandler:^(id array)
{
modelDetailArray = array;
}];
NSLog(#"%d",modelDetailArray.count);
model = [[ModelDC alloc] init];
model = [modelDetailArray objectAtIndex:indexPath.row];
}
This will never work:
modelDetailArray = [[NSMutableArray alloc] init];
[self getModelDetails:model.selectedModel completionHandler:^(id array)
{
modelDetailArray = array;
}];
NSLog(#"%d",modelDetailArray.count);
model = [[ModelDC alloc] init];
model = [modelDetailArray objectAtIndex:indexPath.row];
because you are creating an empty array, asking for it to be populated with data and then immediately using it without waiting for the population to complete (or checking that the data you want was actually obtained).
Change to:
modelDetailArray = nil;
[self getModelDetails:model.selectedModel completionHandler:^(id array) {
modelDetailArray = array;
NSLog(#"%d", modelDetailArray.count);
if (modelDetailArray.count > indexPath.row) {
model = [modelDetailArray objectAtIndex:indexPath.row];
// trigger the UI update or next piece of processing here
} else {
// deal with the error
}
}];
Note that this also isn't creating empty objects that you aren't going to use.

Resources