UINavigationController subclass won't set titleView on load - objective-c

I've just created a simple subclass of UINavigationController.
#import "TTNavigationController.h"
#implementation TTNavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *logo = [UIImage imageNamed:#"logo"];
UIImageView *logoView = [[UIImageView alloc] initWithImage:logo];
self.navigationItem.titleView = logoView;
}
But when I run the project the navigation bar has not the titleView with the logo.
Otherwise if I try to move those 3 lines of code in viewDidLoad of my view controller works fine. Why?

You can't use self.navigationItem because the navigation controllers own navigationItem is never used. It has this property because it is a type of view controller but it isn't actually displayed because the viewControllers (or, more specifically, the topViewControllers) navigationItem is displayed.
So, change the view controller navigationItem (either directly, or when it is pushed).

Related

load an image when app launch - Objective-c

I set an image like this to my view:
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"map3.jpg"]];
Right now I have it in a button action method. But how do I make it set directly when the app is launched?
If you want to set the backgroundColor of a UIViewController's view, then move your code into viewDidLoad and adapt likewise:
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"map3.jpg"]];
A UIViewController doesn't have a backgroundColor directly, but its view does, like any other UIView.
One way is to put that logic within your view controller's -viewDidLoad method for the UIImageView property.
UIView
If you are in a UIView class place the code in either initWithFrame: or initWithCoder:
initWithFrame gets called when you instantiate the view from code (e.g. UIView *myView = [[UIView alloc] initWithFrame:CGRectZero];
initWithCoder: gets called whenever the UIView is loaded from an XIB file.
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html
UIViewController
If in a UIViewController a common place to put it would be in viewDidLoad
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

SideMenu black view

I am trying to make a sidebar menu but i have a little problem.
I explain :
I created an UIViewController that i called sideMenuViewController
In my viewController Class (the initial view controller), in the header file, i import my class SideMenuViewController and i wrote :
-(IBAction)openSideMenu:(id)sender;
#property(nonatomic, retain) SideMenuViewController *sideMenu;
The openSideMenu action is associated to the menu button.
I implemented this method like this :
- (IBAction)openSideMenu:(id)sender {
CGRect destination = self.view.frame;
if(destination.origin.x > 0){
destination.origin.x = 0;
}else{
destination.origin.x += SideMenuX;
}
[UIView animateWithDuration:0.4 animations:^{
self.view.frame = destination;
}completion:^(BOOL finished) {
if(finished){
}
}];
}
SideMenuX is a macro : #define SideMenuX 154.4
My viewDidLoad method looks like this :
- (void)viewDidLoad
{
[super viewDidLoad];
_sideMenu = [[SideMenuViewController alloc] init];
[self.view sendSubviewToBack:_sideMenu.view];
// Do any additional setup after loading the view, typically from a nib.
}
The problem is that when i click on the menu button, i get a black screen and not my side menu view.
Thank you in advance !
Two problems:
You are not adding the sideMenu at all. Try adding it to the parent view (self.view.superview), which in your case most likely will be the UIWindow: [self.view.superview insertSubview:_sideMenu.view belowSubview:self.view]; If you are using a navigation controller, use self.navigationController.view instead self.view.
Not sure if you initialized the view with a NIB or the Storyboard (see below if you didn't).
Here is a working example. I created the left view controller inside the storyboard like this:
Throw a View Controller component on the storyboard.
Select the controller on the left column, and go to the Identity Inspector on the right column (alt+cmd+3):
Set the Class to SideMenuViewController
Set the Storyboard ID to SideMenuViewController
Instantiate the controller inside viewDidLoad with
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
self.sideMenu = (SideMenuViewController*)[storyboard instantiateViewControllerWithIdentifier:#"SideMenuViewController"];
then insert it as child of the superview.
(Answering the comment below)
This line is the problem:
[self.view.superview addSubview:_sideMenu.view];
In a NIB based project the superview is UIWindow, but in a Storyboard project, the self.view.superview of a UIViewController is nil. You can solve this, for example, adding a UINavigationViewController. Follow these steps:
Throw in a "Navigation Controller"
Delete the view controller it points to.
Press Ctrl and drag the pointer from the UINavigationController to your view controller, and select "root view controller" on the dialog that appears.
Drag the arrow pointing to your view controller to the UINavigationController (the one that marks the initial view controller, not the one that comes from UINavigationController).
Then change your code to
_sideMenu = [[SideMenuViewController alloc] initWithNibName:#"SideMenuViewController" bundle:nil];
[self.navigationController.view.superview insertSubview:_sideMenu.view belowSubview:self.navigationController.view];
To hide the navigation bar of the UINavigationController, select it in the Storyboard and click Hidden in the Attributes Inspector (alt+cmd+4).
All you're seeing is black because you don't have the side menu view added. Try this:
- (void)viewDidLoad {
[super viewDidLoad];
_sideMenu = [[SideMenuViewController alloc] init];
[self.view addSubview:_sideMenu.view];
[self.view sendSubviewToBack:_sideMenu.view];
}

how to change current displaying uiview without using segues?

i want to change display to an UIViewController which has view controller at storyboard from an UIViewController class which hasn't got view controller at storyboard. There is no segue at storyboard for this...
Just like this:
In your AppDelegate.m do a quick setup:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
ViewController *sourceViewController = [[ViewController alloc] init];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:sourceViewController];
[self.window setRootViewController:nav];
return YES;
}
In above example replace ViewController class with your own class of sourceViewCntroller
- (IBAction) didPressMyButton {
NewViewController* newVC = [[[NewViewController alloc] init] autorelease];
[self.navigationController pushViewController:newVC animated:YES];
}
Connect this action to a button on storyboard or embed view change in any method. You will need to setup UINavigation controller first.
I'm not completely sure I understand what you're trying to do, but I think you are asking how to load a view controller from a storyboard, without using a segue, from a method in a view controller that wasn't loaded from the storyboard.
First, in your storyboard, select the view controller you want to load, and open the Identity Inspector. Set the Storyboard ID of the view controller. It looks like you want to load a MapViewController, so let's say you set the storyboard ID to map.
In your code, you can load the view controller like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
MapViewController *mapViewController = [storyboard instantiateViewControllerWithIdentifier:#"map"];
Once you have a reference to the view controller, you can set its properties or send it messages. You can then display it in whatever way you want - maybe by pushing it onto a navigation controller, or by presenting it, or by setting it as the root view controller of your window.

UIViewController with no Xib showing blank when using pushViewController

I have subclassed UIViewController like so:
#interface MyClass : UIViewController
I dont have a xib file for the controller, instead I would just like to use a blank UIView and I will layout elements programmatically on that. The problem arrises when I try and push this view controller.
MyClass * thing = [[ImageGallery alloc] init];
[self.navigationController pushViewController:thing animated:YES];
A new title bar is animated in, but there is no view, its see through, so I end up seeing a static background I set on my main "window/view". How should I properly subclass a UIViewController without a xib?
What you have described is correct behaviour so far.
You will want to override the -(void)loadView method, and after the [super loadView]; call, you can set your background colour and begin to place the objects in programatically, that you desire.

Ensuring that a UIViewController is fully set up before loadView is called

There is a UIViewController that uses a UIImageView, and that image view is initialized with image data (NSData). It does not use a XIB, but creates its view programmatically:
- (void)loadView
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:self.imageData]];
scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
scrollView.contentSize = imageView.bounds.size;
scrollView.delegate = self;
[scrollView addSubview:scrollView];
}
That data has to be set by another controller which allocs, inits, and pushes this view controller onto the navigation controller:
ImageViewController *imageViewController = [ImageViewController alloc] init];
imageViewController.imageData = someData;
[self.navigationController pushViewController:imageViewController animated:YES];
How do I know that everything that needs to be done, which in this case, is setting the data, is done before loadView is called? Or, do I not know, and I have to create a custom initializer, or somehow call loadView again when the view controller receives the data?
I have faced many similar situations where I was confused about what will happen, such as with UITableViewControllers.
How do I know that everything that needs to be done, which in this case, is setting the data, is done before loadView is called?
Because the documentation mentions that view controllers do not load their views until they are needed. And the view controller's view is not needed before the navigation controller tries to push it on screen.
Besides, the proper place for assigning the imageData to your image view is probably viewDidLoad ("If you want to perform any additional initialization of your views, do so in the viewDidLoad method."). And your loadView method will not do anything visible in its current form. You have to assign a view to the view controller's view property in that method.
loadView will happen when the view property of the view controller is accessed. The code you wrote will work fine, because the first time the view property will be accessed will be somewhere inside pushViewController.
If you wrote this you'd have a problem:
ImageViewController *imageViewController = [ImageViewController alloc] init];
NSLog(#"size = (%.0f, %.0f)", imageViewController.view.frame.size.width,
imageViewController.view.frame.size.height);
imageViewController.imageData = someData;
[self.navigationController pushViewController:imageViewController animated:YES];
because you access the view property in the NSLog. That would cause loadView to get called before imageData was set.