How to use sdimage in uiimage caching? - ios

Anyway to handle or display UIImage with caching and with placeholder?
I have found one answer from stack exchange but it didnot work for me given below the link :
Best way to cache images on ios app?
Notes: I dont have any URL because i get image object of PHIMAGE asset library.

You can use SDWebImage
It is very simple to display and cache image.
[imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.image_url.com"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];

You can use a very usefull library called SDWebImage
SDWebImage automagically cache all your images when you provide a valid URL with the sd_setImageWithURL. So the next time you call it, will use the cache system instead of re-download the image.
Example to implement in a UIImageView from their github:
// Here we use the new provided sd_setImageWithURL: method to load the web image
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];

There was a problem of smoothing an all image while scroll the table but there is an issue of reload the cell not the caching problem i solved this issue.
I get an image one by one from local identifier which is provided by PHAsset framework and display that image into cell.
For reference Code:
PHFetchResult *savedAssets = [PHAsset fetchAssetsWithLocalIdentifiers:#[your local identifier] options:nil];
[savedAssets enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
//this gets called for every asset from its localIdentifier you saved
PHImageRequestOptions * imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.synchronous = YES;
imageRequestOptions.deliveryMode = PHImageRequestOptionsResizeModeFast;
[[PHImageManager defaultManager]requestImageForAsset:asset targetSize:CGSizeMake(50,50) contentMode:PHImageContentModeAspectFill options:imageRequestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(#"You get an image from result");
}];
}];

Related

Very slow to load images from PHAsset

I am using following code to fetch images and AVAsset from PHAsset. Here are two arrays in code :
galleryArr : to store images for collection view.
mutableDataArr : store images (for image asset) and videos (for AVAsset) to upload on server
Its very slow to fetch all images from PHAssets array.
I googled about this, most of people says remove this line [options setSynchronous:YES]; but if I remove this line then completion is called twice and array duplicates the objects (as objects are appended in array within completion).
for (int i = 0; i < assets.count; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
options.resizeMode = PHImageRequestOptionsResizeModeExact;
[options setNetworkAccessAllowed:YES];
[options setSynchronous:YES];
PHImageManager *manager = PHImageManager.defaultManager;
PHVideoRequestOptions *videoOptions = [[PHVideoRequestOptions alloc] init];
videoOptions.networkAccessAllowed = YES;
__weak typeof(self) weakSelf = self;
if (assets[i].mediaType == PHAssetMediaTypeVideo) {
[manager requestAVAssetForVideo:[assets objectAtIndex:i] options:videoOptions resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
if ([asset isKindOfClass:[AVURLAsset class]])
{
[weakSelf.mutableDataArr addObject:asset];
}
}];
}
[manager requestImageForAsset:[assets objectAtIndex:i]
targetSize: CGSizeMake(1024, 1024) //PHImageManagerMaximumSize
contentMode:PHImageContentModeAspectFit
options:options
resultHandler:^(UIImage *image, NSDictionary *info) {
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (assets[i].mediaType != PHAssetMediaTypeVideo) {
[weakSelf.mutableDataArr addObject:image];
}
[galleryArr addObject:image];
if (i+1 == assets.count) {
[SVProgressHUD dismiss];
[weakSelf.galleryCollectionView reloadData];
}
});
}
}];
});
}
Any suggestion please?
Just one thought, it looks like you are loading all the images from the array before removing your progress HUD and displaying the gallery. As the number of images could be very large and presuming you are using a collection view or similar, that's quite an overhead before anything is displayed.
I did something like this a while ago and instead of looping through the array and loading everything up front, I let the cells request images as they needed them. This makes it very fast and efficient as cells can display immediately with a loading icon, then flip to the image when it was available. Efficiency comes from only loading images the user is actually going to see.
To make things performant, and by performant I mean I could scroll as fast as I liked without the display freezing, each cell would first check an in memory cache for the image, then trigger a request for an image on a background thread.
When the image was returned, the cell would add it to the in memory cache and then if the cell had not being reused for a different image (due to fast scrolling) it would display the image.
Further, I also used a NSCache for the in memory cache so that if the app started to use a lot of memory, images would be automatically dropped and reloaded the next time a cell wanted one.
The summary is to use a memory aware cache, and only load what you actually need.

Images are not correct in collection view cells

