Adding UIToolbar to window - iphone

I have a navigation based application which I'm trying to add a unique UIToolbar that will be persistent no matter which is the current view, using this:
Persistent UIBarButtonItem in UIToolbar?
The problem is my when I set the frame for the navigationController, the UITableView inside the navigationController shifts 20px under the navigation bar, as if it started drawing behind the status bar.
Any ideas on how I can fix this? I'm stuck!

I ended up using the built-in toolbar of the navigationController.
So on every viewDidLoad I set the current toolbarItems to the same array:
- (void)viewDidLoad {
[super viewDidLoad];
MyDelegate *appDelegate = (MyDelegate *)[[UIApplication sharedApplication] delegate];
[self setToolbarItems:[appDelegate toolbarItems] animated:YES];
}
I don't see any transitions and I could always set it to different buttons if I need to on a specialy viewController.
Maybe this is the way it's supposed to be done. Occam's razor, anyone? :)

I've had this happen a lot when adding sub views to the UIWindow. I tried all sorts of advice from people but eventually just did shifted the frame origin down 20px to accommodate the status bar.

I've made a custom object deriving from UIToolbar, and added a property called staticItems that I populate in the init method with 3 UIBarButtonItem (and their logic)
I've set "Show Toolbar" to my UINavigationController object, and changed toolbar's class to my new one.
Then I've set navigation's parent object as navigation's delegate, and implemented these method
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController setToolbarItems:downloadToolbar.staticItems animated:NO];
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{}
Really close to what you've done, a bit more easy to maintain. Hope will help somebody else.

Related

Present modal view controller from different view? ModalViewController being hidden by other views

How can I present a modalViewController from a different view controller?
I am currently displaying my modal view like this:
[self presentModalViewController:navController animated:YES];
But, I want to
[OtherViewController presentModalViewController:navController animated:YES];
Because part of it is being hidden by another viewController that is above it and manages the "self" view.
Well it should work, but maybe you are in a corner case.
Try adding a static method to your delegate like:
+ (void)presentModalViewController:(UIViewController *)viewController;
Where you do something like
[parentViewController presentModalViewController:viewController animated:YES];
And use it to present the modal view directly from the parent VC.
Anyway, if you still have a problem, give us some code :-) or your app archi.
It simply does not work b/c there is now such class method declared in a UIViewController class.
You are trying to call (note the + sign in front):
+ (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
UIViewController class only provides implementation for an instance method (note the - sign in front):
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
What should this tell you?
It tells you that you need to have a link to a live OtherViewController object to be able to invoke presentModalViewController on it, otherwise there is no View hierarchy the compiler can comply with.

Dismiss ModalViewController from another viewController in subview

I've got a view called A open with presentModalViewController Method, inside this view I loaded secondary view using:
new_view = [[new_websongs alloc] initWithNibName:#"new_websongs" bundle:nil];
[mysubview addSubview:new_view.view];
ok, to here it's ok but now I need to dismiss the first view "A" calling a method [self dismissModalViewControllerAnimated:YES] situated if first "A" viewController from secondary view controller (new_view) but not work! the code is:
self.Aviewcontroller = [[Aview alloc] init];
[Aviewcontroller dismissModalViewControllerAnimated:YES];
[Aviewcontroller release];
Please help ME!!!!
Thanks
Did u try [self.parentViewController dismissModalViewControllerAnimated:YES];
You have a logical problem. Start reading View Controller Programming Guide for iOS
The view controller that present an modal view controller must dismiss it or the modal view controller must dismiss it self
Totally agree with other answers; think logically about the order of view controller order and type. So think about which controllers are shown modally, and those shown via a navigation controller.
You can of course set a number of view controllers with:
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
without animation, then when required call say:
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
to show a specified view controller further up your stack of view controllers.
Hope this helps think about what you need to do? It's often a good idea to think about the order and type of view controllers in your app's interface in a separate project - where you can try it out on the device itself.
try this it should work
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
This works if you are presenting a modal view from a UISplitViewController. It can also be applied in so many other ways...
First, create an instance in your .h file for your appDelegate, (AppDelegate_iPad *appDelegate) then put this in your viewDidLoad or comparable method:
ipadDelegate = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
Now, present the first modal view like this:
YOURVC *vc = [[YOURVC alloc] initWithNibName:#"YOURVC" bundle:nil];
[ipadDelegate.splitViewController presentModalViewController:vc animated:YES];
[vc release];
Say you have a subview, like a UITableView, and want to dismiss the modal from the didSelectRowAtIndexPath. All you have to do to dismiss your modal with a subview is create another ipadDelegate instance inside your subview's .h (if needed), reference the [[UIApplication sharedApplication] delegate] again, and dismiss:
[ipadAppDelegate.splitViewController dismissModalViewControllerAnimated:YES];
Essentially, as long-winded as it may be, use your appDelegate's controller to present and dismiss the the modal if you need to maintain a persistent reference to the presentingViewController...because all the things above just don't work in my case.
If you're presenting with your ipadDelegate, make sure you check the mode of presentation in your MainWindow_iPad.xib. Your "Transition Style" should be "Cover Vertical" and "Presentation" should be "Current Context" or your modal may present behind other views.

UINavigationController and viewWillDisappear

So I have a UINavController in my app and am trying to execute a method when the user presses the back button. I have searched everywhere and can only find bits and pieces that don't really make sense out of context.
Is there a way to implement some sort of check that catches when the user presses the back button to dismiss the current view? (the viewWillDisappear method for the view being popped never gets called for some reason. I did read that it doesn't unless you forward that call?) Does that sound right, and does anyone have any ideas or suggestions? Thanks in advance.
Take a look at the UINavigationControllerDelegate. There are the only two methods that get called when a UIViewController is pushed to the navigation controller stack. Similarly, if one is being pushed then something probably was just popped. This is what I did to call viewDidDisappear and viewWillDisappear.
# pragma mark - UINavigationControllerDelegate Methods
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
static UIViewController *vcPointer = nil;
// If the previous view controller is still around then let's send a viewWillDisappear message
if (vcPointer != nil) {
if ([vcPointer respondsToSelector:#selector(viewWillDisappear:)]) {
[vcPointer viewWillDisappear:animated];
}
}
// Keep track of a pointer to the current viewController
vcPointer = viewController;
[viewController viewWillAppear:animated];
}
This code keeps a pointer reference to the last view controller that was pushed so that once we push another one we can pop the last one (if it still exists).
AFAIK, if you add a UINavigationController to a UIView via code, it won't send those messages to it's subviews by default. It will only do this if the UINavigationController received these calls itself. Maybe this is your problem (I don't know your view setup).
So, when adding the view of the UINavigationController, be sure to manually send it these messages.
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:rootViewController];
[navigationController viewWillAppear:NO];
[aView addSubview:navigationController.view];
[navigationController viewDidAppear:NO];
At least, this is what I found during development. Been searching for this for a long time and I still don't understand the rationale behind it.
You can always hide the default back navigation button and create your own with its own method to be called when pressed.
Execute whatever code you want there then pop the view.
I used this solution:
Add a custom button on the left side in the navigation bar
Let that button activate a custom method.
Disadvantage of this workaround: you will lose that nice arrow shaped "back" button. That can be solved as well with a custom image.
So here is my code.
Put this in your viewDidLoad:
// LeftButton in Navigation Bar
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonPushed:)];
self.navigationItem.leftBarButtonItem = leftBarButton;
[leftBarButton release];
Then add this method in the same .m file:
- (void) backButtonPushed: (id)sender {
// do what you want to do
}
dont forget in the .h file
- (void) backButtonPushed: (id)sender;
The viewWillDisappear & viewDidDisappear is called when a controller is popped or dismissed. The function is called on the fore-front view controller not on the UINavigationController itself. Did you possibly subclass and forget to call the super on something?

Update UITabBar Views?

I have an application where I was using buttons on a toolbar to call up the views, but I am switching it over to using a tab bar.
When using the buttons I was using the following code in MainViewController.m to update the values on the page and it was working just fine:
-(IBAction) loadSummaryView:(id) sender {
[self clearView];
[self.view insertSubview:summaryViewController.view atIndex:0];
//Update the values on the Summary view
[summaryViewController updateSummaryData];
[summaryViewController calculateData];
}
However, with the Tab Bar I can not figure out how to do this. I tried putting all of the necessary code in the Summary Views viewDidLoad and it loads the initial values, but it will not update the values when I change them in another view.
Any help is appreciated. I am a bit new at this, so please don't be cryptic as I may not understand the response.
Thank you.
By placing your code in viewDidLoad, it will only be called when the view is loaded from the nib. Unless you're running low on memory, this view will remain loaded for the duration of the life of your app.
So if you need to update values every time the view will appear, consider moving that code to an override of viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// your stuff goes here...
[self updateSummaryData];
[self calculateData];
}
You can update your current view in the viewWillAppear:animated message of the view:
If you have everything setup correctly, there is nothing to do, the UITabBarController will show your view, an your UIViewController will receive a viewWillAppear message, where you can do your update:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self updateSummaryData];
[self calculateData];
}
I strongly recommend reading the View Controller Programming Guide for iOS which describes in detail the main interface paradigms supported by the iPhone.

