Asynchronous loading of images? - ios

How can I load images asynchronously? This is currently what I'm doing (borrowed from open source code for loading an image thumbnail):
- (UIImage*)thumbnailListView:(ThumbnailListView*)thumbnailListView
imageAtIndex:(NSInteger)index
{
NSURL* url = [NSURL URLWithString:[recommendedArray objectAtIndex:index]] ;
// [[cell grid_image] setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:url]]];
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
BOOL isImageLoaded = YES;
UIImage *bookImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#", docPath, [[recommendedArray objectAtIndex:index] lastPathComponent]]];
if(bookImage == nil)
isImageLoaded = NO;
if(!isImageLoaded){
UIImage *thumbnailImage =[UIImage imageNamed:#"App-icon-144x144.png"];}
else{
UIImage *thumbnailImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[recommendedArray objectAtIndex:index]]]]];
return thumbnailImage;
}
}
I tried adding the following to the method, but it's producing an error for the NSURL:
dispatch_queue_t imageLoadQueue = dispatch_queue_create("com.g.load", NULL);
dispatch_async(imageLoadQueue, ^{
//Wait for 5 seconds...
usleep(1000000);
NSArray *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
for(int k=0; k < [images count];k++){
NSLog(#"Loading %d Image", k);
NSString *imgURL = [images objectAtIndex:k];
NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imgURL]];
[imgData writeToFile:[NSString stringWithFormat:#"%#/%#", docPath, [imgURL lastPathComponent]] atomically:YES];
}
[[self collectionView] reloadData];
NSLog(#"DONE WITH ALL IMAGES");
});
error
[NSURL length]: unrecognized selector sent to instance 0x12ea7240
2013-04-18 11:18:35.456 AssamKart[3084:14d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURL length]: unrecognized selector sent to instance 0x12ea7240'

Inside the method->
- (UIImage*)thumbnailListView:(ThumbnailListView*)thumbnailListView
imageAtIndex:(NSInteger)index
Use this->
NSURLConnection *aNSURLConnection= [[NSURLConnection alloc]initWithRequest:<#(NSURLRequest *)#> delegate:<#(id)#> startImmediately:<#(BOOL)#>];
and the inside the delegate
- (void)connectionDidFinishLoading:(NSURLConnection *)connection; get the image data and implement your logic and here u shall call again the
- (UIImage*)thumbnailListView:(ThumbnailListView*)thumbnailListView
imageAtIndex:(NSInteger)index
method recursively till your recommendedArray is exhausted.

just do like this,
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int k=0; k<[images count]; k++) {
NSString *imgURL = [images objectAtIndex:k];
NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString:imgURL]];
[data writeToFile:[NSString stringWithFormat:#"%#/%#", docPath, [imgURL lastPathComponent]] atomically:YES];
}
});

you can use SDWebImage for downloading ur images from the internet and use the method:
[imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];

Use AsyncImageView.
https://github.com/nicklockwood/AsyncImageView
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(Your Frame)];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:URL]];
[AsyncImageLoader defaultCache];
[[AsyncImageLoader sharedLoader]loadImageWithURL:URL target:self success:#selector(successSelector) failure:#selector(failureSelector)];

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];
}

Getting image from my dictionary is causing an "unrecognized selector" error

