iphone showing images in tableView - iphone

Hi I have this code to download images from the server and then to show them in table view with some text (if there is no image I want to show the text anyway):
//download part
NSMutableString *photourl=[[NSMutableString alloc] initWithString:url_image];
[photourl appendString:[dic objectForKey:#"photo"]];
#try{
//add to mutable array
[photoSmallImageData addObject:[NSData dataWithContentsOfURL:[NSURL URLWithString:photourl]]];
}
#catch (id Exception) {
[photoSmallImageData addObject:[NSData dataWithContentsOfURL:[NSURL URLWithString:url_image]]];
}
//part of table view code
NSData *imageData = [photoSmallImageData objectAtIndex:indexPath.row];
#try {
cell.imageView.image = [UIImage imageWithData:imageData];
}
#catch (NSException *exception) {
cell.imageView.image = [UIImage imageNamed:#"icon72.png"];
}
It works but the thing is sometimes there is no image so I would like to replace it with some icon but since we can't add nil to array i juste add some part of my link there and then even if the link doesn't work for image data it doesn't call the catch method. I don't know if I could some how replace the url with local url but I don't know how. Also I can't skip the step because then the images will not correspond to the text next to it.
2.The images are all of diferent sizes and I would like them to have standard look and be centered is there a way to do that and at which point of the code? Thank you very much
EDIT I have found the method:
dataWithContentsOfURL:options:error:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html
but I don't know how to use it

