I have UITabController with labels and buttons inside. I need to pass textView value from one tab to another's label. Using segues.
Simply I need to do like this code:
In TAB1:
textView1 = #"test";
set Tab2.label1 = textView1;
Thanks,
David.
I am setting the title field of a UIViewController via Interface Builder/Storyboard:
This view controller is nested in a UINavigationController which in turn is nested within a UITabBarController. When I run the app, I my navigation item has no title, neither does the tab bar item.
If I explicitly set the view controller's navigation item's title, and also it's tab bar item's title in interface builder, then it works just fine.
I am wondering:
a)If I am not using Storyboard but just regular xibs, setting the title of a view controller implicitly sets the navigation items' title as well as the tab bar item's title. But it's not the same storyboard. Is this the intended behaviour?
b) What is then the purpose of the view controller's title (in Storyboard)? it seems to have no effect.
Thanks!
You can set the title of the UINavigationBar in Storyboard by double clicking the actual navigationBar and typing in a title right there. This only sets the title for the UINavigationBar.
Setting the title in code offers some different possibilities.
self.title = #"Your title"; will set the title of a navigationBar and also cause the title to cascade down to a UITabBarItem, if present.
self.navigationItem.title = #"Your title"; will only set the title of the navigationBar, assuming a UINavigationController is present, and NOT affect a UITabBarItem.
self.navigationController.title = #"Your title"; will set the title of a UITabBarItem but NOT the UINavigationBar.
Step 1
If you're looking at a Xib in Xcode's Interface Builder, take a look in the "Document Outline" panel (second panel from the left). Expand the view controller you're working with until you find an icon labelled: Navigation Item.
Step 2
If you then highlight the Navigation Item and open up the Utilities panel (the farthest on the right), and click the Attributes Inspector, you'll see where you can set the title of the view controller. This is the way to do it in Interface Builder, rather than doing it through code.
I ran into this issue this morning. Here are the stabs I took and the final workaround.
This correctly logs the child view controller's title as set in the storyboard, but has no effect on what's being presented:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Title: %#", self.title);
}
This has no effect; the title still doesn't show (probably doing an "if (![_title isEqualToString:title]){}" user the hood:
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = [self.title copy];
}
This causes the title to be set correctly:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *title = self.title;
self.title = nil;
self.title = title;
}
My guess is that the UINavigationController is pulling the title for the view being presented before it has been loaded from the storyboard, but then doesn't start listening for changes until after the property has been set. I don't use storyboards or nibs very often, however, so it's quite possible there's a magic checkbox for this hidden somewhere that I've missed.
In any case, it looks like you can either do the self.navigationItem.title = self.title dance, or the above, as a workaround and still maintain your titles in IB.
Apples docs for this are kinda clear:
The navigation controller updates the middle of the navigation bar as
follows:
If the new top-level view controller has a custom title view, the navigation bar displays that view in place of the default title view.
To specify a custom title view, set the titleView property of the view
controller’s navigation item.
If no custom title view is set, the navigation bar displays a label containing the view controller’s default title. The string for this
label is usually obtained from the title property of the view
controller itself. If you want to display a different title than the
one associated with the view controller, set the title property of the
view controller’s navigation item instead.
Emphasis mine.
I just ran into the same problem. I don't understand why it's not working... It might be on purpose or just be a bug.
To change the title in interface builder, you can click on the navigation item directly and change the title there:
Everything else on this page failed. For now, this worked, in code, in viewDidLoad:
NSString* text = #"My page title";
UIFont* font = [UIFont systemFontOfSize:20.0];
const CGSize SIZE = [text sizeWithAttributes:#{NSFontAttributeName:font}];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, SIZE.width, SIZE.height)];
label.text = text;
label.textColor = UIColor.blackColor;
self.navigationItem.titleView = label;
If you have UINavigationItem present, then you must use the navigation item title in the storyboard. If you don't have a navigation item for a view controller, then the UINavigationController will use the view controller's title property.
Example :
In your storyboard, if you have a navigation item the navigation controller doesn't need to read the view controller's title. Even if the title field is empty for this navigation item.
Remove the navigation item (if you can, you won't be able to do it for the root view controller but you will for the others) and your title will be correctly loaded
I think it works as designed although we expect another behaviour. If you print the title property in - (void)viewDidLoad it will be the same value that you set in story board so I see no reason of this not working unless Apple's choice.
a) If I am not using Storyboard but just regular xibs, setting the title of a view controller implicitly sets the navigation items' title as well as the tab bar item's title. But it's not the same storyboard. Is this the intended behavior?
I believe this is the intended behavior. I think that the purpose of the title attribute of a view controller is more of a property that can be used at the developer's discretion perhaps for distinguishing between controllers.
Another reason for this change I think is that your navigation item's title may need to be different than the tab bar title, since the tab bar title cannot be nearly as long as the navigation title.
b) What is then the purpose of the view controller's title (in Storyboard)? it seems to have no effect.
I think I mentioned this in my first paragraph. I think that the title attribute of a controller is a property that the developer can use perhaps for distinguishing between controllers.
I tried all of the above methods, even tried manually adding a navigation bar but to no avail.
So this is what worked for me.
Remove any navigation bar item you manually added to the view controller and add this to your viewDidLoad method
self.navigationController.navigationBar.topItem.title = #"My Title";
or
self.navigationController.topViewController.title = #"My Title";
In my case I solve with this:
[self.tabBarController.navigationItem setTitle:#"My Title"];
I have an app with two view controllers. ViewControllerA is a blank view with a tap gesture assigned which allows the user to tab on the view and create a UITextView at the point of the tap. The user can create as many UITextViews as they wish and they are added then programmatically to the view (ViewControllerA) as sub views.
There is also a button which allows the user to change the text font and styling. This triggers a Segue to the second view controller ViewControllerB which then allows the user to set Font, Text Size, Color etc. Once completed the user clicks the DONE button on ViewControllerB and another Segue switches back to the initial view (ViewControllerA).
This all works fine. Except when the user switches back to the initial view (ViewControllerA) from ViewControllerB the view is reloaded from the storyboard and the sub views I have added programmatically are gone.
In view (ViewControllerA) ViewDidLoad and ViewWillAppear are firing just fine so the problem seems to be the initial view is released when the first Segue fires and then recreated from the storyboard on the transition back but the subviews are of course not included as they are not in the storyboard since I added them programmatically.
Any suggestions for a best practice on how to solve this so that the subviews are recreated also when the main view (ViewControllerA) reloads?
Many thanks for any suggestions!
From the question it sounds like you had a segue to the text styles view, then another segue "back to the original" - it doesn't work like that, segues always make new instances of the destination VC. You should have had a modal segue to the text styles view, then dismissed the modal view controller - this would return to your original instance.
Just for the record, I solved this as follows in case anyone else needs a solution.
I created a subview in ViewControllerA which is the size of the main view excluding the Toolbar. I call this canvasView. Then I add all of my ImageViews and TextViews to this canvas view.
Then in ViewControllerA viewWillDisappear I archive the canvasView and all of its subviews to a file like this.
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"Canvas.archive"];
BOOL result = [NSKeyedArchiver archiveRootObject:_canvasView
toFile:archivePath];
if (!result) {
NSLog(#"Archive failed to archivePath %#",archivePath);
}
Then in ViewControllerA viewWillAppear I check if there is an existing archive and if so reload it which loads the sub views in the correct order. Otherwise I create an empty canvasView like this.
// If the collageView already exists then restore it from the achive, otherwise initialize a new one.
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"Canvas.archive"];
_canvasView = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
if (_canvasView) {
// Restore existing canvasView
[_backgroundView addSubview:_canvasView];
} else {
// Initialize a new canvasView
_canvasView = [[UIScrollView alloc] initWithFrame:CGRectMake(_backgroundView.frame.origin.x,
_backgroundView.frame.origin.y,
_backgroundView.frame.size.width,
_backgroundView.frame.size.height)];
[_backgroundView addSubview:_canvasView];
}
I want to add total 5 button at bottom of screen but only four will be visible at first time loading of nib.
and if user press first button it will be disappear with animation and second button will come at place of first . and now in screen one more button (button 5 ) at last.
to make it more clear i am adding image.
screen 1. when nib loaded first time.
screen 2. when button 1 pressed.
screen 3. when button 2 pressed.
AS U HAVENT POSTED ANY CODE THAT U'VE TRIED.
So Here is some idea I can suggest to u.
If u want to disappear the button when pressed then, instead of removing it from the view u can keep it there but only make it invisible , may be by setting properties of "visual appearance of view"(look for UIView class reference) eg. alpha value,hidden property.
Once u invisible it, then make it visible after some delay eg.1/2 second.
Once button is visible then CHANGE the label text.
In case ur, u'll need to set UILabel text of all four button; by incrementing label-text int value by 1.
How about something like this? It's not perfect so you'll have to play with it but it should get you started in the right direction...
in your .h
IBOutlet UIButton *firstButton, *secondButton, *thirdButton, *fourthButton
NSArray *buttonsArray;
in your .m
-(void)viewDidLoad{
// VDL stuff
buttonsArray = [NSArray arrayWithObjects:#"One", #"Two", #"Three", #"Four", #"Five", #"Six", nil];
[firstButton setTitle:[buttonsArray objectAtIndex:0]];
[firstButton setTag:0];
// initial setup of the other three buttons works the same way
}
-(IBAction)updateButtons:(id)sender{
UIButton *btn = (UIButton*)sender;
int index = btn.tag;
for(int i = 0; i <4; i++){
if([buttonsArray count] > index+i){
switch(i){
case 0:;
[firstButton setTitle:[buttonsArray objectAtIndex:i+index]];
[firstButton setTag:i+index];
break;
case 1:; //secondButton
break;
case 2:; //thirdButton
break;
case 3:; //fourthButton
break;
}
}else{
break;
}
}
}
Then all you need to do is connect the four on-screen buttons to the action and in the else you'll need some logic (pretty much the same as the switch-case above) to hide ones once you get towards the end of the array if that's what you want to do.
I am making an app for iPad with different views. Till now I have added 2 views. First view is the home screen which has a single button and some images. Pressing button on first view navigates to the second view. Second view has 6 buttons. Now what I want to do is when I press any button on second view, it navigates to the third view. Each button on second view has to show different data. I don't want 6 different views, instead I want a single third view but it should show only that particular data respective to the button pressed on second view.
How can it be done?? Please help me with the code..
Any help will be highly appreciated..
You just need a variable in the third view that you set before showing it. I would set a different tag value for each of my buttons and have them all call a single method. In that method, check the tag value of the sender and setup the third view accordingly. Then show it.
In the third view's viewDidLoad method you can handle displaying or setting up the new data you assigned to it.
For example, if you were setting some custom text in the third view you would have this for your button method in the second view:
- (IBAction)buttonTap:(id)sender {
UIButton *tappedButton = (UIButton *)sender;
MyThirdViewController *thirdVC = [[MyThirdViewController alloc] initWithNib:#"MyThirdViewController" bundle:nil];
switch (tappedButton.tag) {
case 1:
thirdVC.customText = #"Something for button 1";
break;
case 2:
thirdVC.customText = #"Something for button 2";
break;
case 3:
thirdVC.customText = #"Something for button 3";
break;
}
[self.navigationController pushViewController: thirdVC];
[thirdVC release];
}
In the third ViewController:
- (void)viewDidLoad {
self.myTextView.text = self.customText;
}