How to use custom UINavigationBar - objective-c

I have subclass of UINavigationBar.
#interface MyNavigationBar : UINavigationBar
Made some changes and now want that my application NavigationController would use it:
_navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[_window addSubview:[_navigationController view]];
[self.window makeKeyAndVisible];
I want that _navigationController would have MyNavigationBar
How this could be done ?
Thanks.

You have to create a xib with a UINavaigationController in it. You can then select the navigationBar in Interface Builder and change the class to your subclass of UINavigationBar.
Then to make this a little easier to instantiate I add a category to `UINavigationController like:
#interface UINavigationController (DSCNavigationController)
+ (UINavigationController *)dsc_navigationControllerWithRootViewController:(UIViewController *)rootViewController;
#end
#implementation UINavigationController (DSCNavigationController)
+ (UINavigationController *)dsc_navigationControllerWithRootViewController:(UIViewController *)rootViewController;
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"DSCNavigationController" owner:nil options:nil];
NSAssert(1 == [topLevelObjects count], #"DSCNavigationController should have one top level object");
UINavigationController *navigationController = [topLevelObjects objectAtIndex:0];
NSAssert([navigationController isKindOfClass:[UINavigationController class]], #"Should have a UINavigationController");
[navigationController pushViewController:rootViewController animated:NO];
return navigationController;
}
#end
At the top of the class that uses it makes sure to import the category in my case it looks like
#import "UINavigationController+DSCNavigationController"
Then using it looks something like
MyViewController *myViewController = [[MyViewController alloc] init];
UINavigationController *navigationController = [UINavigationController dsc_navigationControllerWithRootViewController:myViewController];

UINavigationController has a read-only property
#property(nonatomic, readonly) UINavigationBar *navigationBar
since it is read-only you have to subclass UINavigationBar and override this property or make it read-write.E.g. :
MyNaviagtionBar *myBar = [[MyNavigationBar alloc] init];
_navigationController.navigationBar = mybar;
Or subclassing:
MyNavigationController.h
#class MyNavigationBar;
#interface MyNavigationController : UINavigationController
#property(nonatomic, strong) MyNavigationBar *navigationBar;
#end
MyNavigationController.m
#implementation MyNavigationController
#synthesize navigationBar = _navigationBar;
#end
And then change
_navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
to
_navigationController = [[MyNavigationController alloc] initWithRootViewController:self.viewController];

Related

How to add tab bar controller to the detail view of a split view controller application

I'm working on a catalog application for iPad/iPhone devices. I'm, using the master view template from XCode to have a base, in the root or master navigation controller I'm showing the list of the products and now I'm trying to add a tab controller to the detail view because each product have 3 different sections, one with some details, other with a specifications table and other with some pictures or images of the product.
I'm doing this programmatically, this is my code of AppDelegate.h
#import <UIKit/UIKit.h>
#import "MVADetailVwCtrl.h"
#import "MVATableVwCtrl.h"
#import "MVAModelVwCtrl.h"
#interface MVAAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UITabBarController *rootTabBarCtrl;
#property (strong, nonatomic) MVADetailVwCtrl *detailVwCtrl;
#property (strong, nonatomic) MVATableVwCtrl *tableVwCtrl;
#property (strong, nonatomic) MVAModelVwCtrl *modelVwCtrl;
#property (strong, nonatomic) NSArray* viewControllers;
#end
And this is the code on AppDelegate.m
#import "MVAAppDelegate.h"
#implementation MVAAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.detailVwCtrl = [[MVADetailVwCtrl alloc] init];
// self.newMoveVwCtrl.title = #"Product details";
UINavigationController *detailNavCtrl = [[UINavigationController alloc] initWithRootViewController:self.detailVwCtrl];
self.tableVwCtrl = [[MVATableVwCtrl alloc] init];
// self.myAccountsVwCtrl.title = #"Table";
UINavigationController *tableNavCtrl = [[UINavigationController alloc] initWithRootViewController:self.tableVwCtrl];
self.modelVwCtrl = [[MVAModelVwCtrl alloc] init];
// self.settingsVwCtrl.title = #"Pictures";
UINavigationController *modelNavCtrl = [[UINavigationController alloc] initWithRootViewController:self.modelVwCtrl];
self.viewControllers = [NSArray arrayWithObjects:
detailNavCtrl,
tableNavCtrl,
modelNavCtrl,
nil];
self.rootTabBarCtrl = [[UITabBarController alloc] init];
self.rootTabBarCtrl.viewControllers = self.viewControllers;
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
splitViewController.viewControllers = [NSArray arrayWithObjects: self.rootTabBarCtrl, [splitViewController.viewControllers lastObject], nil];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}];
[[UINavigationBar appearance] setBarTintColor:UIColorFromHex(0x009B3E)];
return YES;
}
I'm creating each tab and each navigation controller of each tab and storing all of them in an array, and then I'm retrieving the view controllers of the split view to change them with the new ones but I don't know if this is the best approaching.
Maybe there is a best method editing the storyboard, and I would like to keep the compatibility of the application with iPad and iPhone devices.
Could you help me please? Thanks in advance.
The code you posted won't run on iPhone since UISplitViewController is only supported on iPad.
Have you considered to use Storyboards instead of doing this programatically? I think in your case this could make things a lot easier. In this Stanford course the teacher explains how to make an iPhone app using storyboard universal and he also uses a split view controller.
Just switch the order of the view controllers in your split view, which will switch detail and master view.
splitViewController.viewControllers = [NSArray arrayWithObjects: [splitViewController.viewControllers firstObject], self.rootTabBarCtrl, nil];`