I'm parsing JSON file in iOS and I'm getting elements in a tableview but when I created (prepareForSegue) to get tableview element I can't get image and I get this error:
unrecognized selector sent to instance 0x7fa3427c5b20 2016-05-05 05:08:43.287 MovieClub[4845:212195] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString size]: unrecognized selector sent to instance 0x7fa3427c5b20'
in this line of code:
self.postt.image =[self.actuatlitDetail objectForKey:#"poster_240x342"];
If [self.actuatlitDetail objectForKey:#"poster_240x342"] returns NSURL you can use
NSURL *imageURL = [self.actuatlitDetail objectForKey:#"poster_240x342"];
self.postt.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
If it is NSString then represent URL then
NSString *imageURLString = [self.actuatlitDetail objectForKey:#"poster_240x342"];
self.postt.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURLString]]];
You can load image in background
__weak typeof(self) weakSelf = self;
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(aQueue, ^{
NSURL *imageURL = [weakSelf.actuatlitDetail objectForKey:#"poster_240x342"];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.postt.image = image;
});
});
its url value of actuatlitDetail, get the below code,
NSString *imageurl = [self.actuatlitDetail objectForKey:#"poster_240x342"];
NSString *encodedUrlString = [imageurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *imageURL = [NSURL URLWithString: encodedUrlString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *imag = [UIImage imageWithData:imageData];
self.postt.image = imag;
hope its helpful
Set Image Path Then Follow this :
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"Your image url string"]];
UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageWithData: imageData]];

How to use nscache to download image from api.?

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];
});
}
}];
});

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");
}
});
});
}

NSOperationQueue Issue

I have a code that i used as a image downloder in ios 6 but when i use same code in different application that used ios 5 it gives me error NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance hear is the code that i am using
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl = [NSURL URLWithString:ImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *images = nil;
if (imageData)
images = [UIImage imageWithData:imageData];
if (images){
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
Can anybody tell me what i am doing wrong coz this code is help me a lot when downloading image separately. Thank you
PS Whole function that i am using
-(void) setScrollView:(UIScrollView *)scrollview :(NSArray *)contentArray{
int x = 0;
int i = 0;
NSString *ImageURL=#"http://www.online-image-editor.com/styles/2013/images/example_image.png";
for(NSDictionary *str in contentArray){
UIImageView *imageV = [[UIImageView alloc ] initWithFrame:CGRectMake(x, 0, 200,125)];
#try {
ImageURL = [str objectForKey:#"image"];
}
#catch (NSException * e) {
NSLog(#"Exception: %#", [e description]);
}
imageV.userInteractionEnabled = YES;
ImageTapGesture *singleTap = [[ImageTapGesture alloc] initWithTarget:self action:#selector(tapDetectedMain:)];
singleTap.newItem = str;
singleTap.currentItem = i ;
singleTap.numberOfTapsRequired = 1;
[imageV addGestureRecognizer:singleTap];
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(x,125,200,20)];
[title setFont:[UIFont systemFontOfSize:11]];
title.numberOfLines = 2;
title.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[title setBackgroundColor:[UIColor blackColor]];
[title setTextColor:[UIColor whiteColor]];
title.text = [NSString stringWithFormat:#" %#",[str objectForKey:#"title"]];
x += title.frame.size.width+2;
UIImage *cachedImage = [self.imageCache objectForKey:ImageURL];
if (cachedImage){
imageV.image = cachedImage;
}
else{
imageV.image = [UIImage imageNamed:#"vdo.png"];
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl = [NSURL URLWithString:ImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *images = nil;
if (imageData)
images = [UIImage imageWithData:imageData];
if (images){
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
}
[scrollview addSubview:imageV];
[scrollview addSubview:title];
}
scrollview.contentSize = CGSizeMake(x, scrollview.frame.size.height);
i++;
}
You should definitely check the ImageURL you are sending into the operation. It seems, this ImageURL is [NSNull null].
If it is a local variable, is it declared as __block NSString *ImageUrl?
pls try this code:
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl ;
if((ImageURL!=nil)&&(![ImageURL isKindOfClass:[NSNull class]]))
{
imageUrl= [NSURL URLWithString:ImageURL];
}
NSData *imageData;
if((imageUrl!=nil)&&(![imageUrl isKindOfClass:[NSNull class]]))
{
imageData = [NSData dataWithContentsOfURL:imageUrl];
}
UIImage *images = nil;
if((imageData!=nil)&&(![imageData isKindOfClass:[NSNull class]]))
images = [UIImage imageWithData:imageData];
if((images!=nil)&&(![images isKindOfClass:[NSNull class]]))
{
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
Hope this will help you.

Resources