Show activity indicator on custom cell button - ios

I have custom cell with button. When tap on button I download video from server. During download I need to show activity indicator, but it does not show activityindicatorview.
Code:
RBFriendChatTableViewCell *Cell = [ tableView dequeueReusableCellWithIdentifier:Identifier];
[Cell.m_btnDownLoad addTarget:self action:#selector(downLoadImage:) forControlEvents:UIControlEventTouchUpInside];
-(void)downLoadImage:(UIbutton *)sender{
indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.center = CGPointMake(5, 5);
[sender addSubview:indicator];
[indicator startAnimating]
NSString *strUrl = [NSString stringWithFormat:#"%#%#",chatImage,[dicChatList objectForKey:#"file"]];
NSURL *url=[[NSURL alloc] initWithString:strUrl];
NSData *movieData = [NSData dataWithContentsOfURL:url];
NSURL *fileURL = [self grabFileURL:[dicChatList objectForKey:#"file"]];
[movieData writeToURL:fileURL atomically:YES];
[m_arrDownloadVideoName addObject:[dicChatList objectForKey:#"file"]];
}

You need to update the UI in main thread, you are downloading the video in the same thread, it should be done in a background Asynch thread, for your current situation following fix might help but its best to do the downloading in background and update the UI once its done.
-(void)downLoadImage:(UIbutton *)sender{
dispatch_async(dispatch_get_main_queue(), ^{
indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle : UIActivityIndicatorViewStyleGray];
indicator.center = CGPointMake(5, 5);
[sender addSubview:indicator];
[indicator startAnimating];
});
NSString *strUrl = [NSString stringWithFormat:#"%#%#",chatImage,[dicChatList objectForKey:#"file"]];
NSURL *url=[[NSURL alloc] initWithString:strUrl];
NSData *movieData = [NSData dataWithContentsOfURL:url];
NSURL *fileURL = [self grabFileURL:[dicChatList objectForKey:#"file"]];
[movieData writeToURL:fileURL atomically:YES];
[m_arrDownloadVideoName addObject:[dicChatList objectForKey:#"file"]];
}

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

get image faster than file URL

I'm creating a stack of images in my viewdidload method. The images are from PFFile's from parse so they contain the fileURL of my image data.
My problem is that these two lines of code are dramatically slowing down my app and killing my user experience:
//get scene object
PFObject *sceneObject = self.scenes[i];
//get the PFFile and filetype
PFFile *file = [sceneObject objectForKey:#"file"];
NSString *fileType = [sceneObject objectForKey:#"fileType"];
//check the filetype
if ([fileType isEqual: #"image"])
{
//get image
NSURL *imageFileUrl = [[NSURL alloc] initWithString:file.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl]; ********** these
imageView.image = [UIImage imageWithData:imageData]; ********************* lines
}
How do I get this image/these images (this is nested in a for loop) more quickly? I've already downloaded my PFObjects that contain the PFFiles and stored them locally.
I guess I really don't understand how file URL's operate.
Thank you.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL *imageFileUrl = [[NSURL alloc] initWithString:file.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
dispatch_get_main_queue(), ^{
imageView.image = [UIImage imageWithData:imageData];
});
});
Have not tested but this is the gist. Get the file loading off the main queue and make it asynchronous. The UI will not be bogged down because as soon as this queue is dispatched it's going to return and keep evaluating the rest of your application.
I am using somethig like this:
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[imageFrame addSubview:activityIndicator];
activityIndicator.center = CGPointMake(imageFrame.frame.size.width / 2, imageFrame.frame.size.height / 2);
[activityIndicator startAnimating];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData * imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:thumb]];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
img.image = image;
[imageOver addSubview:img];
[activityIndicator removeFromSuperview];
});
});

Geting multiple Images from Url In ios

i have code to display a single image from json array data in a UIImageView.
i want to display all images in multiple UIImageViews.
plz suggest me how to loop images to display all.
json array data link:
Here's code from my app
NSString *urlString=[NSString stringWithFormat:#"http://ielmo.xtreemhost.com/array.php"];
NSURL * url=[NSURL URLWithString:urlString];
NSData *data =[NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableArray *json=(NSMutableArray*)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#",[json objectAtIndex:0]);
NSString *imageString=[NSString stringWithFormat:#"%#",[json objectAtIndex:0]];
NSURL * urlone=[NSURL URLWithString:imageString];
NSData *datanew =[NSData dataWithContentsOfURL:urlone];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
[imageView setImage:[UIImage imageWithData:datanew]];
testView = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 300.0f, 300.0f, 200.0f)];
[testView addSubview:imageView];
[self.view addSubview:testView];
NSMutableArray *arr=[[NSMutableArray alloc] init];
NSString *urlString=[NSString stringWithFormat:#"http://ielmo.xtreemhost.com/array.php"];
NSURL * url=[NSURL URLWithString:urlString];
NSData *data =[NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableArray *json=(NSMutableArray*)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%d",[json count]);
NSLog(#"%#",[json objectAtIndex:0]);
NSString *imageString;
for (int i=0; i<[json count]; i++) {
imageString=[NSString stringWithFormat:#"%#",[json objectAtIndex:i]];
[arr addObject:imageString];
}
NSLog(#"%#",arr);
// NSString *imageString=[NSString stringWithFormat:#"%#",[json objectAtIndex:0]];
NSURL * urlone=[NSURL URLWithString:imageString];
NSData *datanew =[NSData dataWithContentsOfURL:urlone];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
[imageView setImage:[UIImage imageWithData:datanew]];
UIView * testView = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 300.0f, 300.0f, 200.0f)];
[testView addSubview:imageView];
[self.view addSubview:testView];
After parsing JSON response use follow code
UIScrollView *testView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,480)];
for(int i=0; i<[json count]; i++){
NSLog(#"%#",[json objectAtIndex:i]);
NSString *imageString=[NSString stringWithFormat:#"%#",[json objectAtIndex:i]];
NSURL * urlone=[NSURL URLWithString:imageString];
NSData *datanew =[NSData dataWithContentsOfURL:urlone];*
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,i*480,320,480)];
[imageView setImage:[UIImage imageWithData:datanew]];
[testView addSubview:imageView];
}
[self.view addSubView:testView];
*Note: Now you are going with Synchronous Request to download & load images in the view. It is not a good approach. Use Asynchronous requests for downloading images and loading them.
Find the following URL for asynchronous image downloading
Asynchronous downloading of images for UITableView with GCD
you can get an image dictionary into array like this, into data object
Suppose i have PostClubDC class with posDC obj
for(NSDictionary *returnDicto in dataArray)
{
PostClubDC *postDC = [[PostClubDC alloc] init];
NSDictionary * returnDict = [returnDicto objectForKey:#"club_info"] ;
postDC.postID = [[returnDict objectForKey:#"Id"]integerValue];
postDC.postName = [returnDict objectForKey:#"name"];
postDC.postImage = [returnDict objectForKey:#"image"];
[yourDataArray addObject:postDC];
}

Downloading image from a url into a UIImageVIew dynamically

I am trying to insert and image into a UIImageView from a url. I used the following code to do so.
When running the program gets stuck at
NSURL *url = [NSURL URLWithString:urlstring];
In the below code and it shows "Thread 1 : signal SIGABRT" on that particular line.
Can someone help me with this and tell if the format that i used is correct or what i had did wrong??
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newoffer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *temp = [product objectAtIndex:indexPath.row];
UILabel *Label = (UILabel *)[cell viewWithTag:201];
Label.text = [temp objectForKey:#"item_name"];
UIImageView *Image = (UIImageView *)[cell viewWithTag:200];
NSString *urlstring=[temp objectForKey:#"image_url"];
NSURL *url = [NSURL URLWithString:urlstring];
NSData *data = [NSData dataWithContentsOfURL:url];
Image.image = [UIImage imageWithData:data];
return cell;
}
Change this code:
NSURL *url = [NSURL URLWithString:urlstring];
NSData *data = [NSData dataWithContentsOfURL:url];
Image.image = [UIImage imageWithData:data];
To:
dispatch_queue_t myqueue = dispatch_queue_create("myqueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(myqueue, ^{
NSURL *url = [NSURL URLWithString:[urlstring stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];;
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
Image.image = [UIImage imageWithData:data]; //UI updates should be done on the main thread
});
});
As mentioned by others, an Image Caching library like SDWebImage will help a lot because even with this implementation, you just push the download process to a background thread so the UI does not get stucked, but you are not caching anything.
Try this
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.vbarter.com/images/content/1/9/19517.jpg"]]]];
For async downloading
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.vbarter.com/images/content/1/9/19517.jpg"]]]];
});
if url is dynamic then
NSString *stringUrl; // this can be any valid url as string
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:stringUrl]]]];
NSData *data = [NSData dataWithContentsOfURL:url];
will load imageData synchronous, that means main thread will be blocked .
Use the project on github:SDWebImage for image asynchronous loading and cache.
There's probably better libraries that do this now, but I have always been using this for my projects and it works well: AsyncImageView. There are other alternatives like SDWebImage
But basically, you don't want to use
NSData *data = [NSData dataWithContentsOfURL:url];
because it will block the main thread until the image is downloaded. To avoid this you might want to use something asynchronous, like the above two libraries.
For example, with AsyncImageView, it becomes as easy as:
myImageView.imageURL = someNSURL;

Asynchronous loading of images?

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

Resources