"initWithNibName" method not being called

NSString *nibName = #"SampleViewController"
UIViewController *controller = [[UIViewController alloc] initWithNibName:nibName bundle:nil];
using the above code to move to the "SampleViewController" xib... its working fine but initWithNibName method not triggering in the SampleViewController.
anyone can help me to trigger lifecycle method in SampleViewController
UIViewController is parent from which SampleViewController is implemented. So instead of UIViewController you need to use SampleViewController class instance.
SampleViewController *controller = [[SampleViewController alloc] initWithNibName:#"SampleViewController" bundle:[NSBundle mainBundle]];

How can I reuse a UIView and methods - DRY code in iOS

I have 2 methods that add the Previous, Next & Done toolbar above the iOS Keyboard and handle these actions. I'm looking for a way to code these methods once and reuse it across multiple UITableViewControllers. (DRY Code)
I find myself copy and pasting these methods into each UITableViewController. If I make a small change, I have to copy and pastes that change everywhere. The code below is just an example, I seem to be repeating myself a lot in my code.
Here's an example of the code I'd like to reuse:
- (void) createInputAccessoryView
{
_inputAccView = [[UIView alloc] initWithFrame:CGRectMake(10,0,310,42)];
UIToolbar *keyboardToolbar = [[UIToolbar alloc] init];
keyboardToolbar.barStyle = UIBarStyleBlackTranslucent;
[keyboardToolbar sizeToFit];
_segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Previous", #"Next", nil]];
[_segmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[_segmentedControl addTarget:self action:#selector(nextPrevious:) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *nextPrevButton = [[UIBarButtonItem alloc] initWithCustomView:_segmentedControl];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
NSArray *barItems = [NSArray arrayWithObjects:nextPrevButton, flexSpace, doneBtn, nil];
[keyboardToolbar setItems:barItems];
[_inputAccView addSubview:keyboardToolbar];
}
- (void) nextPrevious:(id) sender
{
switch(_activeTxtField.tag) {
case 1:
//Recipe Name
if (_segmentedControl.selectedSegmentIndex == 1){
[_descriptionTextField becomeFirstResponder];
_activeTxtField = _descriptionTextField;
}
break;
case 2:
//Recipe Description
if (_segmentedControl.selectedSegmentIndex == 0){
[_nameTextField becomeFirstResponder];
_activeTxtField = _nameTextField;
}
default:
break;
}
}
Create a custom UIView that defines the common input accessory view. Should include a definition of a delegate to allow the class using the accessory view to handle, for example, previous/next button taps as appropriate. Here's a header file example for a keyboard accessory view:
#import <UIKit/UIKit.h>
#class KeyboardAccessoryView;
#protocol KeyboardAccessoryViewDelegate <NSObject>
-(void)accessoryNext:(id)sender;
-(void)accessoryPrevious:(id)sender;
#end
#interface InputAccessoryView : UIView
#property (nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate;
#property (nonatomic, setter = enablePrevious:) BOOL previousEnabled;
#property (nonatomic, setter = enableNext:) BOOL nextEnabled;
-(id)initPreviousNextAccessory;
#end
Edit - showing details of use in a UIViewController.
The .h file:
#import <UIKit/UIKit.h>
#import "KeyboardAccessoryView.h"
#interface MyViewController : UIViewController <KeyboardAccessoryViewDelegate>
//...
#end
The .m file:
#import "MyViewController.h"
#interface MyViewController () {
KeyboardAccessoryView *inputAccessoryView;
}
#end
#implementation MyViewController
//...
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputAccessoryView = [[KeyboardAccessoryView alloc] initPreviousNextAccessory];
inputAccessoryView.delegate = self;
//...
}
-(void)accessoryNext:(id)sender{
// handle Next
}
-(void)accessoryPrevious:(id)sender{
// handle Previous
}
//...
#end

Transparent UITableView on top of several UIViewController and OpenGLView (Cocos2D)

Here is my code :
// View Controller with navigation bar
InAppPurchaseViewController *purchaseViewController = [[InAppPurchaseViewController alloc] init];
purchaseViewController.title = #"Magasin";
purchaseViewController.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissViewController:)] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:purchaseViewController] autorelease];
// Add `purchaseViewcontroller` TO container AND container ON openGLView
UIViewController *container = [[UIViewController alloc] init];
[container setView:[[CCDirector sharedDirector] openGLView]];
[container setModalTransitionStyle: UIModalTransitionStyleCoverVertical];
[container presentViewController:navController animated:YES completion:nil];
The UITableView is in purchaseViewController.
I was thinking of using [UIColor clearColor], BUT whatever I use it on I get a BLACK background on my UITableView. The cells get unselectable and unslidable (apart from the elements that are into the cells)
EDIT : The appdelegate
Here is the .h
#class AudioEngine;
#class RootViewController;
#class Score;
#interface AppDelegate : NSObject <UIApplicationDelegate, GameCenterManagerDelegate>
#property int CurrentPackage;
#property int CurrentScore;
#property int CurrentHighScore;
#property BOOL SoundShouldPlay;
#property BOOL PauseScreenUp;
#property(nonatomic, retain) AudioEngine *CustomAudioEngine;
#property(nonatomic, retain) GameCenterManager *CustomGameCenterManager;
#property(nonatomic, retain) UIWindow *window;
#property(nonatomic, readonly) RootViewController *ViewController;
#property(nonatomic, retain) NSString* CurrentLeaderBoard;
#property(nonatomic, retain) NSMutableArray *TenLastScoresArray;
+(AppDelegate *)get;
-(void)connectToGameCenter;
-(void)addScoreToLastScore:(Score*)score;
And the method did finish launching
-(void)applicationDidFinishLaunching:(UIApplication*)application
{
CC_DIRECTOR_INIT();
self.CurrentLeaderBoard = kLeaderboardID;
[[SKPaymentQueue defaultQueue] addTransactionObserver:[InAppPurchaseSingleton sharedHelper]];
[AudioEngine preloadBackgroundMusic];
[AudioEngine playBackgroundMusic:3];
self.SoundShouldPlay = YES;
[SceneManager goSplash];
}
Instead of presenting the view controller on container:
UIViewController *container = [[UIViewController alloc] init];
...
[container presentViewController:navController animated:YES completion:nil];
what should work is presenting it on the root view controller that the cocos2D template created for you. It is normally accessible through the app delegate:
UIViewController *rootViewController = (UIViewController*)[(YOURAPPDELEGATE*)[[UIApplication sharedApplication] delegate] viewController];
[rootViewController presentViewController:navController animated:YES completion:nil];
viewController is an ivar that the cocos2D default template add to the application delegate class. It is normally private, so you will need to define an accessor:
#property (nonatomic, readonly) RootViewController *viewController; //-- .h file
#synthesize viewController; //-- .m file
Hope this helps.
EDIT:
Based on what I have in my app delegate, I think you could try and instantiate the RootViewController like this:
CC_DIRECTOR_INIT
ViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
ViewController.wantsFullScreenLayout = YES;
[ViewController setView:[[CCDirector sharedDirector] openGLView]];
...

Navigate from a view to another

The main: xxxVieController
and the second: OptionViewController
in xxxView controller I have
.h
#interface iMetroAlertViewController : UIViewController {
IBOutlet UIButton *option;
}
-(IBAction) goToOption;
and
.m
#implementation iMetroAlertViewController
-(IBAction) goToOption{
NSLog(#"Works");
OptionViewController *dvController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
Of course a OptionViewController.xib, .m and .h are created...
When I push on the button, nothing happens (the link is done cause I have an NSLog
I don't understand why it doesn't work
It probably doesn't work because you don't have a navigation controller, so calling self.navigationController returns nil.
First you have to create the navigation controller
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
RootViewController *mainMenuVC = [[RootViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:mainMenuVC];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}