In my app start delegate I have the following code:
[window addSubview:[myTabBarController view]];
UIImageView *banner =
[[[UIImageView alloc] initWithFrame:CGRectMake(0,381,320,50)] autorelease];
banner.backgroundColor = [UIColor redColor];
[window addSubview:banner];
[window makeKeyAndVisible];
This works as expected. The tab bar is visible and also my UIImageView is visible.
I need to modify that UIImageView everywhere in my app (I have the TabBarController, a NavigationController, UITableView, etc)
For example, I want to change the background color when I click in a UITableCell.
I tried everything: self.window.view.subviews, atObjectIndex, neither seems to get the current background color.
first you do not need an UIImageView if its just to set a background-color. A UIView is sufficient.
to solve your problem, you can keep a reference to the view who's background-color you want to change in you AppDelegate. you can then access you AppDelegate (and the the reference to your view) from anywhere in your app like so:
((YouAppDelegateName*)[UIApplication sharedApplication].delegate).yourViewReferenceProperty
Are you sure you want to do that?
It's usually best to arrange your app so that the only object manipulating a view controller's view hierarchy is that view controller. If other objects want to change something, they either change the data model or send a message to the view controller. So, you might give your view controller a 'backgroundColor' property, and its setter would update the appropriate view. Setting the background color indirectly through the view controller makes it easier to make changes to your view hierarchy in the future and generally keeps things better organized.
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];
I'm trying to set the background for a number of UITableViews that are loaded inside a UINavigationController. I'm using the appearance proxy added in iOS 5 but it's not working how I'm expecting it to.
The app uses a UISplitViewController, with the master view being the UINavigationController.
Inside this, I have a UITableViewController subclass called PBMasterTableViewController.
In my AppDelegate I have the following :
UIImageView *bgView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"menuBg.png"]] autorelease];
[[UITableView appearanceWhenContainedIn:[PBMasterTableViewController_Ipad class], nil] setBackgroundView:bgView];
This is working fine, and my main menu in the split view has the background that I want.
From this main menu, I 3 other UITableViewController sublasses that are pushed onto the nav controller when I select the relevant rows. I cannot however get the background of these tables to change using the appearance proxy. I'm trying the following :
UIImageView *bgView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"menuBg.png"]] autorelease];
[[UITableView appearanceWhenContainedIn:[PBTwitterTableViewController class], nil] setBackgroundView:bgView];
This is also in the appDelegate right below the code previously shown that works (without the repetition of the image view creation however) but this simply does nothing! When I push an instance of the PBTwitterTableViewController onto the nav controller, I simply get a standard table view with no background change.
I know that I could simply change the background views in the tableViewControllers themselves, however I don't want these backgrounds to be there when the menu is shown in the splitViewControllers popover when rotated to portait, hence I am trying to use appearanceWhenContainedIn:
I also don't want to simply set the appearance to be when contained in the UISplitViewController, as in 2 instances I have a UITableView being loaded into the detail section, so this would then change the appearance of those which I do not want.
Is there another way of doing this without the appearance proxy that will still allow me to change the background for when it is in the popover, or is there a way of making this work with the proxy, or am I just missing something stupid?
Thanks
EDIT :
I've just tried creating a subclass of the UINavigationController and tried using [[UITableView appearanceWhenContainedIn:[PBMenuNavigationController class], nil] setBackgroundView:bgView]; which is again working fine for the main menu, but not for any other UITableView pushed onto the stack, so I'm really stumped now :(
OK sorted it. Just doing it inside each view and checking that the parent controller isn't something that I don't want. Thanks anyway
I have UITabBarController with 2 tabs. One resizes just fine, when StatusBar size changes (emulator "Toggle In-Call Status Bar" menu item). The other one doesn't.
The problematic tab item contains a static view, which dynamically loads one or another view depending on certain things. While getting this setup working I discovered that main tab view did NOT automagically send e.g. viewWillAppear and viewWillDisappear messages to my dynamic subviews.
Apple docs explained this was because dynamically added views were not recognized by the system.
#interface MyTabViewController : UIViewController
{
UIView *mainView;
FirstViewController *aController;
SecondViewController *bController;
}
...
if (index == 0)
{
self.aController = [[FirstViewController alloc]
initWithNibName:#"FirstViewController" bundle:nil];
[self.mainView addSubview:aController.view];
[self.aController viewWillAppear:YES];
}
How can I get StatusBar size changed event into my dynamic subviews? The "didChangeStatusBarFrame" doesn't work, as documented elsewhere.
Have you taken a look at this question?
Also, can we see your App Delegate code using application:didChangeStatusBarFrame:?
You could program a resize yourself, but usually this is done by using "auto resizing masks". (UIView has a property autoresizingMask).
I'm not sure about it but since your were adding those views programmatically maybe you forgot to set the autoresize mask. Without it the view won't resize automatically when the status bar frame changes.
[newView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth];
I hope it helps.
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;
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