TWRequest in background - ios

- (void)fetchImages {
if (self.profileImages == nil) {
self.profileImages = [[NSMutableDictionary alloc] initWithCapacity:200];
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (id tweet in self.timeline) {
TWRequest *fetchUserImageRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://api.twitter.com/1/users/profile_image/%#", [tweet valueForKeyPath:#"user.screen_name"]]] parameters:nil requestMethod:TWRequestMethodGET];
[fetchUserImageRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
[self.profileImages setObject:[UIImage imageWithData:responseData] forKey:[tweet valueForKeyPath:#"user.screen_name"]];
NSArray *indexPath = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[self.timeline indexOfObject:tweet] inSection:0]];
[self.tableView reloadRowsAtIndexPaths:indexPath withRowAnimation:UITableViewRowAnimationNone];
}
}];
}
});
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FavoriteCell"];
// configure cell
id tweet = [self.timeline objectAtIndex:[indexPath row]];
UILabel *tweetLabel = (UILabel *)[cell viewWithTag:102];
tweetLabel.text = [tweet objectForKey:#"text"];
UILabel *usernameLabel = (UILabel *)[cell viewWithTag:101];
usernameLabel.text = [tweet valueForKeyPath:#"user.name"];
UIImageView *profileImage = (UIImageView *)[cell viewWithTag:100];
profileImage.image = [self.profileImages objectForKey:[tweet valueForKeyPath:#"user.screen_name"]];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:103];
NSString *labelString = [[tweet objectForKey:#"created_at"] substringToIndex:10];
dateLabel.text = labelString;
return cell;
}
I get the timeline then want to get the profile images for all of users in the timeline. I need to loop through the tweets and get the image. I'm curious how I can determine when all of the images have been fetched then reload the tableview. As of now this isn't happening. The TWRequest is running after the table is reloaded. What am I doing wrong here? Maybe there is a better way to do this?
Thanks a lot.

That's because [TWRequest performRequestWithHandler:] is an async method. Why do you need to reload the entire table? Why not just reload the cell when you get a image (in the end of your handler block).
If you really want to reload the entire table just keep a count of all your finished requests, and reload the table when all is done.
If you want to reload a single cell you can do something like:
dispatch_sync(dispatch_queue_get_main(), ^{
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:0];
}

Related

Uneven data loading to UITableViewController from Parse when not using PFQueryTableView

I'm using UITableViewController for displaying data from Parse. It runs perfectly on my Xcode Simulator as i think there's no latency in network. But whenever i'm uploading the code to AppStore for Testing. The very first time i run the app it has to load a couple of restaurant's from Parse and display in UITableViewController. Upon clicking a row the first rows data is being loaded into the 3rd row and 4th row data loading in 6th row data irregularly. Why is the data being loaded very unevenly ? Here's my
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"restaurantIdentifier";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
PFObject *tempObject = [self.objectArray objectAtIndex:indexPath.row];
PFFile *imageFile = [tempObject objectForKey:#"RestaurantIcon"];
PFImageView *imageView = [[PFImageView alloc] init];
imageView.file = imageFile;
[imageView loadInBackground:^(UIImage *img,NSError *error){
if(!error){
cell.imageCell.image = imageView.image;
}
}];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 4;
cell.imageView.frame = self.view.bounds;
cell.cellLabel.text = [tempObject objectForKey:#"RestaurantName"];
[self.hotelNamesArray addObject:[tempObject objectForKey:#"RestaurantName"]];
cell.cellLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
_restaurantName = [self.hotelNamesArray objectAtIndex:indexPath.row];
self.restaurantMenuNameArray = [[NSMutableArray alloc] init];
PFQuery *query = [PFQuery queryWithClassName:[self.hotelNamesArray objectAtIndex:indexPath.row]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *obj in objects) {
if (![_restaurantMenuNameArray containsObject:[obj objectForKey:#"RestaurantMenuName"]]) {
NSLog(#"restaurantmenunames are %#",[obj objectForKey:#"RestaurantMenuName"]);
if ([obj objectForKey:#"RestaurantMenuName"] ==nil) {
[self performSegueWithIdentifier:#"restaurantDetail" sender:self];
return;
}else {
[_restaurantMenuNameArray addObject: [obj objectForKey:#"RestaurantMenuName"]];
}
}
}
}else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
[self.tableView reloadData];
NSLog(#"restaurantMenuNames is %#",_restaurantMenuNameArray);
[self performSegueWithIdentifier:#"restaurantDetail" sender:self];
}];
}
Thanks in advance.
If you mean the images get in the wrong cell, you have to consider that cells are recycled when you scroll, and that if the image loading takes a bit too long, you may get the result after the cell has been reused.
You need to check that the cell is still for the item/row you want (you could store the row in the cell's tag and check it before setting the image in the completion handler, for instance).
If it's other data that is mixed up, then you'll need to show us the code that loads that data.

How to set image path coming from server in uitableviewcell

I am making an app in which i am getting data from server and in data image path is also coming but when i am setting image to my tableview cell app will become too much heavy may b i am not setting image properly below is my sample code thanx in advance :)
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *tableviewidentifier = #"cell";
tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1){
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
UIImage *img1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
cell.imageView.image=img1;// here i am setting image due to which app is so heavy and stuck
return cell;
}
Dont use imageWithData: for setting images. It is synchronous and will make your app run slow.
Instead of that Use SDWebImage
You just need to do following things:
Dump SDWebImage folder into your project.
Import UIImageView+WebCache.h.
Set the image using: sd_setImageWithURL:
OR
by GCD (Grand Central Dispatch) and sending asynchronous requests. Code copied from HERE.
First implement following method.
- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
{
UIImage *image = [[UIImage alloc] initWithData:data];
completionBlock(YES,image);
} else{
completionBlock(NO,nil);
}
}];
}
and then in your cellForRowAtIndexPath
[self downloadImageWithURL:your_url completionBlock:^(BOOL succeeded, UIImage *image) {
if (succeeded) {
// change the image in the cell
cell.imageView.image = image;
}
}];
try this below code, hope this helps u .
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
__block tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1)
{
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
NSURL *url = [NSURL URLWithString:img];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^{ //in main thread update the image
cell.imageView.image = image;
cell.textLabel.text = #""; //add this update will reflect the changes
});
});
return cell;
}
EDIT
in order to reuse the downloaded image u can either save them on disk or just for save them some where for example in dictionary for temporary using
in below code i took one example dictionary, and strong the download images with row as key
#interface ViewController ()
{
NSMutableDictionary *imagesDictionary; //lets declare a mutable dictionary to hold images
}
in this method just initialise it
- (void)viewDidLoad {
[super viewDidLoad];
// rest of your code
//...........
//
imagesDictionary = [[NSMutableDictionary alloc]init]; //initilise
}
in index this method just add the downloaded images to dictionary for corresponding row as key
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
__block tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1)
{
// [[cell textLabel] setText:#"Load more records"];
}
__block NSString *row = [NSString stringWithFormat:#"%d",indexPath.row]; //add this
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
// valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
if(![[imagesDictionary allKeys] containsObject:row]) //if image not found download and add it to dictionary
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
NSURL *url = [NSURL URLWithString:img];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^{ //in main thread update the image
[imagesDictionary setObject:image forKey:row]; //sorry, while editing to your code i forgot to add this
cell.imageView.image = image;
cell.textLabel.text = #""; //add this update will reflect the changes
NSLog(#"loading and addig to dictionary");
});
});
}
else
{
cell.imageView.image = [imagesDictionary objectForKey:row];
NSLog(#"retriving from dictioary");
}
return cell;
}
First of all you are calling dataWithContentsOfURL: function which will make the app non responsive because you are calling it on main thread. To make it responsive you need to create a custom cell YourCell and declare a method in YourCell.h
#interface YourCell : UITableViewCell
{
UIImage *_cImage;
}
- (void)downloadImageFromURL:(NSURL *)imageUrl;
#end
Now in YourCell.m you need to do like this:
- (void)downloadImageFromURL:(NSURL *)imageUrl
{
if (_cImage != nil)
{
self.imageView.image = _cImage;
}
else
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_cImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = _cImage;
});
});
}
}
Now from cellForRowAtIndexPath: you just need to call downloadImageFromURL: function of YourCell and pass the imageUrl to it and its the cell responsibility to download and show the image.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier= #"YourCell";
YourCell *cell = (YourCell *)[self.activitiesTableView_ dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"YourCell" owner:self options:nil] objectAtIndex:0];
}
// Set your UILabels as before.....
NSString *imagePath=[[self.inboxmessagesarray objectAtIndex:indexPath.row] objectForKey:#"offerPhoto"];
[cell downloadImageFromURL:[NSURL URLWithString:imagePath]];
return cell;
}
Let me know if you have any questions.
UIImageView *img1 = (UIImageView *)[cell viewWithTag:104];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
img1.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
});
});
Send async requests for images. Doing this would not block your UI until the image gets loaded.

