Hello all,
Step - 3 : Now Open your LazyLoadingViewController.h file and write :
c) Now add all table view methods :
d) For cell creation we want to display a default image in the image view till we get the image from server.In our case we have used this :
Note : Remember to add the labels and the image view to the cell's content view.
f) Encode URL : This is done to create verbatim string for url to override the behavior of the escape sequences.
g) Cell creation is the most important part of the table view that will display the contents from the web when they are available.If Image is available from the server we will display it else we will display the default image. You can see the test condition for this in BOLD.
#define IMG_TAG 1
I know many of us have successfully done this.
I have tried to show the working via images. Hope it helps all the beginners like me to learn more.
What you can get here:
1) How to start with Story-Boards
2) Url Encoding
3) Lazy loading of images
Here is a tutorial for all,
Step -1 : Open New Project in Xcode :
Step - 2 : Open MainStoryBoard.storyboard
Inside the View add a tableview and connect its DataSource and Delegate with the controller class.
You can also change the background color of the view to have a look like this :
Step - 3 : Now Open your LazyLoadingViewController.h file and write :
@interface LazyLoadingViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>
{
IBOutlet UITableView *tableView;
NSArray *animals;
NSArray *animalUrl;
NSMutableDictionary *imageDict;
}
@property(nonatomic,retain)UITableView *tableView;
@property(nonatomic,retain)NSArray *animals;
@property(nonatomic,retain)NSArray *animalUrl;
@property(nonatomic,retain)NSMutableDictionary *imageDict;
-(NSString *) URLEncodeString:(NSString *) str;
@end
Step - 4 : Now Open your LazyLoadingViewController.m file and write this :
a) Synthesize all the properties that you created in .h class
b) Initialize your arrays and dictionary in ViewDidLoad.
I have done like this :
imageDict = [[NSMutableDictionary alloc] initWithCapacity:4];
animals = [NSArray arrayWithObjects:@"CAT",@"DOG",@"FOX",@"LION", nil];
animalUrl = [NSArray arrayWithObjects:
@"http://www.zastavki.com/pictures/1600x1200/2008/Animals_Cats_Small_cat_005241_.jpg",
@"http://spadogbotanicals.com/wp-content/uploads/puppy1-300x225.jpg",
@"http://www.nj.gov/dep/fgw/images/wildlife/fox_gl.jpg",
@"http://www.mikesel.info/wp-content/uploads/2011/07/lion.jpg",nil];
c) Now add all table view methods :
In our case the number of sections is only one but the rows depend on the total contents in the array we will use to display the contents in the table view
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [animals count];
}
d) For cell creation we want to display a default image in the image view till we get the image from server.In our case we have used this :
e) Cell creation is the most important part of the table view that will display the contents from the web when they are available. This is done via dispatching a background thread that fetches the images in background.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Identifier=@"Identifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:Identifier];
if(cell == nil)
{
cell = [self reuseTableViewCellWithIdentifier:Identifier withIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//configure cell
UIImageView *imgView= (UIImageView *)[cell.contentView viewWithTag:IMG_TAG];
if([imageDict valueForKey:[NSString stringWithFormat:@"%i,%i", indexPath.row, indexPath.section]]==nil)
{
[NSThread detachNewThreadSelector:@selector(displayingSmallImage:)
toTarget:self withObject:indexPath];
toTarget:self withObject:indexPath];
}
else
{
imgView.image = [imageDict valueForKey:[NSString stringWithFormat:@"%i,%i",
indexPath.row, indexPath.section]];
indexPath.row, indexPath.section]];
}
UILabel *lblName = (UILabel *)[cell.contentView viewWithTag:TITLE_TAG];
[lblName setText:[animals objectAtIndex:indexPath.row]];
return cell;
}
-(UITableViewCell *)reuseTableViewCellWithIdentifier:(NSString *)identifier withIndexPath:(NSIndexPath *)indexPath
{
CGRect cellRectangle;
cellRectangle = CGRectMake(0.0, 0.0, 340, 180);
UITableViewCell *cell = [[UITableViewCell alloc]
initWithFrame:cellRectangle reuseIdentifier:identifier];
initWithFrame:cellRectangle reuseIdentifier:identifier];
//here we create the image view and set its properties
UIImageView *img11;
cellRectangle = CGRectMake(15,18, 75, 70);
img11 = [[UIImageView alloc] initWithFrame:cellRectangle];
img11.tag = IMG_TAG;
img11.image = [UIImage imageNamed:@"base-image.png"] ;//acts as default image
img11.contentMode = UIViewContentModeScaleToFill;
[cell.contentView addSubview:img11];
//here we create the label and set its properties
UILabel *labelName;
cellRectangle = CGRectMake(150, 40, 200, 20);
labelName = [[UILabel alloc] initWithFrame:cellRectangle];
labelName.font =[UIFont fontWithName: @"Verdana"size:15.0f];
labelName.textColor = [UIColor blackColor];
labelName.autoresizingMask = UIViewAutoresizingFlexibleWidth;
labelName.tag = TITLE_TAG;
[cell.contentView addSubview:labelName];
return cell;
}
Note : Remember to add the labels and the image view to the cell's content view.
-(NSString *) URLEncodeString:(NSString *) str
{
NSMutableString *tempStr = [NSMutableString stringWithString:str];
[tempStr replaceOccurrencesOfString:@" " withString:@"+" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [tempStr length])];
return [[NSString stringWithFormat:@"%@",tempStr] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
After we get the image we save it in the dictionary and display the image on the image view in main thread i.e when the working of background thread is complete.
- (void) displayingSmallImage:(NSIndexPath *)indexPath
{
NSString *imageUrl = [animalUrl objectAtIndex:indexPath.row];
imageUrl = [self URLEncodeString:imageUrl];
NSURL *url = [NSURL URLWithString:imageUrl];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
if(image == nil)
{
image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle]
resourcePath] stringByAppendingPathComponent:@"base-image.png"]];
resourcePath] stringByAppendingPathComponent:@"base-image.png"]];
}
[self.imageDict setObject:image forKey:[NSString
stringWithFormat:@"%i,%i",indexPath.row,indexPath.section]];
stringWithFormat:@"%i,%i",indexPath.row,indexPath.section]];
[self performSelectorOnMainThread:@selector(imageReceived:)
withObject:indexPath
waitUntilDone:NO];
withObject:indexPath
waitUntilDone:NO];
}
h) Here we display the image received and reload the particular row of the table for which we got the image.
- (void) imageReceived:(NSIndexPath *)indexPath
{
UIImage *image = (UIImage *)[imageDict objectForKey:
[NSString stringWithFormat:@"%i,%i",
indexPath.row,indexPath.section]];
[NSString stringWithFormat:@"%i,%i",
indexPath.row,indexPath.section]];
UIImageView *imgs = (UIImageView *)[[tableView
cellForRowAtIndexPath:indexPath] viewWithTag:IMG_TAG];
cellForRowAtIndexPath:indexPath] viewWithTag:IMG_TAG];
[imgs setImage:image];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
withRowAnimation:UITableViewRowAnimationNone];
}
i) Don't forget to add this tag in your .m file : This is done so that the labels and image views when created we assign a tag to them so that while giving them their values the same can be accessed via tags.
#define TITLE_TAG 2
This is to be done after the properties are synthesized.
j) You will see output like this :
i) When the Application is launched.
ii) When only 2 icons were fetched and rest are in transit
iii) When all icons were fetched from the web server
Enjoy table view and iOS....... :)
hi swati nice tutorial, thanks a lot and i have a doubt like as you are using NSArray of objects and links directly in the code, if i have an xml file in url and from that i wanna show the data and images then how come i can rearrange the code. hope you got wat am asking Thank u swati
ReplyDeleteFor this
ReplyDeleteFirst you need to get the xml file using the URL (NSURL)
Then u need to parse this XML and save data and URL for images in an array
Now show the images in table view
ya swati i did so and i face some troubles in it can you see this link you can get what my prob is http://stackoverflow.com/questions/13696406/why-am-viewing-only-uiimage-of-last-element-in-xml-file-from-url-in-iphone/13696528#comment18807682_13696528
Deletehi as we previously discussed, i had used the code,
ReplyDeletexmlParser = [[XMLParsing alloc] loadXMLByURL:@"http://images.com/Products.xml"];
in viewDidLoad() of table controller file and from there
in - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [animals count];
}
i used return [xmlParser.tweets count]; and NSLog(@"Table images %@",xmlParser.tweets); but this didn't give any NSLog output but if i use the same in NSLog(@"Table images %@",xmlParser.tweets);in viewDidLoad() i can get the values of images. i cant understand why its not showing in the tableView numberOfRowsInSection:(NSInteger)section any ideas?
in method : numberOfRowsInSection
Deletehave you checked that parser has some memory or not??
also try to access xmlParser using self.xmlParser
hi swati can you see this link and help me out to solve http://stackoverflow.com/questions/13716716/why-images-not-loading-from-xml-file-of-url-and-not-showing-in-table-view
ReplyDeleteHi Swati this is me again can you help me out to solve this problem
ReplyDeletehttp://stackoverflow.com/questions/14600396/why-the-same-images-are-repeated-in-all-the-collection-views-of-iphone-sdk/14602624#14602624
HI, Thanks for the code, It works well with less no of images in Table view, But there is a problem with more no of images. say If i have 20 no of images that i want to load in to my table, when scrolling images are repeating until the actual image loads.
ReplyDeletePrefer using Show more button at the end. Clicking on Show more produces/displays next 20 images
Deletei need lazy image loading in collection view controller...give some ideas.
ReplyDeletewherever imagetag and title tag is used in the program ..
ReplyDeleteit is giving a warning "expected expression"
can;t figure out why???
sorry for the late reply, Have u # defined IMG_TAG in your code
Deletei have used your code but it is frizzed my app i have download more than 200 images from server then it is frizzed
ReplyDeleteWhen such a big number of images are downloaded try to save images with u, show 20 images and a button indicating "show more". when user clicks on show more next 20 images are fetched and displayed...
Delete