My App have one Parent View Controller(MainViewController.h/m - UIViewController, without NIB file) for all other UIViewControllers, which is at the same time RootViewController.
My App should support iOS 5, so AutoLayout is off..
Hier some code:
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.mainViewController = [[MainViewController alloc] init];
[self.window setRootViewController:self.mainViewController];
[self.window makeKeyAndVisible];
return YES;
}
In MainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if ([[UIScreen mainScreen] bounds].size.height == 568) {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone5" bundle:nil];
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone" bundle:nil];
}
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
}
[self addChildViewController:_homeViewController];
[self.view addSubview:_homeViewController.view];
[_homeViewController didMoveToParentViewController:self];
}
- (void)changeFromViewController:(UIViewController*)fromViewController toViewController:(UIViewController*)toViewController withDuration:(NSNumber*)duration {
toViewController.view.frame = self.view.bounds;
[toViewController.view layoutIfNeeded];
[self addChildViewController:toViewController];
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:[duration floatValue]
options:UIViewAnimationOptionTransitionCrossDissolve
animations:nil
completion:^(BOOL finished) {
[toViewController didMoveToParentViewController:self];
[fromViewController willMoveToParentViewController:nil];
[fromViewController removeFromParentViewController];
}];
}
HomeViewController*.xib contains 7 UIButtons. If one of them touched MainViewController Class is being called to change from one ChildViewController(HomeViewController, etc..) to another.
HomeViewController.m
- (IBAction)firstButton_click:(id)sender {
[(MainViewController *)self.parentViewController setAnimationForChangeFrom:self toStartTestSettingsViewControllerWithDuration:[NSNumber numberWithDouble:0.4] andWithDelay:[NSNumber numberWithDouble:0.1]];
}
Now about the Problem.
On iPhone(Device or Simulater) with iOS 6 and above UIButtons respond only after several touches. Buttons placed on the bottom of the view to work, must be touched more times, then buttons placed on the top. After several touches, when event fired and view was changed, when I come back to this View everything work normally. I have this problem only with iPhone iOS 6.x. It works normally on iPhone iOS 5.x and iPad 5.x-6.x.
If I make HomeViewController RootViewController, Buttons of course respond to events. But then I can't transform with UIViewAnimationOptionTransitionCrossDissolve Animation[[UIViewController transitionFromViewController:toViewController:duration:options:animations:completion:], because view must have same Parent View Controller.
What did I wrong? Is it bug? Is there any solution?
Any help would be greatly appreciated.
Write this in .pch file
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (IS_IPHONE_5) {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone5" bundle:nil];
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone" bundle:nil];
}
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
}
[self addChildViewController:_homeViewController];
[self.view addSubview:_homeViewController.view];
}
The Problem was because of [_homeViewController didMoveToParentViewController:self];.
It is superfluous.
ViewDidLoad in MainViewController should be:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if ([[UIScreen mainScreen] bounds].size.height == 568) {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone5" bundle:nil];
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController~iPhone" bundle:nil];
}
} else {
_homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
}
[self addChildViewController:_homeViewController];
[self.view addSubview:_homeViewController.view];
}
Now everything works..
Related
I am trying to create a back button to return to the main menu of my app, what is happening now, is, once I press the back button, it shows the main menu, but then the app crashes out a second later.
The code I use for back button is;
- (void)backButtonPressed:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
From the AppDelegate.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[[MenuViewController alloc] initWithNibName:#"MenuViewController_iPhone" bundle:nil] autorelease];
} else {
self.viewController = [[[MenuViewController alloc] initWithNibName:#"MenuViewController_iPad" bundle:nil] autorelease];
}
navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController];
navigationController.navigationBarHidden = YES;
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
I cannot see where I am going wrong? It seems to call the right screen, yet crashes straight after?
EDIT - Here is MenuViewController.m file;
#import "MenuViewController.h"
#import "MagicAppDelegate.h"
#import "MagicViewController.h"
#interface MenuViewController ()
#end
#implementation MenuViewController
- (void)viewDidLoad
{
self.view.frame = [[UIScreen mainScreen] bounds];
[super viewDidLoad];
// [self initLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)onStart:(id)sender
{
MagicViewController* viewController;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
viewController = [[MagicViewController alloc] initWithNibName:#"MagicViewController_iPhone" bundle:[NSBundle mainBundle]];
else
viewController = [[MagicViewController alloc] initWithNibName:#"MagicViewController_iPad" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
- (void)dealloc {
[super dealloc];
}
#end
Please use below code,do u want go mainmenuview controller.
[self.navigationController popToRootViewControllerAnimated:YES];
Actually, I don't understand your code: In the statement navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController]; you are sending an alloc to something that seems to be the instance of class UINavigationController, but alloc is a class method. I therefore assume myNavigationViewController is a subclass of UINavigationController (but then is should start with a capital letter).
The new instance returned is then assigned directly, i.e. without using a setter method, to variable navigationController. It is therefore not retained. If your statement returns an autorelease object, it will thus be released as soon as the program returns to the main event loop.
Try thus to use thus a setter method, i.e. self.navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController];
I am trying to launch 1 of 3 views on startup. The view I want to launch is depending on the device type. Here is what I have so far in the AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568.0) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_Portrait5" bundle:nil];
}
else if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 480.0) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_Portrait4" bundle:nil];
}
else {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_PortraitPad" bundle:nil];
}
}
The problem is that, when I launch the app, there is a black screen.
You aren't setting the controller on the window, at the end of the method, add:
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
There's a much cleaner way to write that code (including the fix):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSString *nibName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nibName = #"ViewController_PortraitPad";
} else {
if ([UIScreen mainScreen].bounds.size.height == 480.0) {
nibName = #"ViewController_Portrait4";
} else {
nibName = #"ViewController_Portrait5";
}
}
self.viewController = [[ViewController alloc] initWithNibName:nibName bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
I am implement the TabBar app for ipad & iphone both. But In IPAD the navigation controller is not working for ipad nib in table cell. The viewdid Load method is not call for ipad.
But it work fine for iphone..
self.navigationController is NULL for ipad only in my class to navigate.
Help me!!
my code is as follow:
//Connet.m:
if(i==1)
{
TwitterController *tc;
if ([self isPad]) {
tc = [[TwitterController alloc] initWithNibName:#"TwitterController_ipad" bundle:nil];
}
else
tc = [[TwitterController alloc] initWithNibName:#"TwitterController" bundle:nil];
[self.navigationController pushViewController:tc animated:YES];
NSLog(#"%#",self.navigationController); /Problem ****NULL*****///////
//TWITTER.m
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Custom initialization
self.navigationController.navigationBarHidden = YES;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = YES;
NSString *urlAddress = #"https://twitter.com/UJUDGEIT1";
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Request Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webv loadRequest:requestObj];
}
Try the following code:
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
NSString *nibname=#"";
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
nibname=#"TwitterController_ipad";
}
else{
nibname=#"TwitterController";
}
TwitterController *view = [[TwitterController alloc] initWithNibName:nibname bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:view];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Write this code in your app delegate class. The viewDidLoad method gets called.
piyush
how you implement your tab bar.
make each controller of tab bar as navigation controller. it may called your view did load method.
following code may help you. it create 2 controller on tab bar. finally at it to root view controller.
-(void)createTabbar{
NSMutableArray *controllers = [[NSMutableArray alloc] init];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
//Controller 1
PasswordVC *pvc = [[PasswordVC alloc] initWithNibName:#"PasswordVC" bundle:nil];
UINavigationController *passwordNav = [[UINavigationController alloc] initWithRootViewController:pvc];
passwordNav.navigationController.navigationBarHidden=YES;
[controllers addObject:passwordNav];
pvc.title = #"Password";
[pvc release];
[passwordNav release];
//Controller 2
SettingVC *SVC = [[SettingVC alloc] initWithNibName:#"SettingVC" bundle:nil];
UINavigationController *settingNav = [[UINavigationController alloc] initWithRootViewController:SVC];
settingNav.navigationController.navigationBarHidden=YES;
[controllers addObject:settingNav];
SVC.title = #"Settings";
[SVC release];
[settingNav release];
}
else { //ipad
}
_tabBarController = [[[UITabBarController alloc] init] autorelease];
_tabBarController.delegate=self;
_tabBarController.viewControllers = controllers;
_tabBarController.customizableViewControllers = controllers;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:_window cache:NO];
_window.rootViewController = _tabBarController;
[UIView commitAnimations];
}
I wanna at certain point of the program to load different xib for iphone and for ipad but wanna to reuse most part of the code. how can I achieve this ?
Append ~ipad or ~iphone to the end of the file name. So SomeViewController~ipad.xib or SomeViewController~iphone.xib for instance.
See iOS Supports Device-Specific Resources.
If you create a template project that is universal you can inspect the code created for that version. For Example:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPhone" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
} else { // iPad
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
PSGameViewController *detailViewController = [[PSGameViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
}
[self.window makeKeyAndVisible];
return YES;
}
or from tableView:didSelectRowAtIndexPath:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (self.detailViewController == nil) {
self.detailViewController = [[PSGameViewController alloc] initWithNibName:#"PSGameViewController_iPhone" bundle:nil];
}
self.detailViewController.model = selectedModel;
[self.navigationController pushViewController:self.detailViewController animated:YES];
self.pushedIndexPath = indexPath;
} else { // iPad
self.detailViewController.model = selectedModel;
}
As this configuration is not supported I was wondering what alternatives people have used.
I have a universal app which currently uses a 4 tab UITabBarController on both the iPhone and iPad.
As I'd now like to use the splitviewcontroller I am faced with a design decision.
I guess I could just go with a toolbar at the top and go from there but was hoping there were more interesting techniques.
You could replicate a UITabBar within a modelViewController that pops up when a button on the bottom of the screen is taped and swap Views. :)
I created a UITabBarController subclass which properly propagates the rotation messages to all UISplitViewControllers it contains. This maintains the correct internal state of the UISplitViewControllers. However, one of the SplitViewController delegate methods is not called if the SplitViewController is not visible, so I account for this in the detail view controller viewWillAppear method. I've confirmed this works in iOS5.0 - iOS6.1
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
OSMasterViewController *masterViewController = [[[OSMasterViewController alloc] initWithNibName:#"OSMasterViewController_iPhone" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
self.window.rootViewController = self.navigationController;
} else {
OSMasterViewController *masterViewController = [[[OSMasterViewController alloc] initWithNibName:#"OSMasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
OSDetailViewController *detailViewController = [[[OSDetailViewController alloc] initWithNibName:#"OSDetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
masterViewController.detailViewController = detailViewController;
UISplitViewController *splitViewController = [[[OSSplitViewController alloc] init] autorelease];
splitViewController.viewControllers = #[masterNavigationController, detailNavigationController];
splitViewController.delegate = detailViewController;
OSTestViewController *secondaryController = [[[OSTestViewController alloc] init] autorelease];
OSTabBarController *tabBarController = [[[OSTabBarController alloc] init] autorelease];
tabBarController.viewControllers = #[self.splitViewController, secondaryController];
self.window.rootViewController = tabBarController;
}
[self.window makeKeyAndVisible];
return YES;
}
OSTabBarController.m
#import "OSTabBarController.h"
#implementation OSTabBarController
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
for(UIViewController *targetController in self.viewControllers){
if(targetController != self.selectedViewController && [targetController isKindOfClass:[UISplitViewController class]]){
[targetController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
for(UIViewController *targetController in self.viewControllers){
if(targetController != self.selectedViewController && [targetController isKindOfClass:[UISplitViewController class]]){
[targetController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
}
}
#end
DetailViewController
#implementation OSDetailViewController
-(void)viewWillAppear:(BOOL)animated{
//the splitViewController:willHideViewController:withBarButtonItem:forPopoverController: may not have been called
if(!UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
self.navigationItem.leftBarButtonItem = nil;
}
}
#pragma mark - UISplitViewControllerDelegate Methods
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
}
#end