viewDidAppear: not firing under certain conditions?

I have the following items in my app nib:
the usual: file's owner, first responder window, delegate
View Controller "a"
View "b"
UIScrollView "c"
some other stuff in "b"
In my AppDelegate applicationDidFinishLaunching, I do this:
[window makeKeyAndVisible]
[window addSubView:a.view];
create a view controller "d"
create a navigationController "e" with rootviewcontroller "d"
invoke [c addSubView:e.view]
Question/problem: when I do all of the above, viewDidAppear: is not firing for "d". (but viewDidLoad IS firing.) How do I find out why it is not firing, and fix it so that it would fire?
(Why I want to use viewDidAppear: the above involves some chained animations and viewDidAppear looks like a good place for a view controller to know when its view has been loaded and animated, so it can trigger subsequent animations.)
Usually when you're manually screwing with the view hierarchy you won't get -viewWillAppear:, -viewDidAppear, etc.; they're called by various SDK methods, like -pushViewController:animated:, -presentModalViewController:animated:, and by UITabBarController when a tab gets selected.
When you add a view to the hierarchy yourself, it may or may not be onscreen or going-to-be-onscreen; the -addSubview: method doesn't make any assumptions about your intentions. Just call 'em yourself as you add the view.
The first thing you should be aware of is that viewDidAppear is a method of UIViewController and not of UIView, it really has nothing to do with views.
The second thing is that there can only be one "active" UIViewController at a time.
When you add "a"'s view to the window it becomes the active UIViewController and only "a" will receive the viewDidAppear message while "e" won't actually be getting any UIViewContoller related methods (viewDidAppear, viewWillAppear etc.)
As #Noah mentioned when you use pushViewController you will receive these messages because the method causes the pushed view Controller to become the "active" UIViewController.
My suggestion for you is that if you create controllers for views that are subviews don't subclass UIViewController but rather NSObject, it will reduce your confusion level as you won't expect to get your UIViewController methods called which they won't anyway.
I had a similar issue when I set the delegate of my navigation controller. So in my UINavigationControllerDelegate methods, I did something like this:
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//do something here
[viewController viewWillAppear:animated];
}
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController viewDidAppear:animated];
}