When we click on the wrong option in the quiz application, the background color is red and the background color of the correct option is green. how can I do that? My model :
struct QuizModel {
let q : String
let a : [String]
let correctAnswer : Int
}
my question :
QuizModel(q: "Aşağıdakilerden hangisi ilk yardımın amaçlarından biri değildir?", a: [
"A) İlaçla tedavi etmek","B) Durumun kötüleşmesini önlemek","C) Hayati tehlikeyi ortadan kaldırmak","D) Yaşamsal fonksiyonların sürdürülmesini sağlamak"], correctAnswer: 0)
answer func :
func checkAnswer(userAnswer : Int)-> Bool {
if userAnswer == quiz[questionNumber ].correctAnswer {
return true
}else{
return false
}
}
user tapped option button :
#objc func TappedButton(_ sender : UIButton){
let userAnswer = sender.tag
let userRightGot = quizBrains.checkAnswer(userAnswer: userAnswer)
if userRightGot {
sender.backgroundColor = .green
score += 1
scoreLabel.text = "\(score)"
}else{
sender.backgroundColor = .red
failScore += 1
failScoreLabel.text = "\(failScore)"
}
The method affects only the currently tapped button, you have to update the state of the other buttons, too.
Something like this, button0-button3 are the references to the buttons, you have to add IBOutlets if there are none.
var buttons = [button0, button1, button2, button3]
// please name methods with starting lowercase letter
#objc func tappedButton(_ sender : UIButton) {
let userAnswer = sender.tag
let correctAnswer = quiz[questionNumber].correctAnswer
for button in buttons {
button.backgroundColor = button.tag == correctAnswer ? .green : .red
}
if userAnswer == correctAnswer {
score += 1
scoreLabel.text = "\(score)"
} else {
failScore += 1
failScoreLabel.text = "\(failScore)"
}
}
My vc contains:
-1 name textView
-1 label // for flavors
-2 radio buttons // yes and no
-1 nextButton
What I want to do is keep the nextButton disabled until the textView is filled out, the label's text value is changed from its initial title of "Pick a Flavor" to whatever flavor they pick, and 1 of the radio buttons are selected.
I know using a textView's textViewDidEndEditing() I can listen to changes on it after the user finishes editing disable or enable the nextButton.
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
How would I additionally disable or enable the nextButton based on wether or not one of the radio buttons were selected and the label's text is changed in addition to checking the nameTextView has text inside of it?
FYI the label's text is initially set with "Pick a Flavor". I have a gesture recognizer hooked up to it and when its tapped a new vc with a tableView is presented. The user picks a flavor, a protocol sends it back to this vc and the label's text will change to whatever flavor was selected (eg the label's title would say "Butter Pecan" if chosen). The nextButton should be disabled as long as the label's title is still set to "Pick a Flavor".
code:
let flavorLabel: UILabel = {
let label = UILabel()
label.text = "Pick a Flavor"
label.isUserInteractionEnabled = true
return label
}()
let nameTextView: UITextView = {
let textView = UITextView()
return textView
}()
let noButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("No", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(noButtonPressed), for: .touchUpInside)
return button
}()
let yesButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("Yes", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(yesButtonPressed), for: .touchUpInside)
return button
}()
let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isEnabled = false
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(nextButtonTapped), for: .touchUpInside)
return button
}()
var choice: Bool?
override func viewDidLoad() {
super.viewDidLoad()
flavorVC.delegate = self
}
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
#objc fileprivate func noButtonPressed() {
choice = false
}
#objc fileprivate func yesButtonPressed() {
choice = true
}
// delegate method from FlavorController
func selectedFlavor(flavor: String) {
flavorLabel.text = flavor // eg. "Butter Pecan"
}
You need to create a function that check all like this
func checkAll() {
nextButto.isEnabled = flavorLabel.text != "Pick a Flavor" &&
nameTextField.text != "" &&
(noButton.someProerty != || yesButton.someProerty != )
}
and call it from textfield and button targets plus
var ob:NSKeyValueObservation?
ob = flavorLabel.observe(\.text,options:[.new], changeHandler: { [unowned self] _, change in
self.checkAll()
}
I left the radio checks because both of them are custom , so you should know what to check , btw you can set tag of selected to 1 inside the target method and check according to it or some other logic you want
I'm trying to complete my favorite button by saving it state even when i quit the view \ App . it will be great if anyone could show me how can i do this, I'm using Xcode 8 and coding with Swift 3.
Current Button Code :
//create a new button
let Favoritebutton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
Favoritebutton.setImage(UIImage(named: "EmptyHeart.png"), for: .normal)
Favoritebutton.setImage(UIImage(named: "FilledHeart.png"), for: .selected)
//add function for button
Favoritebutton.addTarget(self, action: #selector(self.button), for: .touchUpInside)
//set frame
Favoritebutton.frame = CGRect(x:0,y: 0,width: 35,height: 35)
let barButton = UIBarButtonItem(customView: Favoritebutton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
let state = UserDefaults.standard.bool(forKey: "isSaved") ?? false
}
#IBAction func button(sender: UIButton) {
sender.isSelected = !sender.isSelected
UserDefaults.standard.set(true,forKey: "isSaved")
UserDefaults.standard.synchronize()
if let Favoritebutton = sender as? UIButton {
if Favoritebutton.isSelected {
// set selected
Favoritebutton.isSelected = true
UserDefaults.standard.set(true, forKey: "MY_FAV_KEY")
UserDefaults.standard.synchronize()
// set badge to tabbar item.
let tabItem = self.tabBarController?.tabBar.items![3]
sel_val = tabItem?.badgeValue
if(sel_val == nil){
sel_val = "0"
}
let sel_num = Int(sel_val!)
tabItem!.badgeValue = String(format: "%d", sel_num! + 1) as String
let Fav: NSMutableArray = []
Fav.add(barImage)
Fav.add(barName)
Fav.add(streetName)
favorite.add(Fav)
} else {
// set deselected
Favoritebutton.isSelected = false
UserDefaults.standard.set(true, forKey: "MY_FAV_KEY")
UserDefaults.standard.synchronize()
let tabItem = self.tabBarController?.tabBar.items![3]
sel_val = tabItem?.badgeValue
if(sel_val == nil){
sel_val = "0"
}
let sel_num = Int(sel_val!)
tabItem!.badgeValue = String(format: "%d", sel_num! - 1) as String
let Fav: NSMutableArray = []
Fav.add(barImage)
Fav.add(barName)
Fav.add(streetName)
favorite.remove(Fav)
}
}
As i said,It will be great if anyone could help me save the button's state
even if i quit the view or app , i would really appreciate it, Thank you in advance !
Saving the value to UserDefaults writes it out to the plist file. It does not read the value back in or restore state when the app resumes. You are responsible for that. So somewhere in viewDidLoad check the state:
let state = UserDefaults.standard.bool(forKey: "isSaved") ?? false
Then set your button accordingly
I have a button which I want to change background color and text when tapped(select) and bring it back to its original state when tapped again (deselect). I am able to select it but I am not being able to deselect it. I have researched on SO and I am getting errors in this code in the if-else part
#IBAction func btn1Pressed(_ sender: AnyObject) {
sender.setTitleColor(UIColor.blue, for: UIControlState.normal)
(sender as! UIButton).backgroundColor = UIColor.green
if sender.isSelected {
sender.selected = false
}
else {
sender.selected = true
}
}
Try this:
#IBAction func btnPressed(_ sender: AnyObject) {
guard let button = sender as? UIButton else { return }
if !button.isSelected {
button.isSelected = true
button.setTitleColor(UIColor.blue, for: UIControl.State.normal)
button.backgroundColor = UIColor.green
}
else {
button.isSelected = false
button.setTitleColor(UIColor.green, for: UIControl.State.normal)
button.backgroundColor = UIColor.blue
}
}
It sounds to me like UISwitch is what you're looking for. Give it a try instead of wasting time implementing something that's already there for you.
try this
#IBAction func btn1Pressed(sender: UIButton) {
if sender.selected {
sender.selected = false
sender.setTitleColor(UIColor.redColor(), forState: .Normal)
sender.backgroundColor = UIColor.blackColor()
}
else {
sender.selected = true
sender.setTitleColor(UIColor.redColor(), forState: .Selected)
sender.backgroundColor = UIColor.blackColor()
}
}
Change background color of selected button from storyboard like below in state config choose selected and then change background color and also coustomize default for normal button.
and use below in action
(sender as! UIButton).selected = !(sender as! UIButton).selected
Please try this code first you need to crate action and propert of the button like
#IBOutlet var btn_ButtonPressed: UIButton!
then Action.
#IBAction func click_ButtonPressed(_ sender: Any) {
if !sender.isSelected() {
sender.selected = true
btn_ButtonPressed.setTitleColor(UIColor.red, forState: .normal)
btn_ButtonPressed.backgroundColor = UIColor.yellow
}
else {
sender.selected = false
btn_ButtonPressed.setTitleColor(UIColor.yellow, forState: .normal)
btn_ButtonPressed.backgroundColor = UIColor.red
}
}
this one worked fine for me!
//
#IBAction func buttonColorChanger(sender : UIButton ) {
if button.isSelected == false
{
button.backgroundColor = UIColor.purple
print("selected")
button.setTitle("selected", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isSelected = true
}else{
button.backgroundColor = UIColor.white
print("unselected")
button.isSelected = false
}
}
A cleaner approach would be:
#objc private func buttonTapped(_ sender: UIButton) {
sender.isSelected.toggle()
if selected {
// Setup appearance for selected state.
} else {
// Setup appearance for deselected state.
}
}
I currently have a UITextfield with an eye icon in it that when pressed is supposed to toggle the secure text entry on and off.
I know you can check mark the "secure text entry" box in the attributes inspector but how to do it so it toggles whenever the icon is pressed?
Use this code,
iconClick is bool variable, or you need other condition check it,
var iconClick = true
eye Action method:
#IBAction func iconAction(sender: AnyObject) {
if iconClick {
passwordTF.secureTextEntry = false
} else {
passwordTF.secureTextEntry = true
}
iconClick = !iconClick
}
hope its helpful
An unintended side-effect of this is that if the user toggles to insecure, and then back to secure, the existing text will be cleared if the user continues typing. The cursor may also end up in the wrong position unless we reset the selected text range.
Below is an implementation that handles these cases (Swift 4)
extension UITextField {
func togglePasswordVisibility() {
isSecureTextEntry = !isSecureTextEntry
if let existingText = text, isSecureTextEntry {
/* When toggling to secure text, all text will be purged if the user
continues typing unless we intervene. This is prevented by first
deleting the existing text and then recovering the original text. */
deleteBackward()
if let textRange = textRange(from: beginningOfDocument, to: endOfDocument) {
replace(textRange, withText: existingText)
}
}
/* Reset the selected text range since the cursor can end up in the wrong
position after a toggle because the text might vary in width */
if let existingSelectedTextRange = selectedTextRange {
selectedTextRange = nil
selectedTextRange = existingSelectedTextRange
}
}
}
This snippet is using the replace(_:withText:) function because it triggers the .editingChanged event, which happens to be useful in my application. Just setting text = existingText should be fine as well.
Why to use an extra var. In the action method of the eye button just do as below
password.secureTextEntry = !password.secureTextEntry
UPDATE
Swift 4.2 (as per #ROC comment)
password.isSecureTextEntry.toggle()
I wrote extension for the same. To provide Password toggle.
In your Assets first add images that you want for toggle.
Add following extension for UITextField.
extension UITextField {
fileprivate func setPasswordToggleImage(_ button: UIButton) {
if(isSecureTextEntry){
button.setImage(UIImage(named: "ic_password_visible"), for: .normal)
}else{
button.setImage(UIImage(named: "ic_password_invisible"), for: .normal)
}
}
func enablePasswordToggle(){
let button = UIButton(type: .custom)
setPasswordToggleImage(button)
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0)
button.frame = CGRect(x: CGFloat(self.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
self.rightView = button
self.rightViewMode = .always
}
#IBAction func togglePasswordView(_ sender: Any) {
self.isSecureTextEntry = !self.isSecureTextEntry
setPasswordToggleImage(sender as! UIButton)
}
}
Call extension on your UITextField Outlet
override func viewDidLoad() {
super.viewDidLoad()
txtPassword.enablePasswordToggle()
txtConfirmPassword.enablePasswordToggle()
}
Swift 4 solution
You don't need extra if statement for simple toggle isSecureTextEntry property
func togglePasswordVisibility() {
password.isSecureTextEntry = !password.isSecureTextEntry
}
But there is a problem when you toggle isSecureTextEntry UITextField doesn't recalculate text width and we have extra space to the right of the text. To avoid this you should replace text this way
func togglePasswordVisibility() {
password.isSecureTextEntry = !password.isSecureTextEntry
if let textRange = password.textRange(from: password.beginningOfDocument, to: password.endOfDocument) {
password.replace(textRange, withText: password.text!)
}
}
UPDATE
Swift 4.2
Instead of
password.isSecureTextEntry = !password.isSecureTextEntry
you can do this
password.isSecureTextEntry.toggle()
Use UITextFiled rightView to show toggle button
var rightButton = UIButton(type: .custom)
rightButton.frame = CGRect(x:0, y:0, width:30, height:30)
yourtextfield.rightViewMode = .always
yourtextfield.rightView = rightButton
If you need TextField with similar feature in multiple places its best to subclass the UITextField like follwing example -
import UIKit
class UIShowHideTextField: UITextField {
let rightButton = UIButton(type: .custom)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
required override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
rightButton.setImage(UIImage(named: "password_show") , for: .normal)
rightButton.addTarget(self, action: #selector(toggleShowHide), for: .touchUpInside)
rightButton.frame = CGRect(x:0, y:0, width:30, height:30)
rightViewMode = .always
rightView = rightButton
isSecureTextEntry = true
}
#objc
func toggleShowHide(button: UIButton) {
toggle()
}
func toggle() {
isSecureTextEntry = !isSecureTextEntry
if isSecureTextEntry {
rightButton.setImage(UIImage(named: "password_show") , for: .normal)
} else {
rightButton.setImage(UIImage(named: "password_hide") , for: .normal)
}
}
}
After which you can use it in any ViewController,
class ViewController: UIViewController {
#IBOutlet var textField: UIShowHideTextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
}
}
For Objective c
set image for RightButton In viewdidload Method
[RightButton setImage:[UIImage imageNamed:#"iconEyesOpen"] forState:UIControlStateNormal];
[RightButton setImage:[UIImage imageNamed:#"iconEyesClose"] forState:UIControlStateSelected];
and then set action method for that RightButton
-(IBAction)RightButton:(id)sender
{
if (_rightButton.selected)
{
_rightButton.selected = NO;
_passwordText.secureTextEntry = YES;
if (_passwordText.isFirstResponder) {
[_passwordText resignFirstResponder];
[_passwordText becomeFirstResponder];
}
}
else
{
_rightButton.selected = YES;
_passwordText.secureTextEntry = NO;
if (_passwordText.isFirstResponder) {
[_passwordText resignFirstResponder];
[_passwordText becomeFirstResponder];
}
}
}
Swift 3
// MARK: Btn EyeAction
#IBAction func btnEyeAction(_ sender: Any) {
if(iconClick == true) {
txtPassword.isSecureTextEntry = false
iconClick = false
} else {
txtPassword.isSecureTextEntry = true
iconClick = true
}
}
Shortest!
I think this is the shortest solution for secure entry as well as updating the picture of the button.
#IBAction func toggleSecureEntry(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
textfieldPassword.isSecureTextEntry = !sender.isSelected
}
Assign the show/hide picture of the button according to the state selected /default , no need to create any variable or outlet.
This worked for me on Swift 5.0
#IBAction func changePasswordVisibility(_ sender: UIButton) {
passwordField.isSecureTextEntry.toggle()
if passwordField.isSecureTextEntry {
if let image = UIImage(systemName: "eye.fill") {
sender.setImage(image, for: .normal)
}
} else {
if let image = UIImage(systemName: "eye.slash.fill") {
sender.setImage(image, for: .normal)
}
}
}
Button attributes:
Result:
Swift 3
passwordTF.isSecureTextEntry = true
passwordTF.isSecureTextEntry = false
#IBAction func eye_toggle_clicked(sender: AnyObject)
{
if toggleBtn.tag == 0
{
passwordTxt.secureTextEntry=true
toggleBtn.tag=1
}
else
{
passwordTxt.secureTextEntry=false
toggleBtn.tag=0
}
}
As others have noted, the property is secureTextEntry, but you won't find this in the UITextField documentation, as it is actually inherited by a UITextField through the UITextInputTraits protocol- https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/#//apple_ref/occ/intfp/UITextInputTraits/secureTextEntry
You can simply toggle this value each time your button is tapped:
#IBAction func togglePasswordSecurity(sender: UIButton) {
self.passwordField.secureTextEntry = !self.passwordField.secureTextEntry
}
try this line:
#IBAction func btnClick(sender: AnyObject) {
let btn : UIButton = sender as! UIButton
if btn.tag == 0{
btn.tag = 1
textFieldSecure.secureTextEntry = NO
}
else{
btn.tag = 0
textFieldSecure.secureTextEntry = NO;
}
}
Here is your answer no need to take any bool var:
#IBAction func showHideAction(sender: AnyObject) {
if tfPassword.secureTextEntry{
tfPassword.secureTextEntry = false
}else{
tfPassword.secureTextEntry = true;
}
}
First you need to set image(visible or hide) of button of eye for different state (selected or normal)
than connect IBAction and write code like
#IBAction func btnPasswordVisiblityClicked(_ sender: Any) {
(sender as! UIButton).isSelected = !(sender as! UIButton).isSelected
if (sender as! UIButton).isSelected {
txtfPassword.isSecureTextEntry = false
} else {
txtfPassword.isSecureTextEntry = true
}
}
In Swift 4
var iconClick : Bool!
override func viewDidLoad() {
super.viewDidLoad()
iconClick = true
}
#IBAction func showHideAction(_ sender: Any)
{
let userPassword = userPasswordTextFiled.text!;
if(iconClick == true) {
userPasswordTextFiled.isSecureTextEntry = false
iconClick = false
} else {
userPasswordTextFiled.isSecureTextEntry = true
iconClick = true
}
}
Assignment values change from YES/NO to true/false boolean values.
password.secureTextEntry = true //Visible
password.secureTextEntry = false //InVisible
You can try this code..
i think it's helpful.
Use button with eye image
and make buttonHandler method
set Tag for button with value 1
-(IBAction) buttonHandlerSecureText:(UIButton *)sender{
if(sender.tag ==1){
[self.textField setSecureTextEntry:NO];
sender.tag = 2;
}
else{
[self.textField setSecureTextEntry:YES];
sender.tag = 1;
}
}
For Xamarin folks:
passwordField.SecureTextEntry = passwordField.SecureTextEntry ? passwordField.SecureTextEntry = false : passwordField.SecureTextEntry = true;
Try this code in swift 4, tried to make a reusable code within a controller. I have set different image for buttons in storyboard as shown in the link https://stackoverflow.com/a/47669422/8334818
#IBAction func clickedShowPassword(_ sender: UIButton) {
var textField :UITextField? = nil
print("btn ",sender.isSelected.description)
switch sender {
case encryptOldPswdBtn:
encryptOldPswdBtn.isSelected = !encryptOldPswdBtn.isSelected
textField = oldPasswordTextField
default:
break
}
print("text ",textField?.isSecureTextEntry.description)
textField?.isSecureTextEntry = !(textField?.isSecureTextEntry ?? false)
}
#objc func togglePasscode(){
switch textfield.isSecureTextEntry{
case true:
textfield.isSecureTextEntry = false
case false:
textfield.isSecureTextEntry = true
}
}
Here is a easy and more readable solution using Switch statement.
Hope this is simpler solution rather than creating a BOOL object globally.
#IBAction func passwordToggleButton(sender: UIButton) {
let isSecureTextEntry = passwordTextField.isSecureTextEntry
passwordTextField.isSecureTextEntry = isSecureTextEntry ? false : true
if isSecureTextEntry {
visibilityButton.setImage(UIImage(named: "visibility"), for: .normal)
} else {
visibilityButton.setImage(UIImage(named: "visibility_off"), for: .normal)
}
}
only add this line into your code replace you TextField name with "textfield" Done:
you need to change the isSecureTextEntry propertity to change true for password type textFiled like ......
textField.isSecureTextEntry = true
sender.isSelected = !sender.isSelected
if(sender.isSelected == true) {
RegPasswordField.isSecureTextEntry = false
sender.setBackgroundImage(UIImage(systemName: "eye.fill"), for: .normal)
} else {
RegPasswordField.isSecureTextEntry = true
sender.setBackgroundImage(UIImage(systemName: "eye"), for: .normal)
}
Swift 5 Please use this
var btnClick = true
if(btnClick == true) {
passwordTextField.isSecureTextEntry = false
} else {
passwordTextField.isSecureTextEntry = true
}
btnClick = !btnClick
}
var viewingPassword = true
#IBAction func btnEyeAction(_ sender: Any) {
passwordTF.isSecureTextEntry = viewingPassword ? false : true
viewingPassword.toggle()
}