UITableViewCell image load

I have the following code that loads an image from a web service, I want to check if the image is loaded and then populate a button with an image (button is already in place)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[FeedTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kTableViewCellIdentifier];
}
// Configure the cell...
cell.post_time.font = [UIFont fontWithName:#"ProximaNova-Bold" size:12];
cell.post_price.font = [UIFont fontWithName:#"ProximaNova-Semibold" size:13];
cell.post_address.font = [UIFont fontWithName:#"ProximaNova-Regular" size:13];
cell.post_attributes.font = [UIFont fontWithName:#"ProximaNova-Regular" size:11];
House * house = [Posts objectAtIndex:indexPath.row];
//cell.post_image.clipsToBounds = YES;
//cell.post_image.contentMode = UIViewContentModeScaleAspectFill;
//cell.post_image.contentMode = UIViewContentModeScaleAspectFit;
cell.post_time.text = house.house_ts;
// [cell.post_image setImageWithURL:[NSURL URLWithString:house.house_aws_image_id]];
[cell.post_image setImageWithURL:[NSURL URLWithString:house.house_aws_image_id] placeholderImage:[UIImage imageNamed:#"splash_image_gray"]];
cell.post_attributes.text = [self decodeAttributes:house.house_bed_rms :house.house_bath_rms :house.house_house_siz];
[cell.post_playButton addTarget:self action:#selector(showVideo:) forControlEvents:UIControlEventTouchUpInside];
cell.post_share.tag = indexPath.row;
[cell.post_share addTarget:self action:#selector(shareoptions:) forControlEvents:UIControlEventTouchUpInside];
//[cell.post_playButton setImage:[UIImage imageNamed:#"feed_play_but_pink.png"] forState:UIControlStateHighlighted];
//[cell.post_playButton setBackgroundImage:[UIImage imageNamed:#"heart_btn"] forState:UIControlStateNormal];
[cell.post_playButton setTag:indexPath.row];
[cell.post_playButton setBackgroundImage:[UIImage imageNamed:#"feed_play_but"] forState:UIControlStateNormal];
return cell;
}
Any ideas how to achieve this? Thanks in advance.
Assuming your getting your data form the web service as array, you should parse the array and copy it mutable (or parse it as mutable array directly).
Then you can do this:
id imageObject = [[[self dataArray] objectAtIndex:[indexPath row]] objectForKey:#"imageURL"];
if ([imageObject isKindOfClass:[NSString class]]) {
NSURLConnection *connection = [NSURLConnection ...];
// replace image url in array so that you don't start connections too often.
[[[self dataArray] objectAtIndex:[indexPath class]] setObject:connection forKey:#"imageURL"];
// when connection finishes, replace the connection by the instance of UIImage and reload the corresponding cell
}
else if ([imageObject isKindOfClass:[UIImage class]]) {
[[cell imageView] setImage:imageObject];
}
You can use the JWURLConnection class for easy block programming. If you do so, you can easily use this code (which is from one of my apps and works just fine):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
NSMutableDictionary *post = [[self dataSource] objectAtIndex:[indexPath row]];
id memberCloseup = [post objectForKey:#"image"];
if ([memberCloseup isKindOfClass:[NSString class]]) {
JWURLConnection *connection = [JWURLConnection connectionWithGETRequestToURL:[NSURL URLWithString:memberCloseup] delegate:nil startImmediately:NO];
[connection setFinished:^(NSData *data, NSStringEncoding encoding) {
[post setObject:[UIImage imageWithData:data] forKey:#"image"];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}];
[teamMemberMeta setObject:connection forKey:#"so_team_member-image_close"];
[post setObject:connection forKey:#"image"];
[connection start];
}
else if ([memberCloseup isKindOfClass:[UIImage class]]) {
[[cell imageView] setImage:memberCloseup];
}
return cell;
}
EDIT
You would have to move your loading logic to the view controller. Letting the cell loading itself is wrong, because your cells are getting reused, so one cell represents various data objects and / or images. My solution saves a lot of memory and data usage.

Asynchronous images loading again and again in the Uitableview cells

Having trouble with the asynchronous images don't know why having this weird problem. I am applying the Asynchronous images load technique but the images are not freezing once loaded on scrolling they are again loading.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell=[self getCellContentView:CellIdentifier];
}
[cell setBackgroundColor:[UIColor redColor]];
NSLog(#"%i",[discussionArray count]);
NSDictionary *dict=[discussionArray objectAtIndex:indexPath.row];
UILabel *textLabel1 = (UILabel *)[cell viewWithTag:1];
UILabel *textLabel2 = (UILabel *)[cell viewWithTag:2];
UILabel *textLabel3 = (UILabel *)[cell viewWithTag:3];
UIImageView *avatarimage = (UIImageView *)[cell viewWithTag:4];
UIImageView *new_oldimage = (UIImageView *)[cell viewWithTag:5];
UIImageView *avatarimage_cover = (UIImageView *)[cell viewWithTag:6];
textLabel1.text =[dict objectForKey:#"user"];
textLabel2.text =[dict objectForKey:#"date"];
textLabel3.text =[dict objectForKey:#"text"];
NSString *photoStrn=[dict objectForKey:#"photo"];
avatarimage.image = nil;
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSString *u=[NSString stringWithFormat:#"http://%#",photoStrn];
NSURL *imageURL=[NSURL URLWithString:u];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
dispatch_sync(dispatch_get_main_queue(), ^{
UIImage *dpImage = [UIImage imageWithData:imageData];
if (dpImage==nil)
{
dpImage = [UIImage imageNamed:#"profileImage.png"];
}
[UIView animateWithDuration:5.0 animations:^{
avatarimage.alpha = 1.0;
}];
avatarimage.image = dpImage;
});
});
avatarimage_cover.image = [UIImage imageNamed:#"avtrcover.png"];
NSString *new=[dict objectForKey:#"new"];
if ([new isEqualToString:#"0"])
{
new_oldimage.image = [UIImage imageNamed:#"old_message.png"];
}
else
{
new_oldimage.image = [UIImage imageNamed:#"new_message.png"];
}
textLabel3.numberOfLines = 0;
NSString *detailText = [[discussionArray objectAtIndex:indexPath.row] objectForKey:#"text"];
CGSize textSize = [detailText sizeWithFont:[UIFont boldSystemFontOfSize:13] constrainedToSize:CGSizeMake(240, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
textLabel3.frame = CGRectMake(70, 53, 240, textSize.height+detailTextoffset );
return cell;
}
You are setting avatarimage.image to nil each time the cell is configured. You call the loading code regardless what. Thus, it is not surprising you keep reloading the image.
Instead, you should maintain a mutable array of downloaded images. This could be just file URLs for the images somewhere in the documents folder. If the image exists use it, if not download it.
if (imageArray[indexPath.row]) {
// use the image to populate the image view
}
else {
// fetch async from server
}
this will solve you problem completely. click on below link:
Image on top of Cell

UITableView scroll shows bad performance

I'm having a big performance issue on my tableviewcontroller. The scroll is very slow. I've made a NSLOG on the didSelectRowAtIndexPath method, and I realized that this is called on every scroll I do. It's supposed to be like that?
I've a search on this table, and I've some logic because the data depends of the json response. You can check this method here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSLog(#" scroll");
// Configure the cell...
static NSString *CellIdentifier = #"contactCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1];
UILabel *workPlaceLabel = (UILabel *)[cell viewWithTag:2];
if(searching)
{
//NSLog(#" copyListOfItems: %#",copyListOfItems);
NSString*lastName=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"lastname"];
if(lastName==nil)
{
lastName=#" ";
}
NSString*firstName=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"firstname"];
if(firstName==nil)
{
NSArray*phonesArray=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"phone"];
NSLog(#"NUMERO TELEFONE %d",[phonesArray count]);
if([phonesArray count]>0)
{
NSString*phoneNumber=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Phone"];
nameLabel.text=phoneNumber;
}else{
nameLabel.text=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Current"];
workPlaceLabel.text=#"";
}
}else{
NSString *stringName= [NSString stringWithFormat:#"%# %#", firstName, lastName];
nameLabel.text=stringName;
workPlaceLabel.text=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Current"];
}
}
else {
//NSLog(#" _contactsArray: %#",_contactsArray);
NSString*lastName=[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Lastname"];
if(lastName==nil)
{
lastName=#" ";
}
NSString*firstName=[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Firstname"];
if(firstName==nil)
{
NSArray*phonesArray=[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Phone"];
//NSLog(#"NUMERO TELEFONE %d",[phonesArray count]);
if([phonesArray count]>0)
{
NSString*phoneNumber=[[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"phone"] objectAtIndex:0]objectForKey:#"phonenumber"];
nameLabel.text=phoneNumber;
}else{
nameLabel.text=[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Current"];
workPlaceLabel.text=#"";
}
}else{
NSString *stringName= [NSString stringWithFormat:#"%# %#", firstName, lastName];
nameLabel.text=stringName;
if([[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Current"])
{
workPlaceLabel.text=[[[_contactsArray objectAtIndex:indexPath.row]objectForKey:#"Contact"] objectForKey:#"Current"];
}
}
}
// Configure the cell...
return cell;
}
There are a lot of needless calls in this that could be removed from your code. All those calls to get a contact that are repeated are taking time to perform when you could make them once. Like in your first branch of the if statement, you have calls like these:
NSString*lastName=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"lastname"];
NSString*firstName=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"firstname"];
NSArray*phonesArray=[[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"]objectForKey:#"phone"];
You could compact these calls by doing something like this:
id contact = [[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"];
NSString *lastName=[contact objectForKey:#"lastname"];
NSString *firstName=[contact objectForKey:#"firstname"];
NSArray *phonesArray=[contact objectForKey:#"phone"];
Ideally though, you would have a class of your own that has those items as properties so you could do something like this:
Contact *contact = (Contact *)[[copyListOfItems objectAtIndex:indexPath.row]objectForKey:#"Contact"];
NSString *lastName = contact.lastName;
NSString *firstName = contact.firstName;
NSArray *phonesArray = contact.phone;
Edit: How to do asynchronous image loading
Here's how I've done asynchronous loading of an image with a placeholder image in the past. The cell I was using was a custom class I wrote, but it should give you an idea of how to do it.
// Setup the image view
UIImageView* imageView = cell.imageView;
imageView.image = [UIImage imageNamed:#"Loading.png"];
// Load the image asynchronously
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
// Here you will want to make a call to your web server to get the image
// and store it in a UIImage named image
UIImage *image = // your code to get the image from the server
// Only update if the cell is still on the screen
if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) {
// Have to update UI elements on the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
[[cell imageView] setImage:image];
[cell setNeedsLayout];
});
}
});
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
is called for every cell that appears so it would be better if you kept your logic out of this loop since it will be called multiple amount of times as the user is scrolling you could set your array outside this loop and just replace the values in this method

Resources