How to use nscache to download image from api.? - ios

I have a UIImageview in UICollectionview cell and parse the image data from api and add to UIImageview. Now everything is going perfect but there is some problem I face during scroll down, when I tried to scroll UICollectionview cell its going hang.
Now I need to use NSCache to download image and than add it to UIImage, but I am unable to do this task I am stuck somewhere in my code, I don't know where. Please look at my code.
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
OneTimeCell *cell = (OneTimeCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.selected = YES;
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
cell.productname.text = [[productname objectAtIndex:indexPath.row] objectForKey:#"product_name"];
cell.productnumber.text = [[productname objectAtIndex:indexPath.row] objectForKey:#"id"];
NSString *image = [[productname objectAtIndex:indexPath.row] objectForKey:#"image" ];
NSLog(#"image %#", image);
NSURL *baseURL = [NSURL URLWithString:#"http://dev1.brainpulse.org/ecoware1//app/webroot/img/uploads/Product/thumb/"];
NSURL *url = [NSURL URLWithString:image relativeToURL:baseURL];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage * productimage = [UIImage imageWithData:imageData];
NSURL *absURL = [url absoluteURL];
NSLog(#"absURL = %#", absURL);
if (productimage) {
cell.productimage.image = productimage;
}
else
{
cell.productimage.image = [UIImage imageNamed:#"icon_1.png"];
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:image relativeToURL:baseURL];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImageView *image = nil;
if (image) {
[self.imageCache setObject:image forKey:imageData];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
OneTimeCell *cell =[collectionView cellForItemAtIndexPath:indexPath];
if (cell) {
cell.productimage.image = image;
}
}];
}
}];
}
return cell;
}

in your code line 10 you fetching image on mainthread that is why your cell got stuck . . .Please replace that code with this one
Replace this code
NSString *image = [[productname objectAtIndex:indexPath.row] objectForKey:#"image" ];
NSLog(#"image %#", image);
NSURL *baseURL = [NSURL URLWithString:#"http://dev1.brainpulse.org/ecoware1//app/webroot/img/uploads/Product/thumb/"];
NSURL *url = [NSURL URLWithString:image relativeToURL:baseURL];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage * productimage = [UIImage imageWithData:imageData];
NSURL *absURL = [url absoluteURL];
NSLog(#"absURL = %#", absURL);
With This one
NSString *image = [[productname objectAtIndex:indexPath.row] objectForKey:#"image" ];
NSLog(#"image %#", image);
NSURL *baseURL = [NSURL URLWithString:#"http://dev1.brainpulse.org/ecoware1//app/webroot/img/uploads/Product/thumb/"];
NSURL *url = [NSURL URLWithString:image relativeToURL:baseURL];
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(q, ^{
NSData * imageData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage * productimage = [UIImage imageWithData:imageData];
});
});

NSURL *url = #"................";
ImageRequest *request = [[ImageRequest alloc] initWithURL:url];
UIImage *image = [request cachedResult];
if (image) {
// Set the image if exist
} else {
[request startWithCompletion:^(UIImage *image, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if(image) {
cell.productimage.image = productimage;
}else {
// Set any placeholder image here.......
}
});
}];
}

NSString *image = [[productname objectAtIndex:indexPath.row] objectForKey:#"image" ];
NSLog(#"image %#", image);
NSURL *baseURL = [NSURL URLWithString:#"http://dev1.brainpulse.org/ecoware1//app/webroot/img/uploads/Product/thumb/"];
NSURL *url = [NSURL URLWithString:image relativeToURL:baseURL];
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(q, ^{
//NSData * imageData = [NSData dataWithContentsOfURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if(data)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIImage * productimage = [UIImage imageWithData:data];
});
}
}];
});

Related

Need to set the image from URL without any blink. Read the description to know the complete scenario

I am uploading the image from the ImagePicker and once the image is upload on the server I show it from URL. So from local image to URL image, there comes a blink, which I want to avoid but I am unable to fix it. Any suggestion will be really helpful. I am adding the code below:
- (void)setDataOnCell:(NSDictionary *)dict {
self.messageTimeLabel.text = [CommonUtils checkForNUllValue:[dict valueForKey:#"msg_time"]];
if (![[CommonUtils checkForNUllValue:[dict valueForKey:#"msg_status"]] isEqualToString:#"Read"]) {
self.messageTickImageView.image = [UIImage imageNamed:#"check_delivered_icon"];
self.messageStatusLabel.textColor = [UIColor colorWithRed:166.0f/255.0f green:166.0f/255.0f blue:166.0f/255.0f alpha:1.0];
}
else {
self.messageTickImageView.image = [UIImage imageNamed:#"check_read_icon"];
self.messageStatusLabel.textColor = [UIColor colorWithRed:254.0f/255.0f green:223.0f/255.0f blue:224.0f/255.0f alpha:1.0];
}
self.messageStatusLabel.text = [CommonUtils checkForNUllValue:[dict valueForKey:#"msg_status"]];
if ([[NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment_type"]] isEqualToString:#"local_img"]){
self.messageImageview.image = [dict valueForKey:#"attachment"];
}
else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#", [NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment"]]]];
NSData *urlData = [NSData dataWithContentsOfURL:imageURL];
//This is your completion handler
dispatch_sync(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:urlData];
self.messageImageview.image = image;
});
});
}
}
first of all you need to set a default image on this image view after that you call image by url and set on this
NSOperationQueue *queueThumbnl = [[NSOperationQueue alloc] init];
[queueThumbnl setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
[queueThumbnl addOperationWithBlock:^{
// Background work
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#", [NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment"]]]];
NSData *urlData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:urlData];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.messageImageview, #"messageImageview", urlData, #"imageData", nil];
[self performSelectorOnMainThread:#selector(mainThreadUIUpdate:) withObject:dict waitUntilDone:YES];
// [self updateThumbnailOnMainThread:anItem setImageTo:cell];
}];
-(void)mainThreadUIUpdate:(NSDictionary *)dict
{
UIImageView *messge = [dict objectForKey:#"messageImageview"];
UIImage *image = [dict objectForKey:#"image"];
[messge.imageView setImage:image];
[cell.imageView setNeedsDisplay:YES];
}

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) block doesn't execute

I have a block to download an convert an image to UIImage. this is my code
-(UIImage *)GetProfileImage
{
NSString *strimgBaseUrl=[[[NSBundle mainBundle] infoDictionary] objectForKey:#"BaseImageURL"];
NSString *strFilePath=[dm.dictUserProfile valueForKey:#"ImagePath"];
NSString *strImgURL=[NSString stringWithFormat:#"%#%#",strimgBaseUrl,strFilePath];
__block UIImage *imgProf=nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *imageURL = [NSURL URLWithString:strImgURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
imgProf= image;
if(image!=nil){
imgProf=image;
}
});
});
return imgProf;
}
But this block is never execute.It goes to return __block UIImage *imgProf=nil; Why is that? Please help me.
Thanks
Code is working ok. This is the purpose of dispatch_async.
Form the documentation
#function dispatch_async
Calls to dispatch_async() always return immediately after the block has been submitted, and never wait for the block to be
invoked.
This is the opposite of dispatch_sync.
You could change the GetProfileImage like this
- (void)setProfileImageForImageView:(UIImageView *)imageView {
NSString *strimgBaseUrl=[[[NSBundle mainBundle] infoDictionary] objectForKey:#"BaseImageURL"];
NSString *strFilePath=[dm.dictUserProfile valueForKey:#"ImagePath"];
NSString *strImgURL=[NSString stringWithFormat:#"%#%#",strimgBaseUrl,strFilePath];
__block UIImage *imgProf=nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *imageURL = [NSURL URLWithString:strImgURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
imgProf= image;
if(image!=nil){
// imgProf=image;
imageView.image = image;
}
});
});
}
Use a completion block instead, rather than returning from function:
-(void)GetProfileImageWithCompletion:(void (^)(UIImage *profileImage))completionHandler
{
NSString *strimgBaseUrl=[[[NSBundle mainBundle] infoDictionary] objectForKey:#"BaseImageURL"];
NSString *strFilePath=[dm.dictUserProfile valueForKey:#"ImagePath"];
NSString *strImgURL=[NSString stringWithFormat:#"%#%#",strimgBaseUrl,strFilePath];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *imageURL = [NSURL URLWithString:strImgURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
if(image!=nil && completionHandler){
completionHandler(image);
}
});
});
}
And use like this:
[self GetProfileImageWithCompletion:^(UIImage *profileImage)
{
//if image exists assign to image view
}
];

How to get image from json response and display in collection view ios

I am new to iOS and I am getting an image url from json.. Now I want to display it on collection view. I am doing the below code. But not able to display image in collection view .Anybody Can help me out for this?enter code here
// Collection View Code
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return imageArray.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
if(!cell)
{
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UIImageView *myImageView = [[UIImageView alloc]initWithFrame:CGRectMake(50,0, 50, 80)];
myImageView.tag = 101;
[cell.contentView addSubview:myImageView];
}
NSString *myImage = [imageArray objectAtIndex:indexPath.row];
NSString *ImageString = [myImage stringByReplacingOccurrencesOfString:#"" withString:#"%20"];
NSLog(#"Image String %#",ImageString);
NSURL *imageURL = [NSURL URLWithString:ImageString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImageView *img = (UIImageView*)[cell.contentView viewWithTag:101];
img.backgroundColor = [UIColor redColor ];
cell.backgroundView = [UIImage imageWithData:imageData];
return cell;
}
// Json Service
NSDictionary *get = #{#"uid":[uidSave valueForKey:#"uid"],#"pro":proNumber};
NSLog(#"Dictionary Data which is to be get %#",get);
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:get options:kNilOptions error:nil];
NSString *jsonInputString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *post = [[NSString alloc]initWithFormat:#"r=%#",jsonInputString];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"%#",displayCaseUrl]];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:120.0];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSError *error;
NSURLResponse *response;
NSData *responseData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (responseData != nil)
{
jsonDict = (NSMutableDictionary *)[NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSLog(#"Values =======%#",jsonDict);
NSMutableDictionary *imageDict = [jsonDict valueForKey:#"images"];
NSLog(#"Image Dictionary :- %#",imageDict);
imageArray = [imageDict valueForKey:#"image_url"];
NSLog(#"MY Array Image :- %#",imageArray);
// Json Respone from where image is to be get
Image Dictionary :- (
{
"image_url" = "http://zapponomics.net/claimservice/parcelimage/1486154806image0.jpg";
"img_for" = "Front view of parcel";
"pro_number" = orange;
}
)
2015-08-26 10:09:05.806 ClaimCloud[1997:87342] MY Array String :- (
"http://zapponomics.net/claimservice/parcelimage/1486154806image0.jpg"
)
//////// USIng Like this but does not work
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UIImageView *myImageView = [[UIImageView alloc]initWithFrame:CGRectMake(50,0, 50, 80)];
myImageView.tag = 101;
[cell.contentView addSubview:myImageView];
NSString *myImage = [imageArray objectAtIndex:indexPath.row];
[self loadImageFromURL:[NSURL URLWithString:[myImage stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] callback:^(UIImage *image) {
myImageView.image = image;
}];
return cell;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0,200);
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100,80);
}
- (void) loadImageFromURL: (NSURL*) url callback:(void (^)(UIImage *image))callback {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData * imageData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
callback(image);
});
});
}
There is a very good library named SDWebImage which will help you to load the image from a URL.As in the above answer of #poojathorat you are converting the image to data, if the images are of larger size, than you will get the memory problem, but this library will manage the memory also.So in my opinion use this library.
Just drag the SDWebImage folder in your project and import
#import "UIImageView+WebCache.h"
then to load the image from URL use this method
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
it will also manage the cache of images.
And if you don't want to include the library then use this function
- (void) loadImageFromURL: (NSURL*) url callback:(void (^)(UIImage *image))callback {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData * imageData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
callback(image);
});
});
}
And use this function like this
[self loadImageFromURL:[NSURL URLWithString:["yourURL" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] callback:^(UIImage *image) {
yourImageView.image = image;
}]
No need of replacing space by %20.Directly apply by follwing way.
NSString *myImage = [imageArray objectAtIndex:indexPath.row];
NSURL *url = [NSURL URLWithString:myImage];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
cell. myImageView.image = [UIImage imageNamed:img];

How can get any message if Image View can't get image from given URL?

I am fetching URL from web, and I want to show any message if image view can't get image from given URL.
Here is my Code.
NSString * image1 = [WebArray objectForKey:#"image_url"];
NSString * image2 = [[tempArray objectAtIndex:0]objectForKey:#"user_image"];
dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue", NULL);
dispatch_async(imageQueue, ^{
NSURL *url = [NSURL URLWithString:image1];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
NSURL *url1 = [NSURL URLWithString:image2];
NSData *imageData1 = [NSData dataWithContentsOfURL:url1];
UIImage *image11 = [UIImage imageWithData:imageData1];
dispatch_async(dispatch_get_main_queue(), ^{
[user_image setImage:image];
[self.tag_user_img setImage:image11];
});
});
check image view is empty or not using
if(CGSizeEqualToSize(imageView.image.size, CGSizeZero))
{
show alert here....
}
dispatch_async(dispatch_get_main_queue(), ^{
if(!image)
{
// show your message
}
else
{
[user_image setImage:image];
}
});

download image form server then share to instagram

I'm trying to share an image after i download it from the server to instagram, this is the code i`m using to download the image form the server
- (IBAction) DownloadImage:(id)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:sender];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *viewImage = [[UIImage alloc] initWithData:data];
UIImageWriteToSavedPhotosAlbum(img, self, #selector(image:didFinishSavingWithError:contextInfo:), (__bridge void *)(img));
});
});
}
now the image is saved to photo album, how can open it in instagram app directly after it have been downloaded ?
image size is always more than 612x612px
After a while i found the answer and modified it to my code
#property (nonatomic, retain) UIDocumentInteractionController *dic;
- (IBAction) DownloadImage:(id)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:sender];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *screenShot = [[UIImage alloc] initWithData:data];
NSString *imagePath = [NSString stringWithFormat:#"%#/image.igo", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]];
[[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];
[UIImagePNGRepresentation(screenShot) writeToFile:imagePath atomically:YES];
_dic = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:imagePath]];
_dic.delegate = self;
_dic.UTI = #"com.instagram.exclusivegram";
NSURL *instagramURL = [NSURL URLWithString:#"instagram://media?id=MEDIA_ID"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
[self.dic presentOpenInMenuFromRect:self.view.frame inView:self.view animated:YES];
}
else {
NSLog(#"no instagram app found");
}
});
});
}

Resources