How to Switch Views inside a nib file.

Discussion in 'iOS Programming' started by Nekbeth, Feb 26, 2011.

  1. Nekbeth, Feb 26, 2011
    Last edited: Feb 26, 2011

    Nekbeth macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #1
    I've seen some tutorials and read some articles about it, a lot of developers like to do it from a Window base App. Well, I haven't found a way to explain a way to do it from a normal UIViewController and it's nib file. The difference of course is that it does not have a delegate nor window. This links explains it well, but inside a Window base app (http://www.youtube.com/watch?v=HaAPa3gIwMY&feature=related

    My question is .. In order for this Switch View to happen in the UIViewController, Do I have to create a Window and add the actions & declarations in the delegate (if so, it will be a mess to be switching around files) or maybe just giving the UIViewController some Protocol Delegate powers, I have no idea. :confused:

    So, I just want to know how to add a switch (button) to another similar View (same size and all) just with different text or photo. The following code is not working for me (.h) :
    Code:
    @interface CheeseController : UIViewController  {
    	
    	IBOutlet UIView *view1;
    	IBOutlet UIView *view2;
    	
    }
    @property (nonatomic, retain) IBOutlet UIView *view1;
    @property (nonatomic, retain) IBOutlet UIView *view2;
    
    //Switch views for Detailviews
    - (IBAction) SwitchTo1;
    - (IBAction) SwitchTo2;
    
    @end
    
    and .m
    Code:
    #import "CheeseController.h"
    
    
    @implementation CheeseController
    
    @synthesize view1;
    @synthesize view2;
    
    
    -(IBAction)SwitchTo2 {
    	
    	[view1 setHidden:YES];
    	[view2 setHidden:NO];
    }
    
    -(IBAction)SwitchTo1 {
    	
    	[view2 setHidden:YES];
    	[view1 setHidden:NO];
    }
    
    
    - (void)viewDidLoad {
    	[super viewDidLoad];
    	
    	self.navigationItem.title = @"Cheese Cake";
    }
    
    @end
    I appreciate any kind of advice, Thank you :eek:
     
  2. Shawnpk macrumors 6502

    Joined:
    Jan 13, 2011
    Location:
    Los Angeles, CA
    #2
    I couldn't get it to work with two views, but if you change view2 to a UIWindow it will work.
     
  3. Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #3

    That is correct Shawnpk, thanks for pointing it out. The only setback with changing to a UIWindow is that it hides the TabBar and there is no way to edit a Window size, only views (I need the hight of the frame to be 411). Do you know a way to get over this? :confused:
     
  4. Shawnpk macrumors 6502

    Joined:
    Jan 13, 2011
    Location:
    Los Angeles, CA
    #4
    I'm not able to try anything as I'm not at home, but what if you try to add a view to the window then add your tabbar to the view?
     
  5. Nekbeth, Feb 26, 2011
    Last edited: Mar 6, 2011

    Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #5
    It could work, only that I already have this Navigation working to show a detail view (the navigation is inside a TabBar) .. I would like the TabBar to be present at all time in all views, but if I add a window, a view inside and then a tabBar.. there will be a very small space left for the recipes.

    Right now I have a Detail View that comes from a nav bar, I added UIToolBar with BarButton Items inside. How can I activate each Bar Button to show a view in that same Detail View? I could just add more nib files and call them up but since there is going to be 4 buttons for each recipe.. i'm thinking it will be too much nib files, or is there a more efficient way to do it? Calling just the views inside one nib files would be ideal but I can't because I need to create a Window and that just takes away all the background controllers (navbar and tabbar).

    * I have attached a photo of the DetailView where I want the Bar Buttons info to show up (middle space)
     
  6. Macman1993 macrumors 6502

    Macman1993

    Joined:
    Nov 23, 2007
    #6
    Open the nib file for the view you are adding. Select the view and open the attributes window. There is a simulated interfaces option. Select simulated tabbar option, that will auto resize your window so it wont cover your toolbar.
     
  7. Nekbeth, Feb 27, 2011
    Last edited: Feb 27, 2011

    Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #7
    Hello Macman, I follow your instructions and while the view in the nib file changed. Once I build and run, when I navigated to the Cheese Recipe (detail view nib file) the Ingredients button opens up it's view taking all the screen. I'm calling the Ingredient nib file the following way in the CheeseController.m :
    Code:
    -(IBAction)ShowIngredients {
    	
    	Ingredients *ingredientes = [[Ingredients alloc] initWithNibName:@"Ingredients" bundle:nil]; 
    	ingredientes.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    	[self presentModalViewController:ingredientes animated:YES];
    	[ingredientes release];
    }
     
  8. Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #8
    Solve it :)

    It took a lot of testing, moving around views, etc. This might not be the best way, so any feedback is positive. I did it by creating more views using that CheeseCakeController, the important thing here is to have the original view of the Controller to be the parent of all views you'll be creating. After that, just connect the views you created to the file owner's (you need to declare them before of course) and in the .m file declare some actions so you can hide or show the view, implement them and connect them to the buttons you'll be using. Something like this :
    Code:
    //Switch views Here
    
    -(IBAction)SwitchTo2 {
    	
    	[view2 setHidden:YES];
    }
    	
    -(IBAction)SwitchTo1 {
    	
    	
    	[view2 setHidden:NO];
    }
    
    
    That's it, views should switch up inside the same navigation controller with the tab bar visible too. Best of all is that your using the same nib file for all switch views, making your project cleaner. I'm learning as I go, so If any experience developer points out a warning for doing it this way, please go ahead, it's all good and for the better to share knowledge :D
     
  9. sverrisson macrumors newbie

    Joined:
    Jan 14, 2011
    Location:
    Reykjavik
    #9
    When using different views inside the nib. You use the following to get an array of the views:
    Code:
    NSArray *array = self.view.subviews;
    NSLog(@"Array: %@", array);
    But remember to use "tag" to number your views and then you can easily identify them.
    To switch between the views:
    Code:
    [self.view exchangeSubviewAtIndex:1 withSubviewAtIndex:0];
    where self.view is pointing to your empty view that you have set in the nib. Make sure the other views are under this one in the tree (you can see this in "Tools -> Reveal Document in Window").
    What you basically do is swap the order of the subviews under the master view.
    The hidden feature works which you use here above, but it is not recommended because if you have controls on the view, the action will first go to the bottom view in the hierarchy and that may be the bottom hidden view (which you probably don't want to act to the gesture).
     
  10. Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #10
    Thanks sverrisson, I will try getting the array and using tags for the views like you mention, so far I'm still using the hidden feature and actions are working ok with each view, It's only a matter of getting the three to show the bottom view first and so on hierarchically. I'll upload some images and the method of the 5 views after I finish the controller. Later on, when adding more controls to each view, I'll let you know if any problem occur. Thanks for the alternative
     
  11. seepel macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #11
    Depending on your use case there are two ways that I would set this up.

    Case 1: You have one view controller that will control two different views (view1, view2)
    Here I would connect the controller's view property to a generic UIView to act as the container view. I would then set view1 and view2 up as properties of the view controller. When needed to switch remove view1 from its superview, and add view2 to the controller's view (the generic container view). Then you can leverage UIView's hooks into core animation and make it look snazzy. For example transitionWithView:...

    Case 2: You have two views that will be controlled by two different view controllers.
    Here I would present the second view controller as a modal view of the first. A good example of this is the Utility Application template in XCode.
     
  12. Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #12
    Hi seepel, I think I took the first case you said, I have the generic container view of the controller on the back with several views inside it and just hiding or showing each view as it is invoked by the ButtonItem. The switching of the 4 views works very nice, about the transition you mention.. how would you implement that effect on the views. Do you call it inside each switching method? I image something like
    Code:
    [self.view transitionWithView] ...  ??:confused:
    Thanks
     
  13. seepel macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #13
    You'll want to look at the documentation UIView Class Reference, but here is a quick example.

    Assume that the container view is your controller's view, and that it currently has view1 (a property of the controller) in its view hierarchy. The following code will have the effect that the container view will flip from left to right revealing view2 (also a property of the controller, and not in the view hierarchy).

    When everything is sad and done, what you have done is to remove view1 from controller.view and added view2 to it.

    Using this function is just a convenient way to tell the iPhone "Hey I'm doing something here, and you should animate it for me". What goes on behind the scenes is basically Apple has provided a lot of commonly used Core Animation code for your convenience, and instead of doing these common things by hand every time, you can just call these static functions provided with UIView.

    I'm sure you could google transitionWithView and/or "Core Animation" and find all sorts of extra goodies you can do with this kind of stuff. Alternatively, you could take a look at the class reference I linked to at the beginning of this post and have a look to the "Animating Views with Blocks" and "Animating Views" sections and play around with the functions listed.

    Code:
    [UView transitionWithView:self.view
                     duration:0.5
                      options: UIViewAnimationTransitionFlipFromLeft
                   animations:^(void) {
                                 [self.view1 removeFromSuperview];
                                 [self.view addSubview:self.view2];
                   }
                   completion:NULL]
    
    Don't be scared off by the
    Code:
    ^(void) {
    }
    
    It's called a block, and just think of it as a way of embedding a function into a parameter. Anything that happens inside the { } will be animated, assuming it is in the list of animatable things... including but not necessarily limited to

    adding/removing a subview
    changing the opaque property of a view,
    changing the bounds/frame/center of a view,
    changing the alpha of a view,
    changing the transform of a view,
    and perhaps some things I've neglected to mention, you can find a full list somewhere in the Core Animation Guide.
     
  14. sverrisson macrumors newbie

    Joined:
    Jan 14, 2011
    Location:
    Reykjavik
    #14
    The method used in Case 1 works, but it is slow. The view needed is loaded each time. If you are only using one view at a time it is fine. But, if you are for example swapping views with rotation then use the method I talk about above, about changing the view order, then the rotation is smooth and no delay when loading the view needed.

    I had problems with Case 2 when using a view as a part of splitView Controller because modal view covers the window. Some times your view is not covering the whole window and then this does not work. But this is definitely the easiest way to go if the design allows.
     
  15. Nekbeth, Mar 2, 2011
    Last edited: Mar 6, 2011

    Nekbeth thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City

Share This Page