Hi in my application i have the image on UIImageView and i have button called download once user click the download button the image will save to the Photolibrary. Now i want to add the Progressbar for the download to know the user its downloading the image.
I have used the MBProgressHUD for the progress but not able work like i wanted. I want to show once user click the download button like its downloading message with progress once image got downloaded i want to show like image downloaded please tell me how to achieve this one i tired something like that its not working.
My MBProgressHUD code.
- (IBAction)down:(id)sender {
HUD = [[MBProgressHUD alloc] initWithView:self.view];
HUD.labelText = #"downloading...";
HUD.mode = MBProgressHUDModeAnnularDeterminate;
[self.view addSubview:HUD];
[HUD showWhileExecuting:#selector(download) onTarget:self withObject:nil animated:YES];
UIImageWriteToSavedPhotosAlbum(imageview.image, nil, nil, nil);
}
- (void)download {
float progress = 0.0;
while (progress < 1.0) {
progress += 0.01;
HUD.progress = progress;
usleep(50000);
}
}
I have used the above code to achieve but its not working like i wanted please tell me how to achieve this one.
Thanks.
- (IBAction)down:(id)sender {
HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
HUD.mode =MBProgressHUDModeAnnularDeterminate;
NSString *strloadingText = [NSString stringWithFormat:#"Downloading...."];
HUD.labelText = strloadingText;
[HUD show:YES];
[HUD showWhileExecuting:#selector(doSomeFunkyStuff) onTarget:self withObject:nil animated:YES];
}
- (void)doSomeFunkyStuff {
float progress = 0.0;
while (progress < 1.0) {
progress += 0.01;
HUD.progress = progress;
usleep(5000000);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
// process in background thread
NSString *strloadingText = [NSString stringWithFormat:#"completed"];
HUD.labelText = strloadingText;UIImageWriteToSavedPhotosAlbum(imageview.image, nil, nil, nil);
[HUD hide:YES];
});
}
}
UIImageWriteToSavedPhotosAlbum works on main thread. So, put this function in GCD. Your UI can not update itself when main thread is busy.
Try this:
- (IBAction)down:(id)sender {
...
[HUD showWhileExecuting:#selector(download) onTarget:self withObject:nil animated:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
// process in background thread
UIImageWriteToSavedPhotosAlbum(imageview.image, nil, nil, nil);
// when finish, dismiss HUD
HUD.hidden = YES;
});
}
you can use https://github.com/samvermette/SVProgressHUD for showing progress bar..If you are downloading image from server then use async call. Like if you are using ASIFormDataRequest request for getting image then use as follow :
[SVProgressHUD showWithStatus:#"Please wait"];
self.view.userInteractionEnabled = NO;
NSURL *url=[NSURL URLWithString:#"your URL request"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setRequestMethod:#"POST"];
[request setPostValue:xyz forKey:#"abc"];
[request.shouldAttemptPersistentConnection = NO;
request.delegate=self;
request.timeOutSeconds = 10;
[request startAsynchronous];
After this you can call :
-(void)requestFinished:(ASIHTTPRequest *)request
{
NSError *error = [request error];
if (!error)
{
NSString *response = [request responseString];
NSMutableDictionary *responseJSON = [response JSONValue];
[SVProgressHUD dismiss];
self.view.userInteractionEnabled = YES;
UIImageWriteToSavedPhotosAlbum(imageview.image, nil, nil, nil);
}
}
Hope this will help you.
Related
I am using the code below to grab a farme from a video to use as a thumb nail. This is working as desired, however my MBProgressHUD is only showing up after the image grab has been completed, flashing on and off the screen in a second. I have used MBPRogressHUD several times in the same way, displaying it at the start of the code and hiding after everything else is done, which has always worked but this time it is like the code is running out of order? Any help will be much appreciated.
This is the method called on my button press.
- (IBAction)grabImage:(id)sender {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeIndeterminate;
hud.labelText = #"Grabing Thumbnail";
[hud show:YES];
self.imageholder.image = [self grabImageMethod];
[hud hide:YES];
}
And this is the grab method called with in.
-(UIImage*)grabImageMethod{
NSURL *vidURL = [NSURL URLWithString:#"http://myserver.com/myfile.mp4"];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidURL options:nil];
AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
NSError *err = NULL;
CMTime time = CMTimeMake(1, 60);
CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
NSLog(#"err==%#, imageRef==%#", err, imgRef);
return [[UIImage alloc] initWithCGImage:imgRef];
}
After the comment from nielsbot i went and replaced
[hud show:YES];
self.imageholder.image = [self grabImageMethod];
[hud hide:YES];
with
[hud showAnimated:YES whileExecutingBlock:^{
self.imageholder.image = [self grabImageMethod];
}];
It now works perfectly.
I need to load some images from a JSON Object. When these images are loading, I need to show a HUD on my view. I tried to define a HUD like following,
Define HUD in viewDidLoad method
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeIndeterminate;
hud.labelText = #"Loading Images";
[hud show:YES];
[hud showWhileExecuting:#selector(loadJSONData) onTarget:self withObject:nil animated:YES];
loadJSONData method
-(void)loadJSONData{
_myObject = [[NSMutableArray alloc] init];
NSData *jsonSource = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:
jsonSource options:NSJSONReadingMutableContainers error:nil];
NSArray *dataDic = [jsonObjects objectForKey:#"data"];
for (NSDictionary *dicData in dataDic) {
Lawyer *l = [[Lawyer alloc] init];
dispatch_async(queue, ^{
NSString *imgUrl = [NSString stringWithFormat:#"myurl",l.imageUrl];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imgUrl]];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
l.uiImage = image;
});
});
[_myObject addObject:[l initFromDictionary:dicData]];
}
}
My out put is showing the HUD for a second and disappeared. No data is loading. How do I fix this.
Thanks in Advance!
Your code is working as expected. loadJSONData performs an asynchronous request so the selector has actually finished executing. What you should do is show the HUD before the method loadJSONData and then hide it when the data has been received in:
dispatch_async(dispatch_get_main_queue(), ^{
l.uiImage = image;
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
Although personally I would have a callback in loadJSONData and perform the HUD dismissal in a completion block.
Use this code :
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView: self.view];
[self.view addSubview: hud];
hud.labelText = #"Loading Images...";
[hud showAnimated:YES whileExecutingBlock:^{
[self loadJSONData];
} completionBlock:^{
// Refresh UI
}];
But make sure , as whileExecutingBlock using thread you have to make all UI change on main thread.
Ok here's the question, how do I simulate loading message until I fully downloaded the data from the server. I have this problem as I can't pass the data to the next view controller when the properties to hold the data from the downloaded json is still nil. So, How can I simulate a loading message until I fully parsed the Json.
Here's my code to fetch data
-(void)fetchFeed
{
NSString *requestString = #"some website";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary * jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.locations = jsonObject[#"someKey"];
NSLog(#"%#", self.locations);
}
];
[dataTask resume];
}
- (void)viewDidLoad
{
[super viewDidLoad];
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:hud];
[hud show:YES];
[hud setLabelText:#"Loading..."];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self fetchFeed]; //Network activity
dispatch_async(dispatch_get_main_queue(), ^{
//do stuff after json download
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
});
Please check out my answer here.. It pretty much does the same thing that you are looking for..
I have used MBProgressHUD to show the loading message.
Its as simple as
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:hud];
[hud show:YES];
[hud setLabelText:#"Loading..."];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
//Network activity
dispatch_async(dispatch_get_main_queue(), ^{
//do stuff after json download
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
});
for a more detailed answer check the link.
*************EDIT*******************
As you are using NSURLSession it allows you to perform background download operations. As per the code you posted, we don't to start a new thread using dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{})
Please try this..
- (void)viewDidLoad
{
[super viewDidLoad];
[self fetchFeed]; //Network activity
}
-(void)fetchFeed
{
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:hud];
[hud show:YES];
[hud setLabelText:#"Loading..."];
NSString *requestString = #"some website";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[[self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSDictionary * jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.locations = jsonObject[#"someKey"];
NSLog(#"%#", self.locations);
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
}] resume];
}
This should work.
I am using MBProgressHUD to show an activity indicator while downloading web service data. The app will be often be used in rural areas with poor connectivity so I want to be able to set a timeout for the HUD to say, 10 seconds (as just an arbitrary figure). I'm not sure how to go about this. Can anyone offer suggestions? THanks!
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
NSString *info = [NSString stringWithFormat:#"Loading %# gauges", self.stateIdentifier];
[hud setLabelText:info];
[hud setDetailsLabelText:#"Please wait..."];
[hud setDimBackground:YES];
[hud setOpacity:0.5f];
[hud show:YES];
[self.view addSubview:hud];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateIdentifier andType:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
[hud removeFromSuperview];
});
});
You can use the:
- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay;
method of MBProgressHUD.
Create MBProgressHUD like:
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:hud];
NSString *info = [NSString stringWithFormat:#"Loading %# gauges", self.stateIdentifier];
[hud setLabelText:info];
[hud setDetailsLabelText:#"Please wait..."];
[hud setDimBackground:YES];
[hud setOpacity:0.5f];
[hud show:YES];
[hud hide:YES afterDelay:10.0];
For Swift, following is the solution:
let progressHUD = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
progressHUD.hideAnimated(true, afterDelay: 5)
I am running around the issue, that MBProgressHUD should be updating its View with a Checkmark/X for succeeded/failed requests. Somehow this doesnt really work as intended and the update only works after all the code has executed.
initializing the HUD
...
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Verifying Credit Card";
_HUD = hud;
CWAPIClient *client = [CWAPIClient sharedClient];
client.delegate = self;
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.clubw.billing", 0);
dispatch_async(backgroundQueue, ^{
[client save:billingProfile with:[Address defaultBillingAddress]];
});
....
Callback to process information:
self POST:[NSString stringWithFormat:#"user/%#/billingprofile", [[Profile defaultProfile] userId]] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate CWAPIClient:self doneVerifyingCreditCard:responseObject];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error);
}];
callback when action is complete
BOOL success = [[jsonResponse objectForKey:#"success"] boolValue];
if (success)
{
NSLog(#"Thread: %#", [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *checkmarkImage = [UIImage imageNamed:#"checkmark.png"];
UIImageView *checkmarkView = [[UIImageView alloc] initWithImage:checkmarkImage];
_HUD.customView = checkmarkView;
_HUD.labelText = #"Credit Card Verified!";
_HUD.mode = MBProgressHUDModeCustomView;
NSLog(#"Thread: %#", [NSThread currentThread]);
sleep(5);
[_HUD hide:YES];
});
After the 5 seconds, it simply closed the HUD - and the updated one flashes for a second.
It seems, like this is a threading issue - but I cant seem to figure out where it is throwing up.
In the portion of the code where you make your callback, be sure to perform the callback on the main queue as well.