Disabling user input for UITextfield in swift - ios

pretty trivial question, I know. But I can not find anything online.
I need to disable the user from being able to edit the text inside of a text field. So that when the click on the text, a keyboard doesn't show up.
Any ideas?
A programmatic solution or if it is possible through storyboards would be great.

Try this:
Swift 2.0:
textField.userInteractionEnabled = false
Swift 3.0:
textField.isUserInteractionEnabled = false
Or in storyboard uncheck "User Interaction Enabled"

Another solution, declare your controller as UITextFieldDelegate, implement this call-back:
#IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
myTextField.delegate = self
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == myTextField {
return false; //do not show keyboard nor cursor
}
return true
}

In storyboard you have two choise:
set the control's 'enable' to false.
set the view's 'user interaction enable' false
The diffierence between these choise is:
the appearance of UITextfild to display in the screen.
First is set the control's enable. You can see the backgroud color is
changed.
Second is set the view's 'User interaction enable'. The backgroud color is NOT changed.
Within code:
textfield.enable = false
textfield.userInteractionEnabled = NO
Updated for Swift 3
textField.isEnabled = false
textfield.isUserInteractionEnabled = false

If you want to do it while keeping the user interaction on.
In my case I am using (or rather misusing) isFocused
self.myField.inputView = UIView()
This way it will focus but keyboard won't show up.

