TableView images from url - iphone

I found a strange problem. I have a JSON web service that returns me:
title
image (link)
featured (bool)
descriprion
I have next code to populate my cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"PasakaCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
Pasaka *retrievedPasaka = [allPasakas objectAtIndex:indexPath.row];
cell.textLabel.text = retrievedPasaka.title;
NSString *ImageURL = retrievedPasaka.image;
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
cell.imageView.image = [UIImage imageWithData:imageData];
cell.accessoryType =UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Only 4 images are being displayed:
Link that is being displayed:
#".../img/desa.png"
Link that is not displayed:
#".../img/38 papagaiļi.png"
Maybe the problem is in the links? With such symbols as: ļ,ā,ī etc.
And if so, how to resolve this? Because the image names on the server have those symbols in names...

I see that second link contains whitespace. This is incorrect.
Change ImageURL initialisation to NSString *ImageURL = [retrievedPasaka.image stringByAddingPercentEscapesUsingEncoding:NSUTD8StringEncoding];
If it does not help take a look into URL syntax.

Related

Table view mixes up images

I use SDWebImage to load and display async images in TableView. But sometimes when I scroll up and down fast, it mixes up all images and display it in other rows. This is my cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell.
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
if (item) {
// Parse out Image URL for cell
if (cell.imageView.image == nil) {
NSError *error = NULL;
NSRegularExpression *regexImage = [NSRegularExpression regularExpressionWithPattern:#"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regexImage enumerateMatchesInString:item.content
options:0
range:NSMakeRange(0, [item.content length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSString *src = [item.content substringWithRange:[result rangeAtIndex:2]];
NSLog(#"img src: %#", src);
[cell.imageView setImageWithURL:[NSURL URLWithString:src]];
}];}
if (cell.imageView.image == nil) {
cell.imageView.image = [UIImage imageNamed:#"video.png"];
}
return cell;
}
I don't know what is wrong, but I think its because I parse the image in the cell and it is not fast enough so it starts again and again. Can you please show me how to fix that
The high-level answer is, I believe, that when you scroll you are reusing the cells before you complete putting an image into them. That's what it means when I see this in my code, anyway.
I don't use SDWebImage and I don't know exactly what setImageWithURL variants are, but the github webpage has a how-to-use that says you can give it a completion block to execute when the image fetch is done (succeeds or fails).
So you need to check, when you finally have the image but before you put it in the UITableViewCell, that the cell is still assigned to the same indexPath as when you started to get the image. Since setImageWithURL seems to set the image always, you will have to put have a temporary UIImageView rather than directly in the cell. The docs I looked at had a method call with both placeHolderImage: and completed: Using that you'd do something like (code not compiler checked):
// before you go off to get the image, save the indexPath of the cell
NSIndexPath *originalIndexPath = indexPath;
UIImageView *tempImageView;
[tempImageView setImageWithURL:[NSURL URLWithString : [NSURL URLWithString:src]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
// completion block
// You probably want to check that it really succeeded, but if it did
// Now you have an image in the image parameter and probably in tempImageView.
// Check to see if the cell is still at the original indexPath
// If so, put the image in.
// If not, the row was scrolled out of sight and the cell has been reused
// so just drop the image on the floor -- it is no longer useful
NSIndexPath *currentIndexPath = [self.tableview indexPathForCell:cell]
if ([currentIndexPath isEqual originalIndexPath]) {
cell.imageView.image = image;
// or perhaps: cell.imageView.image = tempImageView.image;
}
}];
Change cell identifier from
static NSString *CellIdentifier = #"Cell";
to
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%i",indexPath.row];

Loading Images into a UITableView Asynchronously iOS 5

I'm struggling to get my tableView scrolling smoothly when loading images into the cell. At the moment I'm doing:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.newsFeedArray != nil) {
NewsFeedCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"NewsCell"];
self.singleStory = [self.newsFeedArray objectAtIndex:indexPath.row];
NSString *imageURL = [NSString stringWithFormat:#"%#", [self.singleStory valueForKey:#"image_primary"]];
NSURL *imageLink = [NSURL URLWithString:imageURL];
cell.newsFeedImage.image = [UIImage imageWithData: [NSData dataWithContentsOfURL:imageLink]];
cell.newsTitleLabel.text = [NSString stringWithFormat:#"%#", [self.singleStory valueForKey:#"title"]];
return cell;
} else {
NewsFeedCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"LoadingCell"];
return cell;
}
}
I've tried loading the images in on a background thread, but it takes the object out of the array and means it only loads in the first image 10 times.
I've tried implementing LazyTableImages but got confused and lost with what I actually needed.
Advice/help/work arounds would be greatly appreciated!

Parsing HTML Data in UITableView

I have an HTML Data which looks like:
<div id="foo"><a class="someClass" href="http://somelink">Some Title</a></div>
<div id="foo"><a class="someClass" href="http://somelink1">Some Title 1</a></div>
<div id="foo"><a class="someClass" href="http://somelink2">Some Title 2</a></div>
I'm able to show Link title in the tableView, but how can I get URL of these specific title to load a new view (which is pushed through navigation controller upon selecting table cell) ?
Here's the code I'm using to parse HTML Data:
HTMLParser * parser = [[HTMLParser alloc] initWithData:responseData error:&error];
HTMLNode * bodyNode = [parser body];
someArray = [[bodyNode findChildrenWithAttribute:#"id" matchingName:#"someID" allowPartial:NO] retain];
And this one to show the array data in the table:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [someArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
HTMLNode* someNode = [someArray objectAtIndex:[indexPath row]];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[someNode allContents]];
return cell;
}
When you get a node and want information about a child node within it, you have to continue parsing to find the child node and then get the attribute you are looking for. For example:
HTMLNode *anchorNode = [someNode findChildTag:#"a"];
NSString *anchorHref = [anchorNode getAttributeNamed:#"href"];
It might help to mention that you are looking at Ben Reeves' HTMLParser. (At least I think that is the one you are using).

How to print the array value in cells lable?

I am developing a application in that I want to print the array value in the cell contain label place. I got the vlaues for array like names=[results valueForKey:#"name"].
I write the code for print that value in a lable in cellForRowAtIndexPath like
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSInteger row=indexPath.row;
cell = [self getCellContentView:CellIdentifier];
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
lblTemp1.text = [names objectAtIndex:row];
//lblTemp2.text = [names objectAtIndex:row];
return cell;
}
but ,when the application got the error at lblTemp1.text = [names objectAtIndex:row] like Program received signal: “EXC_BAD_ACCESS”.So please tell me how to solve this problem.
It seems you've missed to retain the array names. Try,
names = [[results valueForKey:#"name"] retain];
You could consider using declared properties to overcome the overhead of retaining and releasing the objects.
seems to be new bee. please check out for step by step tutorial
http://adeem.me/blog/2009/05/19/iphone-programming-tutorial-part-1-uitableview-using-nsarray/

Reading plist into TableView

I started this project with a simple plist of a dictionary with two arrays of strings. I now want to add more information and want to use this plist structure:
Root - Dictionary - (2 items)
Standard - Array - (3 items)
Item 0 - Dictionary - (4 items)
Color - String - Red
Rvalue - String - 255
Gvalue - String - 0
Bvalue - String - 0
Sorry about typing in the plist but the site would not let me post an image
I know that the RGB values could be numbers instead of strings but I have a reason for them being strings.
This is the code I used to read the simple plist:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *colorSection = [colors objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if(cell == nil){
cell=[[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier: SectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [colorSection objectAtIndex:row];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton]; //add disclosure button to rows
return cell;
}
My question is what is the specific code to retrieve the contents of the color dictionaries to get the Colors for the cell.textLabel.text and also read the RGB values to add a subtitle. I've been working on this for several days and have read references and lots of examples and unfortunately can't solve the problem. Your assistance will be greatly appreciated.
So providing you have your Standard - Array stored against a Array you've defined in your .h file then something like this would work. In this example the array is stored against self.coloursArray.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if(cell == nil){
cell=[[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier: SectionsTableIdentifier] autorelease];
}
NSString* ColourString = [[self.coloursArray objectAtIndex:indexPath.row] valueForKey:#"Colour"];
NSString* rValue = [[self.coloursArray objectAtIndex:indexPath.row] valueForKey:#"Rvalue"];
NSString* gValue = [[self.coloursArray objectAtIndex:indexPath.row] valueForKey:#"Gvalue"];
NSString* bValue = [[self.coloursArray objectAtIndex:indexPath.row] valueForKey:#"Bvalue"];
cell.textLabel.text = ColourString;
NSString* subCellString = [NSString stringWithFormat:#"%#:%#:%#", rValue, gValue, bValue];
}
Hopefully that'll give a a hand.
First, do not use -[UITableViewCell initWithFrame:reuseIdentifier:]. It has been deprecated and will give you a warning, plus it will make your subtitle harder to implement. This code is a modified version of yours which loads the information, sets the title to the Color property, and sets the subtitle to a string containing the Rvalue, Gvalue, and Bvalue properties.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *colorSection = [colors objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if(cell == nil) {
cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: SectionsTableIdentifier] autorelease];
}
NSDictionary *color = [colorSection objectAtIndex:row];
cell.textLabel.text = [color objectForKey:#"Color"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#, %#, %#",[color objectForKey:#"Rvalue"],[color objectForKey:#"Gvalue"],[color objectForKey:#"Bvalue"]];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton]; //add disclosure button to rows
return cell;
}