I have
#property (weak, nonatomic) IBOutlet UIPageControl *pageCountControl;
Here is my code.
Inside viewDidLoad
// I set the number of pages to 5.
self.pageCountControl.numberOfPages = 5;
// the main view will be the home page so I set it to the index 0
self.pageCountControl.currentPage = 0;
// Then I think that I have to dd the UIPageControl as subview to the current view.
[self.view addSubview:_pageCountControl];
[self.pageCountControl addTarget:self action:#selector(pageTurn:) forControlEvents:UIControlEventValueChanged];
}
// here is my question. I have a method that will be calling when the user moved through the pages. Do I have to create that page like the following code?
-(void)pageTurn:(UIPageControl *) page
{
int c = page.currentPage;
if(c==0)
{
// here
MainViewController *mainViewController = [self.childViewControllers objectAtIndex:self.pageCountControl.currentPage];
}
// and here
else if(c==1)
{
MainViewController *mainViewController =[self.childViewControllers objectAtIndex:c];
SecondViewController *secondViewController = [self.childViewControllers objectAtIndex:self.pageCountControl.currentPage];
}
else if(c==2)
{
SecondViewController *secondViewController =[self.childViewControllers objectAtIndex:c];
ThirdViewController *thirdViewController = [self.childViewControllers objectAtIndex:self.pageCountControl.currentPage];
}
}
I found some tutorial about using UIPageControl for moving between images but there is no tutorial about using ViewControllers.
I am not sure if I am making it right?
Thank you.
Hind
Related
When a user segues to a second VC from within a starting VC that is embedded in a UITabBarController, I change the title of the UITabbarItem with some code placed in the viewWillAppear method of the second view controller.
//Second VC, View WIll Appear
UITabBarItem *selectedItem = self.tabBarController.tabBar.selectedItem;
if (selectedItem) {
selectedItem.title = #"VoiceMail";
}
This works fine.
When the user returns to the starting view controller, I want to switch the title back.
I tried to do this by placing similar code in the view will appear method of the starting view controller.
Starting VC: ViewWIllAppear
UITabBarItem *selectedItem = self.tabBarController.tabBar.selectedItem;
if (selectedItem) {
selectedItem.title = #"Phone";
}
But it is having no effect, leaving the title as Voicemail.
WOuld appreciate any suggestions on how to change back to initial value.
Thanks for any suggestions.
Trying to change the "2nd" tab title by referencing .selectedItem in your "Starting VC" won't work, because at that point .selectedItem is StartingVC.
One approach would be to save a reference to the index of SecondVC... then, inside that VC, on viewWillDisappear you can reset its tab's title:
This is all in SecondVC:
#import "ChangeSecondViewController.h"
#interface ChangeSecondViewController ()
#property (assign, readwrite) NSInteger myTabIndex;
#end
#implementation ChangeSecondViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UITabBarItem *selectedItem = self.tabBarController.tabBar.selectedItem;
if (selectedItem) {
selectedItem.title = #"VoiceMail";
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
_myTabIndex = self.tabBarController.selectedIndex;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
UITabBarItem *myTabItem = [[self.tabBarController.tabBar items] objectAtIndex:_myTabIndex];
if (myTabItem) {
myTabItem.title = #"Phone";
}
}
#end
I create a subclass of UINavigationController, like this
#interface CustomNav : UINavigationController
#property(assign , nonatomic) BOOL canBack;
#end
#implementation CustomNav
- (void)viewDidLoad {
[super viewDidLoad];
self.canBack = YES;
// Do any additional setup after loading the view.
id target = self.interactivePopGestureRecognizer.delegate;
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]
initWithTarget:target action:#selector(handleNavigationTransition:)];
pan.delegate = self;
[self.view addGestureRecognizer:pan];
self.interactivePopGestureRecognizer.enabled = NO;
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
// NSLog(#"self.childViewControllers.count = %li",self.childViewControllers.count);
if (self.childViewControllers.count==1||!self.canBack) {
return NO;
}
return YES;
}
#end
but when i use it to push viewController , the navigationBar display deranged ,for example, it has A viewController, then it push another B viewController,but sometimes, it doesn't display the navigationItem of B , it just display the navigationItem of A , and then I push C to the CustomNav , it also display the navigationItem of A. i don't know why ,i found it seems the CustomNav display the navigationItem of B(or C) ,and then the navigationBar covered by the navigationItem of A . Could everyOne help me ? Thank you ever so much.
I am using a BookController class which is using pagenumbers to keep track of the current view. Currently I am creating each view controller on demand and writing the code programmatically. I would like to access the view controllers that I have created in the StoryBoard (the xib files) so that when I demand a new page it will access a Second view controller I have created.
// Provide a view controller on demand for the given page number
- (id) viewControllerForPage: (int) pageNumber
{
if ((pageNumber < 0) || (pageNumber > 31)) return nil;
if(pageNumber == 0){
//here is where I want to access the entire xib file that the SecondViewController is connected with
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
SecondViewController *myVC = (SecondViewController *)[storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
myVC = [BookController rotatableViewController];
return myVC;
}
else if(pageNumber == 1){
// Establish a new controller
UIViewController *controller = [BookController rotatableViewController];
// Add a text view
UITextView *textview = [[UITextView alloc] initWithFrame:(CGRect){.size = CGSizeMake(100.0f,100.0f)}];
textview.text = [NSString stringWithFormat:#"This is dedicated to people"];
textview.font = [UIFont fontWithName:#"Futura" size:18.0f];
textview.center = CGPointMake(475.0f, 700.0f);
[controller.view addSubview:textview];
// Add a label
UILabel *textLabel = [[UILabel alloc] initWithFrame:(CGRect){.size = CGSizeMake(200.0f, 200.0f)}];
textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
textLabel.text = [NSString stringWithFormat:#"1"];
textLabel.font = [UIFont fontWithName:#"Futura" size:18.0f];
textLabel.center = CGPointMake(475.0f, 985.0f);
[controller.view addSubview:textLabel];
// Add it as an image
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon#2x.png"]];
imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
imageView.center = CGPointMake(160.0f, 230.0f);
[controller.view addSubview:imageView];
return controller;
}
Just not sure how to make a call to access that xib file i've created and make it into the first page (page=0). The second page (page =1) is an example of how i have drawn all the other pages in my book programmatically. Thanks!
Remember the Storyboard is just a collection of NIBs which simply instantiate the hierarchy of each view and connect the outlets to the owning view controllers. You do not want to instantiate the Storyboard yourself to just create a single view controller. What that is doing is creating new instances when the application has already been launched and is running with different instances. Even if you did have them wired up they would be wired to instances which are redundant and not the actual instances you want.
What I would do instead is create an individual NIB file for SecondViewController which you will use separately. Then you will need to wire it together. If this code is within the instance you need to access you would simply pass it along to a property on SecondViewController. Or maybe you just pass along values but most likely you will want to set a delegate property and define a protocol for SecondViewController to call back to the instance which created it.
For your code you can simply load the NIB with the following code.
SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.delegate = self;
You just need to define that delegate and possibly any properties you need to give data to the newly created view controller.
Below is an example of a delegate setup which I recently created for a SideBar interface using a Storyboard. I have a container view for the Header VC which is in the Home VC. This Header VC could be like your SecondViewController because I could not connect it in the Storyboard so I did it with code. First I created a delegate property on the Header VC.
#protocol IFHeaderDelegate;
#interface IFHeaderViewController : UIViewController
#property (nonatomic, assign) IBOutlet id<IFHeaderDelegate> delegate;
#end
#protocol IFHeaderDelegate <NSObject>
- (void)headerViewDidToggleSideBar:(IFHeaderViewController *)sender;
#end
Then when a button is tapped I use the delegate for the callback. (Notice I use an NSAssert to verify the delegate is defined just to give me a heads up if I missed it.)
#import "IFHeaderViewController.h"
#interface IFHeaderViewController ()
#end
#implementation IFHeaderViewController
- (IBAction)siderBarButtonTapped:(id)sender {
NSAssert(self.delegate != nil, #"Delegate must be defined!");
if (self.delegate != nil) {
[self.delegate headerViewDidToggleSideBar:self];
}
}
#end
But in order to wire it up I had to set the delegate from the Home VC which I could not do from the Storyboard. What I did was set it in the Home VC when the embed segue was fired in prepareForSegue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DebugLog(#"segue.identifier: %#", segue.identifier);
if ([#"HomeHeader" isEqualToString:segue.identifier]) {
NSAssert([segue.destinationViewController isKindOfClass:[IFHeaderViewController class]], #"Destination VC must be the Header VC");
IFHeaderViewController *headerVC = (IFHeaderViewController *)segue.destinationViewController;
headerVC.delegate = self;
}
}
You can find the full project on GitHub: https://github.com/brennanMKE/Interfaces/tree/master/SideBar
I have a viewcontroller, if I press a button, another viewController is loaded, but the first is not unloaded. I want to access a variable form the first view controller from the second, actually a UIScrollView, so that I can use it in this way:
scroll1.hidden = YES;
How can I do this? I tried importing the .h file, but still I cannot use the UIScrollView
EDIT:
NSArray* stack = [self.navigationController viewControllers];
NSInteger currentIndex = [stack indexOfObject:self];
ViewController* linkToA = (ViewController*)[stack objectAtIndex:currentIndex - 1];
[linkToA.scroll1.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
[linkToA.scroll1 addSubview:linkToA.backgroundImage];
or
ViewController *linkToA = [[ViewController alloc] init];
linkToA = (ViewController*)self.presentingViewController;
[linkToA.scroll1.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
[linkToA.scroll1 addSubview:linkToA.backgroundImage];
just make sure first view controller does have a property of your scrollView in the header:
#property (nonatomic, strong) UIScrollView *scrollView;
if you don't have a latest xcode put #synthesize scrollView to the implementation of the first controller
lets say your first controller is A and the second is B
if B is a added as a modal then use this:
linkToA = (A*)B.presentingViewController;
if B is added to navigationControllerStack:
NSArray* stack = [B.navigationController viewControllers];
NSInteger currentIndex = [stack indexOfObject:B];
linkToA = (A*)[stack objectAtIndex:currentIndex - 1];
after you have a linkToA you have to do
linkToA.scrollView.hidden = YES;
hope this will help
I have a navigation based application.On click of a button on the navigation bar in the first screen , I am able to push another view controller as follows :
-(void) buttonClicked:(id)sender
{
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
}
Now i have a UIView(separate .h and .m files) as part of the first screen. On click of a button in the UIView, i want to push the SecondViewController.
I have tried the following :
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
It doesnt work!! Kindly help
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
The problem here is that home isn't part of the navigation stack, so [home navigationController] is surely nil. I'm not quite clear on what you're trying to do here, but just creating a view controller doesn't mean that it's actually part of the view controller graph.
Why would it work? Randomly creating view controllers whose view is not even visible, is not the solution. You can either keep a reference to the VC in the view like this:
#imlementation ViewController
- (id) init
{
// ...
aView = [[CustomView alloc] init];
aView.viewController = self;
// ...
}
#end
#interface CustomView
#property (assign) ViewController *viewController;
#end
Or you can search the responder chain at runtime:
UIResponder *next = [view nextResponder];
while (next)
{
if ([next isKindOfClass:[ViewController class]])
{
break;
}
next = [next nextResponder];
}
And now "next" will contain the view controller (or nil if it can't be found).
Try using the same navigationController to push view, this keeps the same stack of ViewControllers.
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
[mv release];
I see your problem now! You need to #import your FirstViewController, then #class it. Then do your push.
So:
//.h
#import "FirstViewContoller.h"
#class FirstViewController;
#interface...
//.m
-(void)return {
FirstViewController *firstview = [[FirstViewController alloc]init(withnibname:)];
[firstView.navigationController pushViewController: firstView.navigationController.topViewController animated: TRUE];
}
If I am not wrong, your UIView though is in separate files, is still added to the screen from a UIViewController class.
Simply, post a notification from UIView to your FirstViewController class where you have access to the navigation controller. Then push the SecondViewController from there.
You Can use this. It Works very well for me:-
Firstly Create Object of AppDelegate in UIView Class and initialize it. Then create Navigationcontroller object in Appdelegate.h :-
#property(strong,nonatomic) UINavigationController *navControl;
In your UIView Class implement this code where you want to push :-
ViewController *objview = [[ViewController alloc]init]; [appDelegate.navControl pushViewController:objview animated:YES];