I like to do it like old times. You just use a custom UITextField Class like this one:
//
// ReadOnlyTextField.swift
// MediFormulas
//
// Created by Oscar Rodriguez on 6/21/17.
// Copyright © 2017 Nica Code. All rights reserved.
//
import UIKit
class ReadOnlyTextField: UITextField {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
override init(frame: CGRect) {
super.init(frame: frame)
// Avoid keyboard to show up
self.inputView = UIView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Avoid keyboard to show up
self.inputView = UIView()
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
// Avoid cut and paste option show up
if (action == #selector(self.cut(_:))) {
return false
} else if (action == #selector(self.paste(_:))) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}

In swift 5, I used following code to disable the textfield
override func viewDidLoad() {
super.viewDidLoad()
self.textfield.isEnabled = false
//e.g
self.design.isEnabled = false
}

Swift 4.2 / Xcode 10.1:
Just uncheck behavior Enabled in your storyboard -> attributes inspector.

you can use UILabel instead if you don't want the user to be able to modify anything in your UITextField
A programmatic solution would be to use enabled property:
yourTextField.enabled = false
A way to do it in a storyboard:
Uncheck the Enabled checkbox in the properties of your UITextField

textField.isUserInteractionEnabled = false

Related

iOS (swift) exit/dismiss preselect textView in share extension

when launching the iOS share extension the textView will by default already be selected / entered. (the keyboard will be visible and the textView will be in edit mode)
I don't want this to happen, how do I programatically exit the textView
override func viewDidLoad() {
self.textView.exit() // obviously doesn't work
}
I see tons of posts about how to exit when user press enter on the keyboard, I do not want to do it "when something delegate" I just want the textview to not be in edit mode when the extension is launched (on viewDidLoad).
I have also tried (as suggested in other post)
self.textView.endEditing(true)
which did not hide the keyboard or exit the textView
You can call textView.resignFirstResponder() in presentationAnimationDidFinish
class ShareViewController: SLComposeServiceViewController {
var textViewTintColor: UIColor?
override func viewDidLoad() {
super.viewDidLoad()
// hide cursor which appears during presentation animation
self.textViewTintColor = self.textView.tintColor
self.textView.tintColor = .clear
}
override func presentationAnimationDidFinish() {
super.presentationAnimationDidFinish()
guard let tintColor = self.textViewTintColor else { return }
self.textView.resignFirstResponder()
// reset cursor
self.textView.tintColor = tintColor
self.textViewTintColor = nil
}
}

How can I make an arbitrary UIAccessibilityElement behave like a UISwitch for VoiceOver?

When selecting a native switch with VoiceOver, the announcement will contain "Off" or "On" with an additional hint "double tap to toggle setting".
I have tried using the accessibility trait UIAccessibilityTraitSelected, but that only results in "Selected" being announced, with no hint unless I provide one explicitly.
Using the Accessibility Inspector I've also noticed that native UIKit switches have an accessibilityValue of 1 when enabled, but providing that does not change VoiceOver behavior.
- (UIAccessibilityTraits)accessibilityTraits {
if (toggled) {
return UIAccessibilityTraitSelected;
} else {
return UIAccessibilityTraitNone;
}
}
- (NSString*)accessibilityValue {
if (toggled) {
return #"1";
} else {
return #"0"
}
}
Is it possible to provide some combination of traits/value/label such that TalkBack recognizes this element as a Switch, without using a UISwitch?
I have created an accessible view that acts like a switch here.
The only way that I have been able to get any arbitrary element to act like a Switch is when inheriting the UIAccessibilityTraits of a Switch. This causes VoiceOver to read the Accessibility Value (0 or 1) as "Off" or "On," adds the hint "Double tap to toggle setting", and makes VoiceOver say "Switch Button."
You could potentially do this by overriding the view's Accessibility Traits like so:
override var accessibilityTraits(): UIAccessibilityTraits {
get { return UISwitch().accessibilityTraits }
set {}
}
Hope this helps!
You can create a custom accessibility element behaving like a UISwitchControl with whatever you want.
The only thing to be specified is the way VoiceOver should interpret it.
Let's suppose you want to gather a label and a view to be seen as a switch control.
First of all, create a class for grouping these elements into a single one :
class WrapView: UIView {
static let defaultValue = "on"
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(with label: UILabel,and view: UIView) {
let viewFrame = label.frame.union(view.frame)
self.init(frame: viewFrame)
self.isAccessibilityElement = true
self.accessibilityLabel = label.accessibilityLabel
self.accessibilityValue = WrapView.defaultValue
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
}
}
Then, just create your custom view in your viewDidAppear() :
class ViewController: UIViewController {
#IBOutlet weak var myView: UIView!
#IBOutlet weak var myLabel: UILabel!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let myCustomView = WrapView.init(with: myLabel, and: myView)
self.view.addSubview(myCustomView)
}
}
Finally, to have a custom view behaving like a switch control, just override the accessibilityActivate function in your WrapView class to implement your logic when your view is double tapped :
override func accessibilityActivate() -> Bool {
self.accessibilityValue = (self.accessibilityValue == WrapView.defaultValue) ? "off" : "on"
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
return true
}
And now you have a custom element that contains whatever you want and that behaves like a switch control for blind people using VoiceOver without using a UISwitch as you wanted.

How to add property to UIButton?

thanks for all help:)! fixed it using iboutlet collection and add properies on viewDidLoad
I'm trying to add properties to keyboard keys like layer.shadowColor or layer.shadowRadius.
I got an error
'Value of type '(UIButton)' -> () has no member 'layer'
how to fix this ?
this is my code keyboardViewController.swift
import UIKit
class KeyboardViewController: UIInputViewController {
var newKeyboardView: UIView!
#IBAction func keyPressed(sender: UIButton) {
}
#IBOutlet var nextKeyboardButton: UIButton!
override func updateViewConstraints() {
super.updateViewConstraints()
// Add custom view sizing constraints here
}
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
}
func loadInterface() {
// load the nib file
let keyboardNib = UINib(nibName: "newKeyboard", bundle: nil)
// instantiate the view
newKeyboardView = keyboardNib.instantiateWithOwner(self, options: nil)[0] as! UIView
// add the interface to the main view
view.addSubview(newKeyboardView)
// copy the background color
view.backgroundColor = newKeyboardView.backgroundColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
override func textWillChange(textInput: UITextInput?) {
// The app is about to change the document's contents. Perform any preparation here.
}
override func textDidChange(textInput: UITextInput?) {
// The app has just changed the document's contents, the document context has been updated.
var textColor: UIColor
let proxy = self.textDocumentProxy
if proxy.keyboardAppearance == UIKeyboardAppearance.Dark {
textColor = UIColor.whiteColor()
} else {
textColor = UIColor.blackColor()
}
self.nextKeyboardButton.setTitleColor(textColor, forState: .Normal)
}
}
I think that in order to apply some style to the button, you need an outlet to this button.
Right now, from what I can understand, you are trying to apply styles to the button from the #IBAction to the sender, which is not the proper way to do it.
Try to make an outlet to the button in the view controller and then to apply the styles from within the viewDidLoad method.
I hope this is clear, but if you want a more specific answer you need to show us what you tried, for example pasting the code you have in the view controller
EDIT:
Based on the code you post, the keyboard is a Nib you instantiate from loadInterface(). I don't have a clear vision of the whole thing with only this piece of code, but it seems to me that you are trying to apply some styles to every key button of a keyboard view. Unfortunately this really depends on how the keyboard is implemented, can you provide some more details?
Anyway, from what I see I think you didn't write this code: probably you are following a tutorial or maintaining someone else's code. That's ok, but I suggest you to follow a an introduction course to iOS development with Swift, like the Udacity's one, which is fantastic IMHO (https://www.udacity.com/course/intro-to-ios-app-development-with-swift--ud585)
If you try to format your UIButton with QuartzCore framework, you'll need to import it first:
import QuartzCore
Then you will be able to access those members.
For example (latest swift3 code):
#IBAction func keyPressed(sender: UIButton) {
let button = sender as UIButton!
button?.backgroundColor = UIColor.red
button?.layer.shadowColor = UIColor.black.cgColor
button?.layer.shadowRadius = 1.0
button?.layer.cornerRadius = 4.0
}
In case you need to apply your styles sooner, try to consider to put this code into viewDidLoad or viewDidAppear methods:
self.nextKeyboardButton.backgroundColor = UIColor.red
self.nextKeyboardButton.layer.shadowColor = UIColor.black.cgColor
self.nextKeyboardButton.layer.shadowRadius = 1.0
self.nextKeyboardButton.layer.cornerRadius = 4.0
Seems like you're trying to "add property" not to a button, but rather to a closure which accepts a button as an argument.
Make it like this:
nextKeyboardButton.layer.shadowColor = UIColor.redColor.cgColor
nextKeyboardButton.layer.shadowRadius = 5.0

