UIAppearance Swift 4 - ios

After updating to Swift 4, I am getting a compiler error:
Static member 'appearance' cannot be used on protocol metatype 'UIAppearance.Protocol'
Here is my viewWillAppear method in my custom Tab Bar Controller subclass, I am setting the font of the item text.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// compiler error on line below
UIAppearance.appearance().setTitleTextAttributes([NSAttributedStringKey.font: font], for: UIControlState.normal)
}
I'm having trouble fixing this, any guidance would be appreciated, thanks!

Right - the current Swift 4 conversion tool (as of Xcode 9 Beta 4) gets a little carried away.
I was able to fix the problem quickly by reverting the UIAppearance conversion code, then updating the individual attributes.
For example, in Swift 3 I had:
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.white], for: .selected)
Xcode "helped" me out by changing it to:
UIAppearance.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.white], for: .selected)
I was able to quiet the errors by half-reverting, to:
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.white], for: .selected)

Related

How to Customize SwiftUI SegmentedPicker

I am using the Picker in SwiftUI with the style of SegmentedPicker.
I am trying to change the colors of the picker and found this code in stackoverflow.
How to change selected segment color in SwiftUI Segmented Picker
init() {
UISegmentedControl.appearance().selectedSegmentTintColor? = .blue
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.blue], for: .normal)
}
But an error pops up saying "Return from initializer without initializing all stored properties"
What can I do to make the error diappear :(
If you provide a own init() method, you have to initialize all your your properties. As almost every property got a default value, you should only have to initialize the Binding to make your code work...
init(showLoginView: Binding<Bool>) {
self._showLoginView = showLoginView //<< here init your stored properties
UISegmentedControl.appearance().selectedSegmentTintColor? = .blue
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.blue], for: .normal)
}
If you're going to call this in the init within LoginSheetView, you also need to set up all of the other variables within the init function.
When you set the UISegmentedControl.appearance(), it is setting the appearance globally across you app for all UISegmentedControls. Since it therefore doesn't need to be called within LoginSheetView, the easy solution would be to move this init to one of your initial views that doesn't have other init variables, such as the ___App.swift file where you #main is called.

UIButton Title Label Text Not Changing Using Storyboard or Programmatically

Xcode 12.0.1
I am trying to remove the title label text on a UIButton using the storyboard. I then plan on setting it programmatically. When removing the text via the storyboard, the preview shows the text removed. However, the text remains when I build and run the application.
Changing programmatically is not working either. I try to change in in the controllers viewDidLoad()
punchBtn.setTitle("Transfer", for: .normal)
punchBtn.setTitle("Transfer", for: .application)
punchBtn.setTitle("Transfer", for: .selected)
punchBtn.setTitle("Transfer", for: .reserved)
punchBtn.setTitle("Transfer", for: .highlighted)
punchBtn.setTitle("Transfer", for: .disabled)
punchBtn.setTitle("Transfer", for: .focused)
The interesting thing is the text is changing when the button is selected:
Any advice would be greatly appreciated.
In the file Main.strings you will find this word "punch".
change it from there or else take a new button.
This does sound like a cache issue, because nowhere in the app does it say "Punch" anymore.
Command-Shift-K to clean the project hopefully fixes that.
If that doesn't work, then search the entire workspace for instances where you used the word "punch".
Try this!!!
override func viewWillAppear(_ animated: Bool) {
// other code
// end of method
// Change the text of your button
}

Change UI based on System Language - Swift

