I want to use standard tab bar item with custom title. I change title after TabBarItem creating directly self.tabBarItem.title = #"Liked". For example "Favorites" - UITabBarSystemItemFavorites:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Liked", #"Liked");
self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:0];
self.tabBarItem.title = #"Liked";
}
return self;
}
Can I do this? If yes, where I made mistake?
UPD: Changing tab bar item title in the viewDidLoad() works on iOS4 but doesn't work on iOS5. Does exist another approach?
Thanks
You should do that in the viewDidLoad and not in the init.
As per Swift5.1 and Xcode the title and image of the system tab bar items cannot be changed. They are defined as enum in obj c as follow. This is the list:
typedef enum UITabBarSystemItem : NSInteger {
case more, favorites, featured, topRated, recents, contacts, history, bookmarks, search, downloads ,mostRecent, mostViewed
} UITabBarSystemItem;
This has a reason. Some icons are immediately recognisable across the whole iOS ecosystem and mean the same thing to everyone, therefore it is not possible to use them differently.
In this way Apple creates a better user experience.
You cannot use the Apple icon and use a different title. You could use a custom icon and custom title instead or in the Storyboards select an SF Symbol like this:
Related
My project is in Xcode 5.0.2 and since I've upgraded to OS X 10.10 I can't use Xcode 5.0.2 now and I need to use Xcode 6 but my problem is my tabbar items in xib file only shows when they're selected(Once selected the image with load and will not hide when unselected).here's the screenshot of it on first load.
Note: I'm using an old UITabBarController usign xib
The solution is only [self setNeedsToDisplay] :D My layout is not updating. Thanks for the help guys :D
In ViewController of every tab add the below code with there respective title and image.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.tabBarItem.title = #"Dashboard";
self.tabBarItem.image = [[UIImage imageNamed:#"dashBoard"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
self.tabBarItem.selectedImage=[[UIImage imageNamed:#"dashBoardSelect"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
return self;
}
So I have an application with different buttons, labels and some Text Views in storyboard where I entered the text directly in the storyboard. I enabled base localization and added a couple of languages.
This generated storyboards for Base (English) and the other languages with a list of items objectIDs.
I translated everything, and the labels and buttons (ALL OF THEM) work and show in the language I set the device to.
The text fields however keep showing the initial English text no matter which language I set...
Are there any extra steps involved for Text View?
So, I did some research, and it seems that in order for this to work correctly, the text for the UITextView needs to be set programmatically.
Source: Devforums.apple
Quote:
as I understand it, strings such as the text property of a text view/field have to be set in code using NSLocalizedString. The first 1/2 hour of WWDC 2013 video session #219 Making Your App World Ready covers this if you have the time to watch it
So, it seems that the workaround (if you don't want to set the text programmatically) is to convert the strings file into a storyboard before shipping the app. This does seem to work as intended and shows the UITextView properly localized.
EDIT: Found another workaround that allows to keep .strings file.
In - (void)viewDidLoad:
for(UIView* v in self.view.subviews)
{
if([v isKindOfClass:[UITextView class]])
{
UITextView* txv = (UITextView*)v;
NSString *loctxt = [txv.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
txv.text = NSLocalizedString(loctxt, #"");
}
}
This produces a Percent Escapes encoded string from whatever is inside the storyboard, like this:
Hello%20World
In your Localizable.strings file, you use the above as the key, and this will produce the localized text in the app at runtime for the selected locale, like this:
"Hello%20World" = "Hallo Welt";
The Percent escaping takes care of all escape characters in the base string.
As my comment on Dmitry's answer cannot be formatted nicely, I repeat this as an answer here. The Swift version of his solution looks like this:
override func viewDidLoad() {
super.viewDidLoad()
for view in self.view.subviews {
if let tv = view as? UITextView, ident = view.restorationIdentifier {
tv.text = NSLocalizedString("\(ident).text", tableName: "Main", comment: "")
}
}
// Do any additional setup after loading the view.
}
(Note that in Swift, NSLocalizedString replaces several Objective-C macros, one of them being NSLocalizedStringFromTable)
P.S.: Unfortunately, in iOS 10 this seems not to work any more. Instead, the call gives back the id that was supplied as first parameter (e.g. "abc-xy-pqr.text"). Any ideas?
If anyone is still interested, I have solved this problem a different way, this will allow you to still use the SAME .Strings file that is generated by Xcode for storyboards.
There are two parts to this solution:
In the .m file for your view add this code:
- (void)viewDidLoad
{
[super viewDidLoad];
for(UIView* view in self.view.subviews)
{
if([view isKindOfClass:[UITextView class]] && view.restorationIdentifier)
{
UITextView* textView = (UITextView*)view;
NSString *textViewName = [NSString stringWithFormat:#"%#.text",textView.restorationIdentifier];
textView.text = NSLocalizedStringFromTable(textViewName, #"Main", nil);
//change this to be the same as the name of your storyboard ^^^
}
}
// Do any additional setup after loading the view.
}
and in your storyboard in the identity inspector copy the "Object ID" to the "Restoration ID" field.
This will apply the new localized text to all of your UITextViews on screen load and will allow you to use the already generated strings files.
I made my own Categories for the components.
For example, a button:
#import <UIKit/UIKit.h>
#interface LocalizedButton : UIButton
#end
#import "LocalizedButton.h"
#implementation LocalizedButton
- (id)initWithCoder:(NSCoder *)aDecoder {
NSLog(#"Loading LocalizedButton: initWithCoder");
if ((self = [super initWithCoder:aDecoder])){
[self localizeButton];
}
return self;
}
- (id)initWithFrame:(CGRect)frame{
NSLog(#"Loading LocalizedButton: initWithFrame");
self = [super initWithFrame:frame];
if (self) {
[self localizeButton];
}
return self;
}
-(void) localizeButton{
self.titleLabel.adjustsFontSizeToFitWidth = YES;
NSString* text = NSLocalizedString(self.titleLabel.text, nil);
[self setTitle:text forState:UIControlStateNormal];
[self setTitle:text forState:UIControlStateHighlighted];
[self setTitle:text forState:UIControlStateDisabled];
[self setTitle:text forState:UIControlStateSelected];
}
#end
You can se the complete code on: https://github.com/exmo/equizmo-ios/blob/master/Quiz/LocalizedButton.m
The Swift solution of https://stackoverflow.com/users/1950945/stefan works for me on iOS 10.2 when I replace the "Main" with the correct id (e.g. "MainStoryboard") which references the localized file id.storyboard (e.g. "MainStoryboard.storyboard")
This is both a question, and a solution.
I recently added a very simple UIViewController with a .xib to my iPad application, containing just a UIDatePicker and a UILabel, which I wish to display as a popup in my iPad app.
I added all of the relevant code to display this .xib as a popup. There were no errors or warnings, my UIViewController class was set as the "Class" for this .xib, and both controls showed that they were linked to the IBOutlets in this particular file.
But, when I ran the app, the popup would appear perfectly well, but if I tried to access anything to do with these two controls, nothing would happen.
So, for example, the following code attempted to set the label's text, to change the UIDatePicker's mode... and nothing would happen. I tried breakpoints, the code WAS being run, the controls did have a value (they weren't nil) but this code wouldn't do anything. The UILabel's text wouldn't be changed, the DatePicker would continue to be in "Date & Time" mode, etc.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
[self.datePicker addTarget:self action:#selector(LabelChange:) forControlEvents:UIControlEventValueChanged];
self.lblQuestion.text = #"Is this working...?";
self.datePicker.datePickerMode = UIDatePickerModeDate;
self.datePicker.date = [NSDate date];
}
return self;
}
Eventually - eventually - I added one line of code, to set the "contentSizeForViewInPopover":
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Without this line of code, the code-behind doesn't communicate
// with the controls in this .xib
self.contentSizeForViewInPopover = self.view.bounds.size;
// ... etc ...
...and suddenly, it worked beautifully.
So, my question is.. why ?!
What the heck does this one line of code do, which suddenly makes it so I can set my UILabel's text, and can talk to the UIDatePicker control...?
I'm very used to the quirks and crashes with XCode, but I'm baffled by why this suddenly made my code start to work. I'm relieved that this quirk "only" wasted a couple of hours of my life... and would like to understand the reason behind it.
Btw, this is with XCode 4.6.3, running on an iOS 6.1 SDK app for an iPad.
The outlets are connected when the nib is loaded. The nib is loaded when you access the controllers's view for the first time.
In other words, in your initializer all your outlets are nil. However, if you call self.view, your view gets loaded and outlets are connected. contentSizeForViewInPopover or bounds.size is irrelevant.
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.view; //this is enough
...
This is why you shouldn't put such code into initializer but into viewDidLoad instead.
- (void)viewDidLoad {
[self.datePicker addTarget:self
action:#selector(LabelChange:)
forControlEvents:UIControlEventValueChanged];
self.lblQuestion.text = #"Is this working...?";
self.datePicker.datePickerMode = UIDatePickerModeDate;
self.datePicker.date = [NSDate date];
}
I have 2 view controllers in a tab bar controller. My 2nd Nav Controller wants to set a badge value.
This controller is not loaded when the app starts, so the badge does not show. If I go over to that tab, the badge is properly updated.
this snippet runs when the tab's View Controller loads/reloads/updates/etc...
[self.navigationController.tabBarItem setBadgeValue:[NSString stringWithFormat:#"%u",[self.photos count]]];
Is the correct way to do this: Override the Nav Controller with a custom class and put the badge value in at that level? It seems like that is where I should put this info, but I haven't found a definite answer.
When the TabBarController is loaded, all of it's contained initial viewControllers are initialised. But their views are not loaded until you navigate to the respective tab item. So you can't execute code at this point in any of the view-loading methods (viewDidLoad etc). However you can execute code by overriding one of the initialisation methods.
If using storyboards the process of unarchiving the viewController triggers this method when the NIB has loaded:
- (void) awakeFromNib
{
}
If not using Storyboards, this initialiser is called prior to NIB loading:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
In either case you can override these methods to execute some code...
- (void) awakeFromNib
[super awakeFromNib];
[self.navigationController.tabBarItem
setBadgeValue:[NSString stringWithFormat:#"badgeValue"]]];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self.navigationController.tabBarItem
setBadgeValue:[NSString stringWithFormat:#"badgeValue"]]];
}
return self;
}
However you will need to take care where you are getting your data from. At this point self.photos may be uninitialised for example. If the data for this is coming out of userdefaults, you should be able to read those in here and set your badge accordingly.
I am a new to iOS development, and I recently came across QuickDialog. From what it seems, it creates the dialog page for you automatically.
My recent learning has taught me to use the Storyboard to create the views. I was wondering, would QuickDialog integrate with Storyboard? So say I had a login form made by quick dialog, would the login view appear on the storyboard?
Thanks!
Your link seems broken. But I guess you are talking about this library?
Well, storyboard doesn't change much of the development environment. It just handles some transition between view controllers for you. So, yes, you can use QuickDialog with storyboard.
But it will not just appear in your storyboard. You need to add view controllers implemented with QuickDialog in it by yourself.
You have to create the QRootElement when storyboard is creating the controller in initWithCoder, and if you want to use the grouped option, it has to be set there, for the rest of the options, you can set them in the viewload, apart from that it's as usual:
Create a new class inheriting from QuickDialogController
Add in your class implementation the following code:
-(id) initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
QRootElement *_root = [[QRootElement alloc] init];
_root.grouped = YES;
/* Put your init code here or in viewDidLoad */
self.root = _root;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
QSection *section = [[QSection alloc] init];
QLabelElement *label = [[QLabelElement alloc] initWithTitle:#"Hello" Value:#"world!"];
[section addElement:label];
self.root.title = #"Hello World";
[self.root addSection:section];
}
Set the custom class of your storyboard UIViewController to be the one you just created