How do I activate an inputView using a UIButton in Swift?

I am attempting to have a UIDatePicker come up as a keyboard when the user hits a UIButton. I was able to get it to work with a textfield, but I don't like how the cursor is visible and the user could enter in any text if they had an external keyboard. Here is my code:
#IBAction func dateFieldStart(sender: UITextField) {
var datePickerStartView : UIDatePicker = UIDatePicker()
datePickerStartView.datePickerMode = UIDatePickerMode.Time
sender.inputView = datePickerStartView // error when sender is UIButton
}
I tried changing the sender to UIButton but it gave this error on the line that is marked above:
Cannot assign to 'inputView' in 'sender'
I have tried researching it and no one else seems to have had a problem with it. Anyone know how to trigger a UIDatePicker inputView using a UIButton or anything that might work better that the user cannot type into? Thanks!
This is years after the original question, but for anyone who may be looking for solution to this you can subclass UIButton and provide a getter and setter for the inputView property. Be sure to call becomeFirstResponder in the setter and override canBecomeFirstResponder. For example:
class MyButton: UIButton {
var myView: UIView? = UIView()
var toolBarView: UIView? = UIView()
override var inputView: UIView? {
get {
myView
}
set {
myView = newValue
becomeFirstResponder()
}
}
override var inputAccessoryView: UIView? {
get {
toolBarView
}
set {
toolBarView = newValue
}
}
override var canBecomeFirstResponder: Bool {
true
}
}
let tempInput = UITextField( frame:CGRect.zero )
tempInput.inputView = self.myPickerView // Your picker
self.view.addSubview( tempInput )
tempInput.becomeFirstResponder()
It's a good idea to keep a reference to tempInput so you can clean-up on close
I wanted to do the same thing, I ended up just overlaying a UITextField over the button and using the inputView of that instead.
Tip: set tintColor of the UITextField to UIColor.clearColor() to hide the cursor.
You can create a view for the picker off screen view and move it on screen when you need it. Here's another post on this.

error passing data between ViewController

I've a strange issue. I have a UITextField I can write inside and the text is displayed directly in UITextView. I'm using a UITabBarController to switch between the UIViewController.
I'm using that class to save data (wrote in TabBarController.swift):
public class ModelData {
var text = ""
var color:UIColor? = nil
}
That code to save the data (wrote in ViewController.swift):
override func viewDidDisappear(animated: Bool) {
let model = (self.tabBarController as TabBarViewController).model
model.color = textview.textColor
model.text = textview.text
}
And that code to give the data (wrote in SecondViewController.swift):
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let model = (self.tabBarController as TabBarViewController).model
textview.textColor = model.color
textview.text = model.text
}
So, my problem is that: Because I use a UItextField where I can write inside I have disabled User Interaction in UITextView, but now I need to enable that options because I want scroll the UITextView. But now when I pass between the ViewController the data is not saved. (only the color is not saved)
For whatever reason, (it looks like a bug), the textColor property of UITextView returns nil when Selectable is unchecked in Interface Builder. It is not a problem if the selectable property is set to false in code. So a workaround is to leave Selectable checked in Interface Builder and set it to false in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
// Set selectable to false here so that the user can't select the
// textview text, but User Interaction is still enabled to allow them
// to scroll it. This is a workaround for a problem in Interface
// Builder which causes the textColor property to return nil if Selectable
// is unchecked in Interface Builder.
textview.selectable = false
}

Resources