I've got both working great individually, but when I try to combine them like this:
- (IBAction)showWithLabel:(id)sender
{
HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
[self.checkinsViewController.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Sending tweet";
[HUD showWhileExecuting:#selector(tweet) onTarget:self withObject:nil animated:YES];
}
- (void)tweet { [_twEngine sendUpdate:#"Test tweet"]; }
I don't get any errors, but the tweet isn't sent If I place:
[_twEngine sendUpdate:#"Test tweet"];
In the IBAction, it tweets. If I change tweet to sleep, the HUD shows up properly.
Any ideas?
The showHUDAddedTo:animated: and showWhileExecuting: methods are mutually exclusive. You can't use both methods to show the HUD .
Change your initializer to just allocate a HUD and it should work.
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
Related
MPProgressView won't display when I try to push a viewcontroller until seconds before the pushed VC is displayed. Should the viewController be placed in the same function as the MBProgressView is displayed? I've made sure that my MBProgressView is on the main thread, I've tried many solutions on SO and can't see anyone with the same issue. I am simply trying to display the MBProgressHUD while the viewController is loading and being pushed. Thanks!
I am using MBProgressView as follows:
- (IBAction)pushButton:(id)sender
{
self.HUD =[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[self.view addSubview:self.HUD];
self.HUD.labelText = #"Doing stuff...";
self.HUD.detailsLabelText = #"Just relax";
self.HUD.delegate=self;
[self.view addSubview:self.HUD];
[self.HUD showWhileExecuting:#selector(loadCreate) onTarget:self withObject:nil animated:YES];
}
- (void)loadCreate {
[self performSelectorOnMainThread:#selector(dataLoadMethodMail) withObject:nil waitUntilDone:YES];
}
-(void)dataLoadMethodMail
{NSLog(#"data load method is displaying");
SelectViewController *mvc = [[SelectViewController alloc] init];
[self.navigationController pushViewController:mvc animated:YES];
}
You don't need to add self.HUD to self.view, showHUDAddedTo: does it for you.
[self.HUD showWhileExecuting:#selector(loadCreate) onTarget:self withObject:nil animated:YES];
Shows the hud until loadCreate returns.
[self performSelectorOnMainThread:#selector(dataLoadMethodMail) withObject:nil waitUntilDone:YES];
dispatches something on main thread and returns right after (before the actual end of dataLoadMethodMail). The HUD is shown but disappears right away.
To solve the issue try hiding manually the HUD when dataLoadMethodMail finishes it's work.
Just replace
[self.HUD showWhileExecuting:#selector(loadCreate) onTarget:self withObject:nil animated:YES];
with
[self loadCreate];
and add
dispatch_async(dispatch_get_main_queue(), ^{
[self.HUD hide:YES];
});
at the end of dataLoadMethodMail
PS : Loading data should not be done on main thread.
In one stack I am displaying the MBProgressHUD and if by using the other stack when some calculation called I want MBProgressHUD to remove from the view but it is not been removed from the hud ..check what mistake I am doing..
first stack called LoginViewController.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
}
-(void)myTask {
// Do something usefull in here instead of sleeping ...
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self.hud hide:YES];
self.hud=nil;
[self.hud removeFromSuperview];
//[self.hud showWhileExecuting:#selector(myTask1) onTarget:self withObject:nil animated:YES];
}
now theViewController get calls but view will be same Previous and
after some calculation and I want that in ViewController I want to remove theHUD from the view by calling the method in the LoginViewController..check code
- (void)didReceiveResponseFromServer:(NSString *)responseData
{
login=[[LoginViewController alloc]init];
[self.login myTask];
}
Set UP MBProgressHUD
- (void) setupHUD
{
//setup progress hud
self.HUD = [[MBProgressHUD alloc] initWithFrame:self.window.bounds];
[self.SpurView addSubview:self.HUD]; // add it as here.
self.HUD.dimBackground = YES;
self.HUD.minSize = CGSizeMake(150.f, 150.f);
self.HUD.delegate = self;
self.HUD.labelText = #"Loading...";
}
Then use for hide [self.HUD hide:YES]; as describe in your code .
like me ,
I tyr [MBProgressHUD hideHUDForView:bAnimatedView animated:YES]
but it will no work at times when I quick push in and back out .
So I add something to check the view of MBProgressHUD.
MBProgressHUD *HUD = [MBProgressHUD HUDForView:bAnimatedView];
if (HUD!= nil) {
[HUD removeFromSuperview];
HUD=nil;
}
I'm displaying some views,webVies and while they are loading i display an ProgressHud with waiting message. I'm using an instance of that object :
MBProgressHUD * progrssHUD
Using the show and hide methods to control over loading windows. In some views i would like to add view only after the hide method is turned on - meaning no window displayed now.
How can i check from any interface what is that status of MBProgressHUD and only after status X to do something?
If you see the implementation of MBProgresshud then you will find that when they are hiding it they are setting it's alpha 0 and when they are showing it they are setting it alpha 1.
So you can use this property to check whether it is hidden or shown.
i.e
if(progrssHUD.alpha == 0){
//perform hide operation
}else{
//Perform show operation
}
-(IBAction)SHOW{
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.delegate = self;
[HUD show:YES];
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(showHUD) onTarget:self withObject:nil animated:YES];
}
- (void)hudWasHidden:(MBProgressHUD *)hud {
// Remove HUD from screen when the HUD was hidded
[HUD removeFromSuperview];
[HUD release];
HUD = nil;
}
THE METHOD showWhileExecuting CALLING THE HUD WAS ACTIVE WHILE THE DELEGATE METHOD WILL COME.
in a method, i want to call a method after n seconds:
self.toolBarState = [NSNumber numberWithInt:1];
[self changeButtonNames];
[self drawMap];
[self performSelector:#selector(showActionSheet) withObject:nil afterDelay:2];
i want to show the action sheet 2 seconds after drawMap is complete. when i use this performSelector, it never makes the call.
if i just put [self showActionSheet];, it works just fine. is there reason why the performSelector is not making the call?
EDIT: in another part of my code, i make the same call and it works:
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = (id) self;
[HUD showWhileExecuting:#selector(drawMap) onTarget:self withObject:nil animated:YES];
[self performSelector:#selector(showActionSheet) withObject:nil afterDelay:6];
here, the showActionSheet gets called 6 seconds after drawMap has completed. i'm guessing there is something going on with the threads that i don't understand yet...
EDIT2:
-(void)showActionSheet
{
InspectAppDelegate *dataCenter = (InspectAppDelegate *) [[UIApplication sharedApplication] delegate];
if (dataCenter.fieldIDToPass == nil)
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Selected Boundary Options" delegate:(id) self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Analyze a Field",#"Retrieve Saved Analysi", #"Geotag Photos", #"Refresh the map",nil];
actionSheet.tag = 0;
[actionSheet showInView:self.view];
}
else
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Selected Boundary Options" delegate:(id) self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Analyze a Field",#"Retrieve Saved Analysi", #"Geotag Photos", #"Attribute the Field", #"Refresh the map",nil];
actionSheet.tag = 0;
[actionSheet showInView:self.view];
}
}
EDIT3:
ok, so the progress of method calls is:
-(void) foundDoubleTap:(UITapGestureRecognizer *) recognizer
{
[HUD showWhileExecuting:#selector(select) onTarget:self withObject:nil animated:YES];
}
-(void) select
{
[self changeButtonNames];
[self drawMap];
[self performSelector:#selector(showActionSheet) withObject:nil afterDelay:2];
}
showActionSheet never gets called. like i said, i'm pretty sure its a threading issue. if call it with [self showActionSheet], it will run. =/
I ran into this same issue, and by necessity I solve it slightly different from the accepted answer. Notice I wanted my delay and selectors to be variables? Using a block allows me to stay within my current method.
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelector:loopSelector withObject:nil afterDelay:cycleTime];
});
By the way, this is definitely a threading issue. The documentation for performSelector:withObject:afterDelay: states that this will be performed on the current thread after the delay, but sometimes that thread's run loop is no longer active.
A more detailed discussion on the subject can be found here
Try using:
-(void) select {
[self changeButtonNames];
[self drawMap];
[self performSelectorOnMainThread:#selector(showActionSheet) withObject:nil waitUntilDone:YES];
}
-performSelector:withObject:afterDelay: schedules a timer on the same thread to call the selector after the passed delay.
Maybe this will work for you:
-(void) select {
[self changeButtonNames];
[self drawMap];
[self performSelectorOnMainThread:#selector(someA) withObject:nil waitUntilDone:YES];
}
-(void)someA {
[self performSelector:#selector(showActionSheet) withObject:nil afterDelay:2];
}
Does your class still exist in memory?
If your class goes away before the performSelector fires, do you wind up sending the message to nil (which would cause nothing to occur).
You could test this by dropping an NSLog into your dealloc()
You mentioned threads. If your performSelector isn't called from the MainThread it could cause issues (UI things should be done on the main thread).
I got the same problem when I call performSelector:withObject:afterDelay: in a background thread created by ReactiveCocoa.
If I execute the block in the ReactiveCocoa's way, the block will be called correctly:
[[[RACSignal empty] delay:2.0] subscribeCompleted:^(){
// do something
}];
I guess there is some magic in the ReactiveCocoa's threading model.
I want to show an MBProgressHUD in my iPhone app without spawning new threads.
I have a very complicated set of business logic which sometimes (but not always) needs to wait for user input, and running on multiple threads ends up asking for user input multiple times at once, leading to crazy errors. Thus I would prefer to avoid running anything off of the main thread. However, due to this constraint, MBProgressHUD is not showing because the main thread is being blocked! Normally I would create my MBProgressHUD with the following code:
[HUD showWhileExecuting:#selector(myWorkerMethod) onTarget:self withObject:nil animated:YES];
But I would like to use the following code without blocking the main thread:
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.minShowTime = 0.0;
HUD.labelText = #"some text";
[HUD show:YES];
Any thoughts?
How about this?
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
HUD.labelText = #"Foo";
// code to execute synchronously
[MBProgressHUD hideHUDForView:self.view animated:YES];
Better late than never. You can do this with some run loop tickery. See this answer for details.