I have an app and I want to support 2 languages. English and Greek.
I have already localised the whole app and everything works perfect except the UI.
I want to change images based on the system language user has. It works fine on simulator but when I use my real device the app changes its language except the images.
This is my code for the change.
let language = NSLocale.current.identifier
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
func setupUI() {
if language == "el_US" {
print(language)
scanBtn.setBackgroundImage(UIImage(named: "scanBtnGr"), for: .normal)
detoxBtn.setBackgroundImage(UIImage(named: "detoxGr"), for: .normal)
bioBtn.setBackgroundImage(UIImage(named: "bioBtn"), for: .normal)
searchBtn.setBackgroundImage(UIImage(named: "browseGr"), for: .normal)
captureBtn.setBackgroundImage(UIImage(named: "scanGr"), for: .normal)
uploadBtn.setBackgroundImage(UIImage(named: "uploadGr"), for: .normal)
}else{
print(language)
scanBtn.setBackgroundImage(UIImage(named: "scanBtn"), for: .normal)
detoxBtn.setBackgroundImage(UIImage(named: "detoxBtn"), for: .normal)
bioBtn.setBackgroundImage(UIImage(named: "bioBtn"), for: .normal)
searchBtn.setBackgroundImage(UIImage(named: "browseBtn"), for: .normal)
captureBtn.setBackgroundImage(UIImage(named: "scan"), for: .normal)
uploadBtn.setBackgroundImage(UIImage(named: "upload"), for: .normal)
}
}
I really don't know where is the problem because on the Simulator works perfect.
Changing the way you set those images as below can help.
scanBtn.setBackgroundImage(UIImage(named: NSLocalizedString(key: "scanBtnGr", comment: ""), for: .normal)
In this way, you won't have to worry about the target language code as well. You can remove if statement and define corresponding names in Localizable.strings file.
Besides, if you change the language of your app without terminating the app and changing the device language, please make sure that setupUI() function gets invoked one more time after the language switch. viewWillAppear may be a suitable place for it.

Change title text color of a specific segment in UISegmentedControl?

How can I change the text color of just one specific segment of a UISegmentedControl? I want to keep them all normal, except for a specific segment which should be a different color, whether it is selected or not.
#IBDesignable
class DesignableSegmentControl: UISegmentedControl{
}
extension UISegmentedControl{
#IBInspectable
var textColor: UIColor{
get {
return self.textColor
}
set {
let unselectedAttributes = [NSAttributedString.Key.foregroundColor: newValue,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: UIFont.Weight.regular)]
self.setTitleTextAttributes(unselectedAttributes, for: .normal)
self.setTitleTextAttributes(unselectedAttributes, for: .selected)
}
}
}
Just change you segment control's class name as shown below:
[change class name]:
[change text color]:
for swift 5:
yourSegment.setTitleTextAttributes( [NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
Updated Swift 4.1
UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.red], for: .selected)
Swift 3.1
UISegmentedControl.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red as Any], for: .selected)
For Earlier Swift Version:
UISegmentedControl.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red], for: .selected)
There isn't any built-in way; as you've probably figured out, setTitleTextAttributes applies to all the segments. You would have to draw your text as an image and use that instead.
Just add this line of code:
UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: .selected)
You can implement your own segmented control for customisation.
Add two buttons with same UI as segmented control.
Round the corners.
On click make the background colour according to your need and clear back ground of other and make it unselected.
In this way there is large scope for customisation.
Also there are many custom segmented control are available at GitHub.
You can try this
https://github.com/gmarm/BetterSegmentedControl

Changing text of UIButton programmatically swift

Simple question here. I have a UIButton, currencySelector, and I want to programmatically change the text. Here's what I have:
currencySelector.text = "foobar"
Xcode gives me the error "Expected Declaration". What am I doing wrong, and how can I make the button's text change?
In Swift 3, 4, 5:
button.setTitle("Button Title", for: .normal)
Otherwise:
button.setTitle("Button Title", forState: UIControlState.Normal)
Also an #IBOutlet has to declared for the button.
Just a clarification for those new to Swift and iOS programming. Below line of code:
button.setTitle("myTitle", forState: UIControlState.Normal)
only applies to IBOutlets, not IBActions.
So, if your app is using a button as a function to execute some code, say playing music, and you want to change the title from Play to Pause based on a toggle variable, you need to also create an IBOutlet for that button.
If you try to use button.setTitle against an IBAction you will get an error. Its obvious once you know it, but for the noobs (we all were) this is a helpful tip.
Swift 5.0
// Standard State
myButton.setTitle("Title", for: .normal)
Swift 5:
let controlStates: Array<UIControl.State> = [.normal, .highlighted, .disabled, .selected, .focused, .application, .reserved]
for controlState in controlStates {
button.setTitle(NSLocalizedString("Title", comment: ""), for: controlState)
}
Swift 3:
Set button title:
//for normal state:
my_btn.setTitle("Button Title", for: .normal)
// For highlighted state:
my_btn.setTitle("Button Title2", for: .highlighted)
Changing title when attributed is a bit different :
I just ran into a problem : If you have an UIButton with an Attributed Title, you have to use :
my_btn.setAttributedTitle(NSAttributedString(string: my_title), for: my_state)
as, per Apple SetTitle Doc :
If you set both a title and an attributed title for the button, the button prefers the use of the attributed title over this one.
I had an attributed title and I tried to setTitle on it, with no effect...
Swift 3
When you make the #IBAction:
#IBAction func btnAction(_ sender: UIButton) {
sender.setTitle("string goes here", for: .normal)
}
This sets the sender as UIButton (instead of Any) so it targets the btnAction as a UIButton
As of 12/12/2021 - Swift version 5.5.1^ assuming you already have an IBOutlet linked to yourButton in a normal state.
yourButton.setTitle("Title of your button", for: .normal)
swift 4.2 and above
using button's IBOutlet
btnOutlet.setTitle("New Title", for: .normal)
using button's IBAction
#IBAction func btnAction(_ sender: UIButton) {
sender.setTitle("New Title", for: .normal)
}
Swift 3
let button: UIButton = UIButton()
button.frame = CGRect.init(x: view.frame.width/2, y: view.frame.height/2, width: 100, height: 100)
button.setTitle(“Title Button”, for: .normal)
To set a title for a button in Xcode using swift - 04:
first create a method called setTitle with parameter title and UIController state like below ;
func setTitle(_ title : String?, for state : UIControl.State) {
}
and recall this method in your button action method
like ;
yourButtonName.setTitle("String", for: .state)

Resources