I have used sdwebimage for caching images.
Now imagesArr is array of images i want to display first for all cells.
I am downloading the image in background and then saving into disk so when i want those images in offline mode i can have from the disk.
But in some cases when i scroll the collectionView the images are set incorrect and then again scrolling the images appear to be correct.
This is the below code which i have implemented in cellForItemAtIndexPath. I have tried to debug but seems the data is coming correct and the image name is also correct.
Also the collectionView is laggy in scroll. Please help me to find the issue.
if(imagesArr.count>0)
{
ClothesImage *obj_image=[imagesArr objectAtIndex:0];
NSString *fileName = [stringPath stringByAppendingFormat:#"/%#",obj_image.imagePath];
NSLog(#"FILES NAMES %# ", obj_image.imagePath);
NSData *data = [NSData dataWithContentsOfFile:fileName];
if(data!=nil){
UIImage *image=[UIImage imageWithData:data];
cell.imgProduct.image=image;
}
else{
NSString *offline=[user_defaults objectForKey:#"offline"];
if([offline integerValue]==0){
cell.imgProduct.image=[UIImage imageNamed:#"noImageThumb"];
NSString *str_url=[NSString stringWithFormat:#"%#/%#",WEB_THUMB_IMAGE,obj_image.imagePath];
str_url = [NSString stringWithFormat: #"%#",[str_url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[cell.imgProduct setImageWithURL:[NSURL URLWithString:str_url] placeholderImage:[UIImage imageNamed:#"noImageThumb"] options: SDWebImageRefreshCached];
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:[NSURL URLWithString:str_url] options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) {
NSString *stringPathImage = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:#"WebThumb"];
NSData *data = [NSData dataWithData:UIImagePNGRepresentation(image)];
NSString *fileName = [stringPathImage stringByAppendingFormat:#"/%#",obj_image.imagePath];
[data writeToFile:fileName atomically:YES];
NSLog(#"DOWNLOADED IMAGE %#",fileName);
}];
}
else
{
cell.imgProduct.image=[UIImage imageNamed:#"noImageThumb"];
}
}
} else{
cell.imgProduct.image=[UIImage imageNamed:#"noImageThumb"];
}
I think there are a few ways you could improve this.
It seems like you're duplicating a lot of the work that SDWebImage will do for you. That library will cache images and fetch them on demand. You should look at having that library prefetch your files into cache, rather then yourself attempting to prefetch and write them out to disk. Ultimately by the time you are in -cellForRowAtIndexPath, you only need two cases: One for setting an image when the device is offline, and then another that will either fetch or set the image from cache, which SDWebImage provides for you:
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
That's it. All the caching and switching you're doing isn't necessary. The other thing to be sure of is in your cell subclass method -prepareForReuse, you are nilling out the image.

How to load an image from URL in app Extension?

I have implemented an app extension for my application, but i am facing an issue when trying to load an image from a URL into an imageView.
I tried to use PAImageView and UIImageView but both with failure.
The code that i was using for PAImageView is the following:
[self.imageView setImageURL:[NSURL URLWithString:#"https://blabblaLogo.jpg"]];
self.userImageView.clipsToBounds = YES;
and tried to use SDWebImage for UIImageView with the following:
[self.imageView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:#"default.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
}];
and the image doesnt appear in both cases. Note that a default image from assets is displayed correctly without any issue.
Is it possible to load an image from a URL in an app Extension? and how can we achieve that?
Thank you.
Am using something like this and it's work good until this issues fixed
cell.avatar.image = [UIImage imageNamed:#"selection-box_emty.png"];
// Load the image with an GCD block executed in another thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:Arr[indexPath.row][#"avatar"]]];
if (data) {
UIImage *offersImage = [UIImage imageWithData:data];
if (offersImage) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *offersImage = [UIImage imageWithData:data];
cell.avatar.image = offersImage;
});
}
}
});
I faced a similar problem, put breakpoints into into library and problem apparently was App Tranport Security. We need separate App Transport Security Settings for every extension we add
Try This in your Image url
If image url contain any space it will add %20 and work fine
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

iOS: TableView with multiple Images per Row (SDWebImage)

I am a bit desperated about my sectioned tableview. I use a custom UITableViewCell with 4 images like the one below:
I try to load the images via SDWebImage for each cell.
The loading procedures are all done in my custom UITableViewCell - not in the UITableViewController. From the cellForRowAtIndexPath i just call [cell setup] which executes the following code in the current cell:
NSArray *imageViews = [NSArray arrayWithObjects:self.imageView1, self.imageView2, self.imageView3, self.imageView4, nil];
for (int i = 0; i < self.products.count; i++) {
Product *currentProduct = [self.products objectAtIndex:i];
UIImageView *currentImageView = [imageViews objectAtIndex:i];
NSString *thumbURL = [[CommonCode getUnzippedDirectory] stringByAppendingPathComponent:currentProduct.collectionFolderName];
thumbURL = [thumbURL stringByAppendingPathComponent:thumbFolder];
thumbURL = [thumbURL stringByAppendingPathComponent:currentProduct.product_photo];
[currentImageView setContentMode:UIViewContentModeScaleAspectFit];
[currentImageView setImageWithURL:[NSURL fileURLWithPath:thumbURL]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
The images are all stored in the documents directory and are not greater than max. 500Kb.
Problem:
My Problem is that when I scroll through my tableview it suddenly crashes and I don't know why. Enabling a symbolic breakpoint for all exceptions shows that it crashes because of one line in SDWebImage. Unfortunately there isn't a debugger output: (It crashes where the image is allocated)
UIImage *image = nil;
if ([imageOrData isKindOfClass:[NSData class]])
{
image = [[UIImage alloc] initWithData:(NSData *)imageOrData];
}
I also tried to load images via dispatch_asnyc with a similar result. Is it possible that it has something to do with concurrent file operations?
Additionally I get Memory Warnings when I scroll very fast so that I have to clear the cache of SDWebImage. At the same time it stops at the code line in SDWebImage mentioned above.
I already searched the web for 2 days now and I didn't find something useful. I would be glad for some hints to fix this problem. If somebody needs additional data such as crash reports or something, just let me know and I will provide them quickly.
I have meet the same problem, But I solve it like below temporarily, but it cause memory problem especially on iPhone 4s
NSArray *arrImgs = cellModel.thumbnails_qqnews;
if (arrImgs.count > 0) {
[self.imgView.subviews enumerateObjectsUsingBlock:^(__kindof UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj sd_setImageWithURL:[NSURL URLWithString:arrImgs[idx]] placeholderImage:[UIImage imageNamed:#"placeholdImage"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image != nil) {
obj.image = [UIImage cutImageWithTargetSize:[NEMulTiNewsCell getImgSize] image:image];
}
}];
}];
}
I think multi images download is illogical,but the method i think is download multi images then draw multi images in one image then display, but it may create large number line of code.

Slow loading the images from URL in UITAbleView.

I'm loading the images from URL in UITableView. But it's very slow when loading an view. Here's an example,
UIImage *image = nil;
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://calcuttans.com/palki/wp-content/uploads/2009/02/kidscover-small.png"]]];
In Table view, UIButton i'm setting the background image.
Please Can you provide the sample.
FYI : I'm used the LazzyTable sample program but it's not much helpful. Can you suggest any other samples.
Load image asynchronously
NSURL* url = [NSURL URLWithString:#"http://calcuttans.com/palki/wp-content/uploads/2009/02/kidscover-small.png"];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
NSImage* image = [[NSImage alloc] initWithData:data];
// do whatever you want with image
}
}];
There are some open source libraries available for this:
HJCache
SDWebImage
These libraries download image in a asynchronous manner and cache it for further use.
Try to implement AFNetworking. It uses async requests to download the image, you are currently blocking your view with every download.
You can then use an AFImageRequestOperation to download your image.
if you load the image all download from the internet every time , it must be very slow.
I think you shuold exist your download image to the filePath , and when you will load the image , you can check whether the image has been downloaded before , if not ,then download. if it has been downloaded , you can use imageWithContentsOfFile: method to load the image
//Make use of dispatch queue for faster processing of data. add this in viewDidLoad
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData * data=[NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
[self performSelectorOnMainThread:#selector(setImage:) withObject:data waitUntilDone:YES];
});
//once data is got set the image and reload tableview
-(void)setImage:(NSData *)responseData
{
image = [UIImage imageWithData:responseData];
[tableView reloadData];
}
maybe you can use asihttprequest to lazy load images. use ASINetworkQueues
You've to use NSOperationQueue to make your tableview efficient.
Check this icodeblog tutorial and raywenderlich tutorial
Have a look at this tutorial. It helped me a lot. When I was using it I was quite new to iOS in general and it was helpful not only with respect to loading images from the web.
http://www.markj.net/iphone-asynchronous-table-image/
With AFNetworking it is more easy.
//AFNetworking
#import "UIImageView+AFNetworking.h"
[cell.iboImageView setImageWithURL:[NSURL URLWithString:server.imagen] placeholderImage:[UIImage imageNamed:#"qhacer_logo.png"]];

Resources