Why don't you create the images when the image data is downloaded and keep them in the array? Also, you are right to be after the dataWithContentsOfURL:options:error: method. Given that you keep the image names in the dic dictionary, the code would look like this:
NSMutableString *photourl=[[NSMutableString alloc] initWithString:url_image];
[photourl appendString:[dic objectForKey:#"photo"]];
//try to create the image
NSError* err = nil;
UIImage* img = nil;
NSData* tempData = [NSData dataWithContentsOfURL:[NSURL URLWithString:photourl] options:NSDataReadingMappedIfSafe error:&err];
if (!err) {
// image data loaded, create image
img = [UIImage imageWithData:tempData];
} else {
// image data could not be loaded, display error
NSLog(#"%#", err);
// put the default image in the array
img = [UIImage imageNamed:#"icon72.png"];
}
[photoSmallImage addObject:img];
And then in the table view delegate:
cell.imageView.image = [photoSmallImage objectAtIndex:indexPath.row];
As for the second part of your question, you may want to have a look at the contentMode property of UIView class. The default is scale to fill. By manipulating this property on the cell.imageView, you can achieve the effect that you desire.

Related

UITableView custom cell can't scroll fluent,as database block my main thread

I used multi column tableView !For one screen I have 16 cells,and If I have 3000 data ,and I got the thumbnail image from database( I use the open source -FMDB),and when load this table,I open only one thread to download the thumbnail, and save to database.
When the cell is visible,I got thumbnail from db,if it had been downloaded.
But I found that I got data from database is very slow,about 0.15~1.3 seconds for one cell, and I have 16 cell for one screen. So it block my main thread?
Any suggestion to help me solve the problem?
Thanks in advance.
This is the code I get thumbnail~
-(NSData *)queryVideoSmallThumbnailData:(NSString *)theSourceUrl
{
if(theSourceUrl == nil)
return nil;
NSString *query = #"SELECT SMALL_THUMBNAIL_DATA FROM FIELDS WHERE SOURCE_URL";
query = [query stringByAppendingString:#"=\""];
query = [query stringByAppendingString:theSourceUrl];
query = [query stringByAppendingString:#"\""];
NSData * data = nil;
FMResultSet *rs = [database executeQuery:query];
while ([rs next])
{
data = [rs dataForColumn:#"SMALL_THUMBNAIL_DATA"];
break;
}
[rs close];
return data;
}
This is the table view refresh image code.
image = [thumbCache getThumbFromCache:record.sourceUrl]
if (image == nil)
{
DBVideoThumb *thumbDB = [[DBManager getInstance] getDBVideoThumb];
NSData *data = [thumbDB queryVideoSmallThumbnailData:record.sourceUrl];
image = [UIImage imageWithData:data];
if (image != nil)
[thumbCache addThumbToCache:record.sourceUrl image:image];
}
The size of your database may affect your query speed. So, when your table View dragging,you may change your thumbnail to small one. a blur one, as small as possible.
Create a Index for your database as can improve your query speed from n to log2 n.
For example :Create index urlIndex on Fields(url);
If you're using this FMDB I suggest you (re)read the instructions. The author points out that using a single instance of FMBD on multiple threads is a bad idea. This is a common problem for anything that has to maintain data integrity.
Assuming you are using FMDB, have you tried creating multiple instances of FMDB on the same store, one for each thread? You can apply this to other answers posted here, inside an asynchronous block. Remember to close each instance when you're done and check that there is a lock on the database to ensure atomic writes.
If you're open to other solutions, Core Data might be of use if you're modelling an object graph you'd like to persist.
I faced same problem during my app development but I used following code to solve this issue. May be its help you. If you get any trouble let me know.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *imageData ;
imageData = [UICommonUtils imageDataFromString:profile.Photo];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
if([imageData length] > 1) {
cell.ProfileImage.image = [UIImage imageWithData:imageData];
} else {
cell.ProfileImage.image = [UIImage imageNamed:kDefaultProfileImage];
}
});
imageData = nil;
});
I think [UIImage imageWithData:filename] may be a cause. its performance, as I believe, is far lower than imageNamed:. or imagewithContentOfFile:. My solution is saving it as file in another thread, then show it in main thread after saving done. if the video is not changed, next time will directly show file without query database.

How know whether image is coming from cache or form url in SDWebImage?

I am using SDWebImage for loading a list of images and it was really good but while loading images next time it's loading image from cache if the url is same. But I need to know its coming form cache or web. Any help would be greatly appreciated.
Check SDWebImageManager, it has 2 versions of functions to check whether an URL is already cached or not:
- (BOOL)diskImageExistsForURL:(NSURL *)url;
There's also a version with a block which executes after the check. Hope this helps!
You can check the cache to see if the image in question has already been downloaded like so:
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:URL];
UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
use your url
SDWebImageManager *manager = [SDWebImageManager sharedManager];
UIImage *cachedImage = [manager imageWithURL:url];
if (cachedImage)
{
[button setImage:cachedImage];
//image is cashed
}
else
{
[manager downloadWithURL:url delegate:self];
}
and then implement delegate function
- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage*)image {
[button setImage:image];
// new image
}

how to load few images from URL individually to scroll view ? objective-c

i have this scroll view, that I'm loading into him few images from URL.
the problem is that the scroll view don't show any of them until that all loaded.
i want to show every image the moment i finished loading her.
my code looks like this:
-(void)loadPhotosToLeftscroll{
for (int count = 0 ; count < [leftPhotoArray count]; count++) {
NSLog(#"nextPhotoHight: %f",nextLeftPhotoHight);
NSMutableDictionary *photoDict;
photoDict = [leftPhotoArray objectAtIndex:count];
float photoHight = [[photoDict objectForKey:#"photos_height"]floatValue];
float photoWide= [[photoDict objectForKey:#"photos_width"]floatValue];
NSString *photoPath = [photoDict objectForKey:#"photos_path"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:photoPath]];
UIImage *image = [[UIImage alloc] initWithData:imageData];
UIImageView *photoView = [[UIImageView alloc]initWithFrame:CGRectMake(10 , nextLeftPhotoHight, photoWide, photoHight )];
[photoView setImage:image];
[photoView.layer setMasksToBounds:YES];
[photoView.layer setCornerRadius:6];
nextLeftPhotoHight = photoView.frame.size.height + photoView.frame.origin.y + 10;
[leftBlockScroll addSubview:photoView];
}
}
You better use a asynchronous way to do that.
Relative topic is NSURLConnection, UIImageView.
I have done something similar before.
1. Create a new model inherit to UIView
2. This model will have a UIImageView, NSData
3. When u init the model, pass in a URL
4. Use NSURLConnection to send out AsynchroizedRequest
5. By using NSURLConnection delegate, you will finally get the Data of the image
6. Init a UIImage with these data
7. Init The UIImageView with this Image
8. Add this imageview to this model or directly pointing this model to the imageview
Feel free to ask for more detail :)

Populating Data from NSMutableArray in iPhone

I have three arrays and I have copied all these arrays into a single array. All these three arrays are arrays of dictionaries.All arrays has a field called picture, but that pictures is coming from different sources- URL in one array, data in other and files in the third one.
Say, Array1 has dictionaries with a key - picture and its loaded from NSURL.
Similarly, Array2 and Array3 has dictionaries with same key name - picture and loaded from ContentofFiles and NSData.
Now, I want to populate tableview, of course,m having Custom UITableViewCell, it has image view as its content view. To load that image, what should I do.
I was doing this thing..
NSURL *url = [NSURL URLWithString:[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"]];
cell.contactImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
But, this will crash if cell.contactImageView.image don’t receive image from NSURL.So, what should I do? Any help, will be appreciated
But,
all you is to check if the received image is null and if it is, then set a template photo image called no photo like a photo on facebook when no profile picture is selected
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
if (img)
cell.contactImageView.image = img;
else
cell.contactImageView.image = [UIImage imageNamed:#"no_photo.png"];
If these images are retrieved from the net, i would suggest not using [NSData dataWithContentsOfURL:].
You should be using a non blocking method, that loads images asynchronously. Using this method on numerous rows in a table will cause performance issues.
Here's my recommendation , use the SDWebImage Library . Easy to use, and even easier to install.
Once you add the library to your project, simply #import the UIImageView+WebCache.h class usage example is below.
[cell.contactImageView.image setImageWithURL:[NSURL URLWithString:[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
You can add one more key in dictionary which will specify from where to take photo and accordingly you can provide image to cell.contactImageView, if you want to provide image from different sources.
Thanks a lot buddies for your Quick reply,especially #skram, due to your suggestion,my tableview performance has increased much. the Question, that I have asked,the better answer that I have thought of is using iskindofClass. If image is coming from any class, on a condition ,we can check from where that image was coming and populate our image accordingly.
if ([[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"] isKindOfClass:[UIImage class]])
{
cell.contactImageView.image = [[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"];
}
else if ([[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"] isKindOfClass:[NSString class]])
{
cell.contactImageView.image = [[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"];
}
else if([[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"] isKindOfClass:[NSURL class]])
{
[cell.contactImageView setImageWithURL:[NSURL URLWithString:[[contactList objectAtIndex:indexPath.row] objectForKey:#"picture"]]placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
Now, I’m able to populate the tableview properly.Once again thanx to scram.

iphone app - load cell image from XML element

I need some help to figure this out ..
I am getting data from the XML, one of the elements is the Image file Name "Icon1.png", images are save on my resources locally, at the moment I can load the icon1.png with this code
// retrieve an image
NSString *imageicon = [[NSBundle mainBundle]
pathForResource:#"icon2" ofType:#"png"];
UIImage *cellicon = [[UIImage alloc] initWithContentsOfFile:imageicon];
//set the image on the table cell
cell.imageView.image = cellicon;
but i want to load the icon file name from the XML element
<dimage>icon2.png</dimage>
how can I load the image to my cell ? - Solved
part 2 - selected row go to bclass description view controller,
-(void)viewDidLoad {
self.title = bclass.title;
[self.textView setText:bclass.description];
[self.destag setText:bclass.descimg];
}
at the moment "discing" is just showing the image name (UItextView), but i want to display the image on a UIImageView.
Thanks for your help.
Hernando.
Read the image file name from XML file to a NSString, and then create an UIImage using the
+(UIImage*)imageNamed:(NSString*)name class method of an UIImage object:
Example
NSString *imageName = ... read the name from xml.
cell.imageView.image = [UIImage imageNamed:imageName];