Uinavigation Controller issues - ios

Hi i created UInavigation controller in iOS programatically but the problem is when i move to next view controller i am directing to same screen.I created another view with name InfoView but when i push to InfoView it shows the same screen with buttons that i created in ViewController.
#import "AppDelegate.h"
#import "ViewController.h"
#interface AppDelegate ()
{
UINavigationController *navigation;
}
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
navigation = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
self.window.rootViewController = navigation;
[self.window makeKeyAndVisible];
return YES;
}
#import "ViewController.h"
#import "InfoView.h"
#interface ViewController ()
{
UIButton *RealVideo,*listen,*Readmat,*Look,*DiveIn;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor=[UIColor whiteColor];
[self designDeclare];
}
-(void)designDeclare{
RealVideo=[UIButton buttonWithType:UIButtonTypeCustom];
RealVideo.frame=CGRectMake(10,self.view.frame.size.height*0.2, CGRectGetWidth(self.view.frame)-20, CGRectGetHeight(self.view.frame)/7);
[RealVideo addTarget:self action:#selector(real:) forControlEvents:UIControlEventTouchUpInside];
[RealVideo setTitle:#"Real Video" forState:UIControlStateNormal];
RealVideo.backgroundColor=[UIColor colorWithRed:0.744f green:0.000f blue:0.000f alpha:1.00f];
[self.view addSubview:RealVideo];
listen=[UIButton buttonWithType:UIButtonTypeCustom];
listen.frame=CGRectMake(CGRectGetMinX(RealVideo.frame),CGRectGetMaxY(RealVideo.frame)+20, CGRectGetWidth(RealVideo.frame), CGRectGetHeight(RealVideo.frame));
// [listen addTarget:self action:#selector(Listen:) forControlEvents:UIControlEventTouchUpInside];
[listen setTitle:#"Listen" forState:UIControlStateNormal];
listen.backgroundColor=[UIColor purpleColor];
[self.view addSubview:listen];
Readmat=[UIButton buttonWithType:UIButtonTypeCustom];
Readmat.frame=CGRectMake(CGRectGetMinX(RealVideo.frame),CGRectGetMaxY(listen.frame)+20, CGRectGetWidth(RealVideo.frame), CGRectGetHeight(RealVideo.frame));
// [Readmat addTarget:self action:#selector(Listen:) forControlEvents:UIControlEventTouchUpInside];
[Readmat setTitle:#"Reading Material" forState:UIControlStateNormal];
Readmat.backgroundColor=[UIColor colorWithRed:0.000f green:0.412f blue:0.851f alpha:1.00f];
[self.view addSubview:Readmat];
Look=[UIButton buttonWithType:UIButtonTypeCustom];
Look.frame=CGRectMake(CGRectGetMinX(RealVideo.frame),CGRectGetMaxY(Readmat.frame)+20, CGRectGetWidth(RealVideo.frame), CGRectGetHeight(RealVideo.frame));
[Look addTarget:self action:#selector(Look) forControlEvents:UIControlEventTouchUpInside];
[Look setTitle:#"Look" forState:UIControlStateNormal];
Look.backgroundColor=[UIColor colorWithRed:0.400f green:1.000f blue:0.400f alpha:1.00f];
[self.view addSubview:Look];
DiveIn=[UIButton buttonWithType:UIButtonTypeCustom];
DiveIn.frame=CGRectMake(self.view.frame.size.width*0.7,CGRectGetMaxY(Look.frame)+20, CGRectGetWidth(RealVideo.frame)/4,CGRectGetHeight(RealVideo.frame)/1.5);
[DiveIn setTitle:#"Dive In" forState:UIControlStateNormal];
DiveIn.backgroundColor=[UIColor colorWithRed:0.941f green:0.471f blue:0.353f alpha:1.00f];
[self.view addSubview:DiveIn];
}
-(void)real:(id)sender{
}
-(void)Look{
InfoView *infoVC=[[InfoView alloc]init];
[self.navigationController pushViewController:infoVC animated:YES];
}
]1

A navigation controller works like a stack so you can push and pop viewcontroller exactly like a stack behaves in the real world. Think of a navigation controller as a stack of viewcontrollers, so you cant actually add a UIView, but what you would like to do instead is to add the uiview as a subview in your view controller and push that view controller onto the navigation controller stack with a simple:
[navigationcontroller pushViewController:aViewcontroller];
Please read through Apple Documentation for more insight.

You can't push a View. You need to push a View Controller.
If you want to show the View on top of the same View Controller, then you need to add the InfoView as the subView, preferably with animation.
But if you wanted to push the InfoView then you should create a UIViewController in your Storyboard and then add the InfoView as that View Controller's subview.
Let's say you create a new View Controller called InfoViewcontroller which is going to hold the InfoView. Now go to the InfoViewcontroller's -viewDidLoad method and add the following line
InfoView *infoVC=[[InfoView alloc]initWithFrame:self.view.frame];
[self.view addSubview:infoVC];
However, as you don't want to touch your storyboard, you may want to add it as a subView with animation. So, you can change your Look method with something like-
-(void)Look{
InfoView *infoVC=[[InfoView alloc]initWithFrame:self.view.frame];
[UIView transitionWithView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self.view addSubview:infoVC];
}
completion:NULL];
}
When the InfoView.m looks like-
#import "InfoView.h"
#implementation InfoView
-(id)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
if(self){
self.backgroundColor=[UIColor whiteColor];
}
return self;
}
#end
Note: you need an -initWithFrame method as your InfoView needs to know it's frame size.

Related

UIButton click not working if subview of UIWIndow

I am creating an iOS library. My library when initiated from AppDelegate will create a button on top of the screen.
I have created the button and it is showing up. But when I click, the target method is not evoked.
This is how I have created the button and assigned its action in the library
- (void) addLoginButton {
UIWindow *appWindow = [[[UIApplication sharedApplication] delegate] window];
UIButton *loginButton = [UIButton buttonWithType:UIButtonTypeSystem];
[loginButton setFrame:CGRectMake((appWindow.frame.size.width/2)-35, 20, 70, 20)];
[loginButton setBackgroundColor:[UIColor blueColor]];
[loginButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[loginButton setTitle:#"Login" forState:UIControlStateNormal];
[loginButton addTarget:self action:#selector(auLoginClicked) forControlEvents:UIControlEventTouchUpInside];
[appWindow addSubview:loginButton];
if([appWindow.rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navCon = (UINavigationController *)(appWindow.rootViewController);
if (!navCon.navigationBar.isHidden) {
navCon.navigationBar.layer.zPosition = 0;
}
}
loginButton.layer.zPosition = 5;
}
- (void) auLoginClicked {
NSLog(#"Hello");
}
I copied your code and have the same result.It's really strange and i am still working on it.I confirm it is the storyboard that caused the result,because i use your code in my project which does not use the storyboard,it works properly.
But please do not use loginButton.layer.zPosition = 5;It is not a proper way .
Here are some advices:
But If are you using UINavigationController Use:
[self.navigationController.view.window addSubview:aView];
If are you using UITabBarController Use:
[self.tabBarController.view.window addSubview:aView];
In AppDelegate you can directly assign a view to window. In appDelegate didFinishLaunchingWithOptions method Use:
[self.window addSubview:aView];
Hope it helps...
Instead of adding your button as a subview of window add this
then your button will get action.
[appWindow.rootViewController.view addSubview:loginButton];
If you add your view(Button) as a subview of window, then it won't be able to get events from user.That is the reason why your button not responding to event.
Debug it you will come to understand:)
If you want that to be on the top of every viewController, then check if UINavigationController is not the initialViewController then create a your own NavigationController and make it as initialContoller. It will make your button will be visible throughout the app(until the user by himself present any other VC)
UIWindow *appWindow = [UIApplication sharedApplication].keyWindow;
[appWindow addSubview:view];
You just need to fetch the keyWindow of the application and add the button as a subview. You don't have to set the zPosition

Add UIView to KeyWindow, How to Animate UIView Off Screen When pushViewController is Called?

I have added a UIView to my [UIApplication sharedApplication].keyWindow and it is working properly.
When a button on the UIView is tapped, I want to push a new UIViewController onto the underlying NavigationController
This all works, but how can I make the UIView animate off the screen, to the left, with the underlying UIViewController ?
You can animate your custom view and at the same time pass the control to the mail view controller to push the next view controller onto the navigation controller's stack... Below is the example code which I have simulated. The animation of your custom view should be in sync with the view controllers animation.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_v = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0, 0, 50, 30)];
[btn setTitle:#"Button" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[_v addSubview:btn];
_v.backgroundColor = [UIColor redColor];
[[[UIApplication sharedApplication] keyWindow] addSubview:_v];
}
- (void)btnClicked:(id)sender {
NSLog(#"Btn Clicked");
[UIView animateWithDuration:0.2
delay:0.1
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
_v.frame = CGRectMake(-_v.frame.size.width,
_v.frame.origin.y, _v.frame.size.width, _v.frame.size.height);
}
completion:^(BOOL finished)
{
}];
UIViewController *c = [self.storyboard instantiateViewControllerWithIdentifier:#"TestVC"];
[self.navigationController pushViewController:c animated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

How to go one view controller to another view controller when we login with social networks in ios

Hi i am new for Ios and in my app i am trying to move one view controller to another view controller when we login with social networks as like twitter for this i have already registered my app with twitter
According to my code when we tapped on twitter login button then twitter login page will be loaded on screen and there is "AuthorizedApp" button is available on twitter login page when we click on that button we get user details
After we get that user details i want move another page
Note:-
My main intention is when we clicked on that "AuthorizedApp" button then i want to move another page please help me some one
According to my code i am getting exception like:- Warning: Attempt to present on whose view is not in the window hierarchy!
My code:-
#import "ViewController.h"
#import "FHSTwitterEngine.h"
#import "ViewController1.h"
#import "AppDelegate.h"
#interface ViewController ()<FHSTwitterEngineAccessTokenDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[FHSTwitterEngine sharedEngine]permanentlySetConsumerKey:#"XXXXXXXXXXXXXX" andSecret:#"XXXXXXXXXXXXXXXXXXXXXXXXXX"];
[[FHSTwitterEngine sharedEngine]setDelegate:self];
[[FHSTwitterEngine sharedEngine]loadAccessToken];
//google plus login button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(loginOAuth)
forControlEvents:UIControlEventTouchUpInside];
// [button setImage:[UIImage imageNamed:#"twitter-icon.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(10, 390, 300, 30);
button.backgroundColor = [UIColor redColor];
CALayer * d = [button layer];
[d setMasksToBounds:YES];
[d setCornerRadius:20];
[self.view addSubview:button];
}
- (void)loginOAuth {
UIViewController *loginController = [[FHSTwitterEngine sharedEngine]loginControllerWithCompletionHandler:^(BOOL success) {
NSLog(success?#"L0L success":#"O noes!!! Loggen failure!!!");
NSLog(#"User name ---->>>%#",FHSTwitterEngine.sharedEngine.authenticatedUsername);
NSLog(#"User id ------> %#",FHSTwitterEngine.sharedEngine.authenticatedID);
[self movetoanotherview];
}];
[self presentViewController:loginController animated:YES completion:nil];
}
-(void) movetoanotherview{
ViewController1 *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
[dvc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentViewController:dvc animated:YES completion:nil];
}
I think this is happening because you're creating a view controller in a block. The view controller will be gone together with the block at the end of it's scope.
Try to declare dvc as a property inside your .h file (or at the top of your .m file)
#property (strong, nonatomic) ViewController1 *dvc;
Then do this instead:
self.dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
[_dvc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentViewController:_dvc animated:YES completion:nil];

IOS 6 subviews overlap toolbar in parent view

I am following Apress Beginning IOS 6 for school where we were asked by the professor to implement a custom algorithm that switches between 3 views (blue, yellow, and green) with each press of the "Next View" button in the toolbar. My approach was to add the subviews at different indices and shuffle the views in the hierarchy in BIDSwitchViewController.m:
#import "BIDSwitchViewController.h"
#import "BIDYellowViewController.h"
#import "BIDBlueViewController.h"
#import "BIDGreenViewController.h"
NSInteger count;
#interface BIDSwitchViewController ()
#end
#implementation BIDSwitchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.yellowViewController = [[BIDYellowViewController alloc] initWithNibName:#"YellowView"
bundle:nil];
self.greenViewController = [[BIDGreenViewController alloc] initWithNibName:#"GreenView"
bundle:nil];
self.blueViewController = [[BIDBlueViewController alloc] initWithNibName:#"BlueView"
bundle:nil];
//the topmost view is the last one in the stack (2)
[self.view insertSubview:self.blueViewController.view atIndex:2];
[self.view insertSubview:self.yellowViewController.view atIndex:1];
[self.view insertSubview:self.greenViewController.view atIndex:0];
[self.view setBackgroundColor:self.blueViewController.view.backgroundColor];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.blueViewController = [[BIDBlueViewController alloc]
initWithNibName:#"BlueView" bundle:nil];
[self.view insertSubview:self.blueViewController.view atIndex:0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.;
self.blueViewController = nil;
self.yellowViewController = nil;
self.greenViewController = nil;
}
- (IBAction)switchViews:(id)sender
{
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:
UIViewAnimationTransitionFlipFromRight
forView:self.view cache:YES];
switch (count)
{
case 0:
[self.view sendSubviewToBack:self.blueViewController.view];
[self.view bringSubviewToFront:self.yellowViewController.view];
[self.view setBackgroundColor:self.yellowViewController.view.backgroundColor];
break;
case 1:
[self.view sendSubviewToBack:self.yellowViewController.view];
[self.view bringSubviewToFront:self.greenViewController.view];
[self.view setBackgroundColor:self.greenViewController.view.backgroundColor];
break;
case 2:
[self.view sendSubviewToBack:self.greenViewController.view];
[self.view bringSubviewToFront:self.blueViewController.view];
[self.view setBackgroundColor:self.blueViewController.view.backgroundColor];
break;
}
if (++count >= 3)
{
count = 0;
}
[UIView commitAnimations];
}
#end
Here is the code in BIDAppDelegate.m where the root view controller is added as an instance of BIDSwitchViewController:
#implementation BIDAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.switchViewController = [[BIDSwitchViewController alloc]
initWithNibName:#"SwitchView" bundle:nil];
UIView *switchView = self.switchViewController.view;
CGRect switchViewFrame = switchView.frame;
switchViewFrame.origin.y += [UIApplication
sharedApplication].statusBarFrame.size.height;
switchView.frame = switchViewFrame;
//[self.window addSubview:switchView];
self.window.rootViewController = self.switchViewController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
And the BIDSwitchViewController.h header file:
#import <UIKit/UIKit.h>
#class BIDSwitchViewController;
#interface BIDAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) BIDSwitchViewController *switchViewController;
#end
The app and logic all work as the views switch from blue -> yellow -> green and back to blue again. As shown in the first picture (BIDBlueViewController's BlueView.xib subview of the BIDSubViewController) each of the views overlap the toolbar slightly. I have double and triple checked all of my simulated metrics in IB with the help of one of my classmates:
Am I using poor practice in shuffling the topmost views through the view hierarchy array, instead of removing each view via the book's method of "removeFromParentViewController()," or is their another, hidden cause for the sub views not properly sitting inside / behind the parent view?
Your UIToolbar control's Z-Order on it's view is behind your blue view controller. Since you created it in IB, you can add an IBOutlet for it, and bring it's view to top of the parent view. You're loading the ViewControllers as subviews, so they are all subviews of self.view of your parent.
In your header definition:
IBOutlet *toolBar UIToolbar;
Bring to front in your implementation.
[self.view bringSubviewToFront:toolBar];
You can do this after you've added the blue controller subview or at the end of all your case statements.

How to interrupt viewWillAppear hierarchy

I have a rootViewController, in it's viewDidLoad method, I initialized another two ViewController2* object and their views as subview of rootViewController.view, then I set first ViewController2* controller.view.hidden = YES.
Then, on v1 has a button handler, when touch it, it present a UINavigationController, after that touch 'dismiss' button call dismissViewControllerAnimated on v1.
The question is: when dismiss complete, the two of ViewController2* fire viewWillAppear. How to make it only fire the viewWillAppear on the visible one, but not on the hidden one?
the rootViewController's implementation:
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.v1 = [[ViewController2 alloc] init];
self.v1.title = #"v1";
[self.view addSubview:self.v1.view];
self.v1.view.hidden = YES;
self.v2 = [[ViewController2 alloc] init];
self.v2.title = #"v2";
[self.view addSubview:self.v2.view];
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"POP" forState:UIControlStateNormal];
[btn sizeToFit];
[btn addTarget:self action:#selector(touchHandler:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:btn];
}
- (void)touchHandler:(id)sender {
UINavigationController * nc= [[UINavigationController alloc] initWithRootViewController:[[UIViewController alloc] initWithNibName:nil bundle:nil]];
((UIViewController *)[nc.viewControllers objectAtIndex:0]).navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"dismiss" style:UIBarButtonItemStyleBordered target:self action:#selector(dismissHandler:)];
[self presentViewController:nc animated:YES completion:nil];
}
- (void) dismissHandler:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
ViewController2:
#implementation ViewController2
- (void)viewWillAppear:(BOOL)animated
{
NSLog(#"%#",self.title);
}
#end
viewWillAppear will fire on your UIViewController's, even if the view controllers view is set hidden=YES.
You can surely test if (self.view.hidden == YES) in your viewWillAppear delegate method if you want to prevent some expensive operation from occurring, but beware that if you later make that view un-hidden, that viewWillAppear won't fire then.
Simple, the reason why those methods are called is because the viewController's view is part of the main window's view hierarchy. This means that it has a superview that has a superview that has a superview and so on until that superview is the main window.
Instead of hiding and unhiding the viewController views, you should instead add and remove them from their superview. Also, to make sure that viewWillAppear and viewDidAppear are called correctly at the correct times, take a look at ViewController Containment:
http://www.cocoanetics.com/2012/04/containing-viewcontrollers/

Resources