I'm writing a view based app, but I'm a bit confused about loading my views. I'd like to have four different views loaded at the same time in the same window. I can't seem to figure out how to do this. I'd prefer to do everything programatically rather than with the interface builder if possible.
My 4 views are: a UIView, a UIWebView, a UITableView and another UIView with buttons.
Thanks in advance for the help.
Views in an iPhone app are arranged hierarchically - that is, each view has a "parent" view (excepting the root view). The interesting bit here is that UIWindow is itself a subclass of UIView, so you can add all four views to your window directly. (This may not be the best approach, but it's perhaps the simplest.)
All you really have to do is initialize each of your four views programmatically with the location and dimensions you want them to have in the UIWindow. You do this by giving each view a frame parameter, either in the init method or afterwards (depending on the type of view). So, for example, in your app delegate you could add this code:
CGRect frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
UIView *view = [[[UIView alloc] initWithFrame:frame] autorelease];
[window addSubview:view];
This will create a 100x100-pixel view and add it to the upper left corner of the window. You can do similar things for each of the other three views.
Note that developers usually don't initialize views directly in the app delegate - a better approach might be to have a fifth view take the place as the root view for the other four, then add that root view to the window. You can use a view controller for the fifth view to make this task easier - move the view initialization code into that view controller's implementation, then from the app delegate you can just instantiate the view controller and let it take over from there.
You can use [self parentViewController] to get access to the parent UIView
Related
I haven't been able to find anything on this and feel it likely isn't possible in a simple manner.
Can I have a view, such a loading bar for example which constantly sits over every other view controller until I choose to dismiss it but at the same time any underlying view can still be interacted with? Sort of acting like a system view. Be persistent when presenting new view controllers and all.
Thanks.
Add it as a subview of your window. Like this:
UIView *myView = ...
[self.window addSubview:myView];
Rather than adding it to the window, as #JackyBoy suggests, add it to the window's rootViewController's view. That will rotate along with the device. If you just add it to the window, you may have problems with rotation.
UIView *myView = ...
[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:myView];
There are 4 items on MyViewController.xib window:
File's Owner (of type MyViewController)
First Responder (of type UIResponder)
View (of type UIScrollView)
FloatingView (of type UIView)
Both View and FloatingView contain some controls (such as labels and text fields...), and are designed using IB. The FloatingView must NOT occupy the full screen; and my app functionality requires the FloatingView to move to a newly tapped location when user taps on the screen.
An instance variable UIView *myFloatingView; is defined as a property/IBOutlet and synthesized, which is connected to the FloatingView view on IB.
On viewDidLoad method, I am adding myFloatingView to my view controller's view as its subview as:
-(void)viewDidLoad {
[super viewDidLoad];
CGRect myFrame = CGRectMake(50, 50, 150, 150); //initial location
self.myFloatingView.frame = myFrame;
[self.view addSubview:self.myFloatingView];
}
Apple documentation says each UIViews should have a corresponding view controller. However, I am using only one view controller here. I am treating the floating UIView object as a regular control, or say as a panel. I might in future allow user to hide/unhide this floating view.
Is this a good practice, or is there a better way (any example) to do what I am trying to do?
Thank you very much for your help.
What you are doing is fine. In fact, a viewController can often control a whole hierarchy. Also, you said your floatingView was in the same nib as your root view? If so, you can probably make it a subview there, instead of adding as a subview in viewdidLoad.
I am developing a navigation based application in iPhone.
In which I want to create physical menu button like menu like the one in Android phones.
The menu can be accessed from any view in the hierarchy.
Do any one have any idea how can we achieve this .
Can we add a drawer like menu to UINavigationBar ?
Please don't suggest the tabbarcontroller as it is the last option.
What you should do is create a subclass of UIViewController, e.g. MasterViewController. Have all of the view controllers subclass MasterViewController. In the MasterViewController you can write code to create and display your drawer view, and then all of your view controllers will inherit that code and can call it on themselves at any point.
To slide the view in:
drawerView.frame = CGRectMake(0, -1*drawerView.frame.size.height, self.view.frame.size.width, whateverHeight);
[UIView beginAnimations:nil context:NULL];
drawerView.frame = CGRectMake(0, 0, self.view.frame.size.width, whateverHeight);
[UIView commitAnimations];
I think that what you want is just set the titleView of UINavigationItem to an arbitrary UIView to handle user taps.
This doesn't have to be a text label :)
If that's the case then I'd suggest you taking sharedInstance with flags tracking the hierarchy of the view controller stack. Every time when user navigate just update your sharedInstance and do the custom menu preparation and populate it. The good practice would be reuse your UI component rather than making it new on every navigation operation.
You can create a "DrawerView" class and import it into where you will want to use it. Then you can use presentModalViewController: myDrawer to make it appear when you need it. Hope that makes sense.
Its very simple..
In one XIB u can add many views right. now add two main views like say data view and down side button view u want in. (if m nt wronge with 4 buttons to navigate) now keep ur this view at top . and all the other hirarchy of views u can add in that data view.
I think you should create a singleton UIViewController or UIView for this. Advantage of the UIViewController is that it can be presented with the presentModalViewController:animated: method, and also if you need, you can push it to your navigation stack. Also an advantage that you have a UIView instance in the same time.
Using the singleton pattern, you can reach your class anywhere.
Check this link from the official documentation about singleton in objective-c: Creating a Singleton Instance
Or you can use Matt Gallagher's macro (because this is very comfortable to use): Singleton macro
If you can get iOS 5 beta, I highly recommend it. The new beta dev release has an extension on UIViewController, dubbed by Apple as container view controllers. They are very easy to set up, and I am using one in my app.
Container view controllers work like UINavigationControllers and UITabBarControllers in that they allow you to add child view controllers, not just child views. Like I've said, they are simple to set up. I'll explain how:
Create a new class called ContainerController. Add an initialization method called - (id)initWithNavigationController:(UINavigationController *)controller. It's implementation should look something like this:
if ((self = [super init])) {
[self addChildViewController:controller];
controller.view.frame = CGRectMake(0, 0, 320, 420); // Leave room for the menu at bottom of the screen
[self.view addSubview:controller.view];
}
The reason we are adding a navigation controller is because it keeps this container controller from doing transitions, which is more complicated.
In the ContainerController's viewDidLoad method, create the menu:
[super viewDidLoad];
UIView *menuWrapperView = [[[UIView alloc] init] autorelease];
menuWrapperView.frame = CGRectMake(0, 420, 320, 40); // Place a wrapper for the menu buttons directly below the navigation controller
UIButton *button1 = ...;
UIButton *button2 = ...;
[menuWrapperView addSubview:button1];
[menuWrapperView addSubview:button2];
[self.view addSubview:menuWrapperView];
With this approach (using child view controllers), your views and navigation controller will get their needed memory warning, view loading, and rotation handling method calls when needed.
I want to duplicate this controller same functionality without using it, this is because tab bar controllers are not customizable at all (fixed size, toggleable state tabs, etc...).
I want a customized "tab bar" that contains whichever view I want. And also I need to push view controllers leaving this customized tab bar fixed in its position.
I´ve seen lots off apps that do this, and I was wondering if using different UIWindow objects (one for the custom tab bar and other one for the content) was the best approach.
Any advice or guidance on this?
Thanks in advance.
Definitely not UIWindows - in an iPhone app there should only ever be one UIWindow.
I'd make a UIViewController subclass that had your new navigation bar ui at the top and a UIView underneath it. This view would be used to contain all the views of the controllers you are going to push in it. The view would have clipsToBounds set to YES to make sure your other controllers views don't overlap your navigation bar etc.
It would also have an array to hold the list of controllers that are currently inside it.
Your controller would implement the pushViewController:animated: methods etc to allow you to add other view controllers to the stack - you would add the new controller to your array and would add it's view as a subview of your controller's view.
However, it's actually quite a lot of work to make this well - a navigation controller will release child controller views on low memory warnings, handle rotation, animating on/off views etc. Are you 100% sure that this is what you want to do?
I've used a very simple approach. I subclass UITabbarController and during the init:
// Custom TabBar View
//
self.tabBar.hidden = YES;
MyTabBarView *myTabBarView = [[MyTabBarView alloc] initWithFrame:CGRectMake(0, 1024-44, 768, 44) // it'a an iPad app
configuration:configuration]; // an array of dictionary representing the view controllers
[self.view addSubview:myTabBarView];
[bottomBarView release];
then I load some view controllers with:
aViewController.hidesBottomBarWhenPushed = YES;
From MyTabBarView instance I perform on the UITabBarViewController:
setSelectedIndex:
In this way I've a customizable full screen application without pains.
I think I'm missing something fundamental and so I want to ask the community for some help. I'm building an app based around a basic iPhone Utility Application. My MainView and FlipsideView share some elements so I have created separate ViewControllers and nib files for those pieces. In order to do this I have done the following:
1. Created a viewcontroller called searchDateViewController which is the file's owner of searchDateView.xib
2. searchDateView.xib is basically a UIView with a UILabel inside, the view is wired up correctly
3. Inside both MainViewController.m and FlipsideViewController.m I add a subview as folllows:
- (void)loadView{
[super loadView];
searchDateViewController = [[SearchDateViewController alloc] initWithNibName:#"SearchDateView" bundle:nil];
[[searchDateViewController view] setFrame:[searchDateView frame]];
[[self view] addSubview:[searchDateViewController view]];
...
}
Everything displays and works just fine. Basically depending on actions that happen in each of the main and flipside views the UILabel of the nib is changed. However, I wanted to do something slightly different if the searchDateViewController is loaded from the MainView or the FlipsideView. However, I can't seem to figure out which ViewController is adding the searchDateViewController subview.
In searchDateViewController I tried:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"superview %#", self.view.superview);
NSLog(#"parentviewcontroller %#", self.parentViewController);
}
In both cases I get nil.
So my question is - can I find out which ViewController is adding searchDateViewController a a subview? If so how? Or if my logic here is completely messed up, how should I be doing this?
Thanks!
viewDidLoad is invoked when the view controller has loaded its view. In your case, that happends in this line:
[[searchDateViewController view] setFrame:[searchDateView frame]];
At that moment, you haven't yet called addSubview: so it is no wonder the view's superview is nil.
To solve your problem, you should define a property inside SearchDateViewController to distinguish between the different cases. This property would then be set accordingly by the parent controller that creates the SearchDateViewController instance.
Generally, I do not think it is a good idea to use a UIViewController subclass as a controller for a view that is used as a subview of one or several fullscreen views rather than be used as a fullscreen view itself. Much of UIViewController's logic works on the assumption that it is used to manage a fullscreen view. For instance, with your design, I think it's possible that SearchDateViewController will modify the view's frame when the device orientation changes etc. Since you don't need all this functionality for a non-fullscreen subview, I suggest you subclass your SearchDateViewController directly from NSObject.
ViewController and views are completely separate.
In most cases, when you add a subview to a parent view you don't add its controller to the parent's viewController. The exception to this rule is the navigation controller which adds the controller instead of the view to maintain a hierarchy of view controllers.
Your SearchDate viewController can't find a parent controller because you never assigned one and the system does not do it automatically. You can just assign a parent controller when you evoke the view from another controller.
searchDateViewController.parentController=self;