I initialize an activity indicator and in a button press action I start it animating and call the next view to display.
-(IBAction) downloadButtonPressed:(id)sender {
NSLog(#"Download Button Pressed");
indicator.hidden = NO;
[indicator startAnimating];
if (addviewcontroller == nil)
addviewcontroller = [[AddViewController alloc]init];
[self.view addSubview:addviewcontroller.view];
[addviewcontroller setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:addviewcontroller animated:YES];
}
When I press the button, the activity indicator doesn't start immediately. It starts when the other view is called. The indicator is displayed for a second, but when the button is pressed it takes some time to load the other view.
I dont know why the indicator shows for a second without starting.
Try this :
-(IBAction) downloadButtonPressed:(id)sender
{
NSLog(#"Download Button Pressed");
indicator.hidden = NO;
[indicator startAnimating];
[self performSelector:#selector(showController) withObject:nil afterDelay:0.1f];
}
- (void)showController {
if (addviewcontroller == nil)
addviewcontroller = [[AddViewController alloc]init];
[self.view addSubview:addviewcontroller.view];
[addviewcontroller setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:addviewcontroller animated:YES];
}
That should do the trick ;-)
EDIT
I just noticed that there is a problem in your code, you are adding your addviewcontroller twice. One by adding it as a subview of the actual view controller, and one by modally presenting another view controller. You should remove one of the statements from this function.
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.
I am trying to hide the navigation bar 'back' button during an animation. When the animation completes, the button re-appears.
my code is as follows:
- (void) animateResults {
[self hideNavBarButtons];
[self animatePlayer1];
[self animatePlayer2];
[self performSelector:#selector(showNavBarButtons) withObject:nil afterDelay:3.0];
}
- (void) hideNavBarButtons {
[self.navigationItem setHidesBackButton:YES animated:YES];
}
- (void) showNavBarButtons {
[self.navigationItem setHidesBackButton:NO animated:YES];
}
This works fine on the simulator... but I get weird results on the device. It is very inconsistent, and stops hiding the 'back' button after a few tries. I am assuming I have some delegates messed up.. but I am lost. Any help is appreciated.
Thanks.
I'm having an issue with my save button in a modal UINavController. When I press the save button, I'm dismissing the keyboard if it is still up, validating the data from the text fields, then showing a UIProgressView while I send my info out.
My problem is that the keyboard isn't getting out of the way fast enough, so keyboard is still up when it is time to show the UIProgressView and it is getting added towards the bottom of my view and it looks stupid.
I can hit the return key, and the keyboard drops, then press save, no issues. But if the user skips the keyboard return key and goes right for the top right save button, I have issues.
Ideally I'd like to implement a short wait statement for it to drop out of sight. Or perform my validation after a delay, but nothing I have tried is working. Please help.
Code Example:
// end edit mode - should kill all keyboards
[[self.tableView superview] endEditing:YES];
// make sure everything is entered correctly and validates
[self validateEntryFields]; // keyboard not gone when this finishes
if (valid) { // progress view shows up towards bottom of view
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Adding User";
HUD.detailsLabelText = #"Please Wait";
[HUD showWhileExecuting:#selector(sendNewUserInformation) onTarget:self withObject:nil animated:YES];
}
You may use keyboard notification (it would be more correct solution than based on timer):
[notificationCenter addObserver: self selector: #selector(keyboardDidHide:) name: UIKeyboardDidHideNotification object: nil];
And show your progress view in keyboardDidHide: method.
If a small delay would be working you could try the following code between your validation and your if statement where you decide whether or not you will showing the progress view.
You can use the NSTimer object:
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(mumboJumbo:)userInfo:nil repeats:NO];
And add your code into a method like:
-(void)mumboJumbo:(id)sender{
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Adding User";
HUD.detailsLabelText = #"Please Wait";
[HUD showWhileExecuting:#selector(sendNewUserInformation) onTarget:self withObject:nil animated:YES];
}
If I understood correctly your problem that should work.
i have added a UIPopover to my navigationbar when the user touches the rightbarbuttonitem.
I want to know whats the cleanest coding for showing and dismissing the popover. With the code below, it works, but not correct.
If the user touches the rightbarbuttonitem first, the popover appears. Now he can choose a cell,.. works. Or you can touch outside the popover and it disappears. Both ways correctly.
But when touching the rightbarbuttonitem and after that, the same touch on that icon again, you have to touch it twice to bring up that popover again. (Not on the first touch).
How should that correctfunction look like? Thanks for your time..
-(void) downloads:(UIBarButtonItem*)button{
NSLog(#"downloads");
if(tableViewController == nil) {
tableViewController = [[[TableViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
self.popoverController = [[[UIPopoverController alloc] initWithContentViewController:tableViewController]autorelease] ;
[self.popoverController presentPopoverFromBarButtonItem:barButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
tableViewController.delegate = self;
}else {
[self.popoverController dismissPopoverAnimated:NO];
tableViewController.delegate = nil;
tableViewController = nil;
//[self.popoverController release];
//self.popoverController = nil;
}
}
//delegate
-(void) selectedTable:(NSString*)text{
NSLog(#"selectedTable: %#", text);
[self.popoverController dismissPopoverAnimated:YES];
}
Comments
Your downloads: method checks for tableViewController value and make decision if UIPopoverController should be displayed or dismissed. But yours selectedTable: method does dismiss popoverController and does not set tableViewController to nil thus it doesn't work as expected by you.
And I also don't see UIPopoverControllerDelegate implementation, especially popoverControllerDidDismissPopover: which will tell you when UIPopoverController was dismissed (by touching outside your UIPopoverController for example).
Memory Management
Read memory management guide. [self.popoverController release] with self.popoverController = nil leads to crash - one release and second release during setting to nil. (I assume your popoverController property retains).
#Chiefly Izzy: Thanks for your help. You point me in the right direction.
Here´s the code i´m using. It works great. Hope that memory management is clean, too. Isn´t it?
-(void) downloads:(UIBarButtonItem*)button{
if([self.popoverController isPopoverVisible])
{
[self.popoverController dismissPopoverAnimated:YES];
[self.popoverController.delegate popoverControllerDidDismissPopover:self.popoverController];
return;
}
// PopOver Bookmarks-Icon
if(tableViewController == nil) {
tableViewController = [[PdfTableViewController alloc] initWithStyle:UITableViewStylePlain]; //autorelease];
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:tableViewController]; //autorelease] ;
[self.popoverController presentPopoverFromBarButtonItem:barButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
popoverController.delegate = self;
tableViewController.delegate = self;
}
/* Using "isPopoverVisible" from top or that else. both works
else {
[self.popoverController dismissPopoverAnimated:YES];
[self.popoverController.delegate popoverControllerDidDismissPopover:self.popoverController];
}
*/
}
-(void) selectedTableView:(NSString*)text{
NSLog(#"selectedTableView: %#", text);
[self.popoverController dismissPopoverAnimated:YES];
[self.popoverController.delegate popoverControllerDidDismissPopover:self.popoverController];
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popover{
NSLog(#"popoverControllerDidDismissPopover");
tableViewController.delegate = nil;
[tableViewController release];
tableViewController = nil;
popoverController.delegate = nil;
[popoverController release];
popoverController = nil;
}
I have a MKMapView (also a UIPopoverControllerDelegate) with Annotations. This MapView has, in the MKTestMapView.h file, a UIPopoverController* popoverController defined in the #interface and a #property (nonatomic, retain) UIPopoverController* popoverController; defined outside of the #interface section. This controller is #synthesized in the MKTestMapView.m file and it is released in the - (void)dealloc section. The Annotations in this MapView have rightCalloutAccessoryViews defined to the following:
- (void)mapView:(MKMapView *)mapView2 annotationView:(MKAnnotationView *)aview calloutAccessoryControlTapped:(UIControl *)control{
...
CGPoint leftTopPoint = [mapView2 convertCoordinate:aview.annotation.coordinate toPointToView:mapView2];
int boxDY=leftTopPoint.y;
int boxDX=leftTopPoint.x;
NSLog(#"\nDX:%d,DY:%d\n",boxDX,boxDY);
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
popoverController.delegate = self;
CGSize maximumLabelSize = CGSizeMake(320.0f,600.0f);
popoverController.popoverContentSize = maximumLabelSize;
CGRect rect = CGRectMake(boxDX, boxDY, 320.0f, 600.0f);
[popoverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
...
}
Now here comes the fun part. First of all, I am not sure if I need maximumLabelSize and the rect to be the same size. I am new to the popovercontroller so I am playing this by ear..
Okay, the popover shows. Now to dismissing it. I can click anywhere on mapView2 and the popover goes away...but I need the user to click a button in the view if they change anything. URGH!
The docs show:
To dismiss a popover programmatically,
call the dismissPopoverAnimated:
method of the popover controller.
Well, here is the problem: By definition of how the popoverController works, you are clicking inside the view of the displayed popover (to click the button) but have to trigger the dismissPopoverAnimated: method of the controller that launched this popover view, in my case, the popoverController inside the MKTestMapView.m file.
Now, having said all that, remember, [popoverController release] doesn't happen until:
- (void)dealloc {
[popoverController release];
[mapView release];
[super dealloc];
}
So, do i just do the following inside the button (messy but may work):
(Assuming my popover view is a TableView) In the:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MKTestMapView * mKTestMapView = [[MKTestMapView alloc] init];
[[mKTestMapView popoverController].dismissPopoverAnimated:YES];
}
Here is my issue: I cannot figure out whether doing the above gives me a reference (if there is such a thing) to the existing view that is on the screen -- and therefore the view that is the owner of that popoverController. If it is as simple as
[[[self parentView] popoverController].dismissPopoverAnimated:YES];
I will shoot myself cos I don't think that is the correct syntax either!
This should be easy...yet I am lost. (probably just frustrated with so many iPad differences that I am learning).
Can anyone explain more?
I had the same problem... I had a neat "close" button (X) in the top of my view loaded by the popover, but it didn't work. In my universal app it will be presented as a new view, so that code should stay.
What I did now was that I added the following to my detailedPinView (the view the popover loads):
in the detailedPinView.h file:
#interface detailedPinView : UIViewController {
[...]
UIPopoverController *popover;
[...]
}
-(void)setPopover:(UIPopoverController*)aPopover;
In the detailedPinView.m file:
- (void)setPopover:(UIPopoverController*)aPopover
{
popover = aPopover;
}
The X button closes the view using an IBAction, this is what I did there:
In the detailedPinView.m file:
-(IBAction)releaseDetailedView:(UIButton *)sender
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
if (popover != nil)
{
[popover dismissPopoverAnimated:YES];
}
else {
NSLog(#"Nothing to dismiss");
}
}
else{
[self.parentViewController dismissModalViewControllerAnimated: YES];
}
}
In the class loading the my map and the popover view I added the following code:
[...]
-(void)mapView:(MKMapView *)theMapView annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control
{
UIViewController *detailController = [[detailedPinView alloc] initWithNibName:#"detailedPinView"
bundle:nil
annotationView:pin];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:detailController];
[aPopover setDelegate:self];
[aPopover setPopoverContentSize:CGSizeMake(320, 320) animated:YES];
[detailController setPopover:aPopover];
[detailController release];
[mapView deselectAnnotation:pin.annotation animated:YES];
self.popoverController = aPopover;
[mapView setCenterCoordinate:pin.annotation.coordinate animated:YES];
[self.popoverController presentPopoverFromRect:CGRectMake(382,498,0,0) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
else
{
[self presentModalViewController: detailController animated:YES];
}
[detailController release];
}
[...]
I don't know if the was the answer you were hoping for, I think it might be a bit of a messy way to do it... but giving the time schedule this worked like a charm :)
Here is another simple solution.
I found that we should follow the following steps for clearly dismissing popovers.
dismiss a popover.
release a view loaded by the popover.
Before iOS8, almost all of us may release a view loaded by a popover first, and then we programmatically dismiss the popover.
However, in iOS8, we do the steps in revers.
Before iOS8, my code of dismissing a popover
// creating a popover loading an image picker
picker = [[UIImagePickerController alloc] init];
...
pickerPopover = [[UIPopoverController alloc] initWithContentViewController:picker];
[pickerPopover presentPopoverFromRect:aFrame inView:aView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// dismissing the popover
[picker.view removeFromSuperview]; // (1) release a view loaded by a popover
[picker release], picker = nil;
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[pickerPopover dismissPopoverAnimated:YES]; // (2) dismiss the popover
}
In iOS8, the dismissing code part should be changed as below,
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[pickerPopover dismissPopoverAnimated:YES]; // (2) dismiss the popover first
}
[picker.view removeFromSuperview]; // (1) and then release the view loaded by the popover
[picker release], picker = nil;