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

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.

Related

How to change the color of all Labels in a UIView in Swift?

I found a similar question here. But the problem is it is in OBJ-C. I do not know the code and am working in SWIFT so please can anyone explain and translate this code in swift.
I am still new to swift so please help me.
Regards
Create
var globalColor = UIColor.red
class CustomLbl:UILabel {
override func awakeFromNib() { // inside IB
super.awakeFromNib()
self.textColor = globalColor
}
override func draw(_ rect: CGRect) { // programmatically
super.draw(rect)
self.textColor = globalColor
}
}
And assign it in IB or code , for programmatically call
self.view.setNeedsDisplay()
after you change global color
with an extension. Maybe its not the perfect solution but once you applied it to all needed labels, then it applies to all labels when you make a change. Create a new swift file and put the following code in:
import UIKit
extension UILabel {
func labelColor() {
self.textColor = UIColor.red //or whichever color you want
}
}
And in the viewDidLoad or viewWillLoad you can do:
yourLabel.labelColor()
self.view.subviews.forEach { (view) in // Loop
if let label = view as? UILabel { // check the type
label.textColor = .red // assign the color
}
}
And self is your viewController
As explain in the similar question, you have to
Loop through all the UIView's in self.view.subviews and check if it's
of type UILabel.

Prevent UITextField editing but detect taps

I have a UITextField and I am trying to detect the taps on it and prevent user typing input at the same time. The scenario is, I'm gonna use an alert view to make the user select an option and write it inside UITextField rather than user typing it using keyboard.
I tried using in viewDidLoad():
myTextField.delegate = self
myTextField.isEnabled = true
myTextField.isUserInteractionEnabled = false
// for keyboard
myTextField.inputView = UIView()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didRecognizeTapGesture(_:)))
myTextField.addGestureRecognizer(tapGesture)
However this tap gesture doesn't work:
private dynamic func didRecognizeTapGesture(_ gesture: UITapGestureRecognizer) {
print("YYYY")
let point = gesture.location(in: gesture.view)
guard gesture.state == .ended, taxableField.frame.contains(point) else { return }
//doSomething()
}
Then I tried making userInteractionEnabled true and this time:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == myTextField {
print("XXXX")
return true
}
return true
}
This worked, however now I can long-press and paste into the textfield, so it is active, it's just not showing the keyboard this way.
So any of the ways I have tried don't seem convenient. What do you suggest for achieving such thing?
So, to create a UIPickerView and add it as your inputView, you need a delegate and a datasource. For this example, I'm going to assume that your VC will fill all of these roles. I usually split these out into custom classes, but I want to keep this simple:
// Data source for your picker view
var pickerViewData : [String]?
var myPickerView = UIPickerView()
#IBOutlet myTextField : UITextField!
func viewDidload() {
myPickerView.delegate = self
myPickerView.dataSource = self
myTextField.delegate = self
myTextField.inputView = pickerView
}
And then, to update your UITextField, whenever your picker view is used, implement the correct delegate method (It won't build unless you implement the method, regardless):
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
myTextField.text = pickerViewData![pickerView.selectedRow(inComponent: 0)]
}
And that's it! You also have to implement some other UIPickerView and UITextField delegate and datasource methods; I'm assuming you can figure out how to do this, if you don't know already.
You can take a UIButton over the UITextField and align its leading, trailing, top and Bottom with the UITextField.
Then add an action for the button.
Disable the TextField.
You can use UIPickerView to implement your function. If the picker must be a AlertView, you can replace the UITextField with a UILabel and put a UIButton upon it then you can implement the custom action in the UIButton callback and display the selection in the UILabel.
create a custom UIViewController which background color is clear and add a UIPickerView to show options. Show the UIViewController (overlay on top of current UIView) while UITextField is focus. So, you can do your handles within custom UIViewController.

Remove UIButton highlight for all buttons in an app

I'm wondering if there's a way to remove the highlight from UIButtons in my app. I know how to do it for an individual button (adjustsImageWhenHighlighted) but I don't want to go through all the buttons in my app and do it. Is it possible to set adjustsImageWhenHighlighted to false in the App Delegate so it applies to all buttons?
Put this code in didFinishLaunchingWithOptions
UIButton.appearance().adjustsImageWhenHighlighted = false
Then all the default value adjustsImageWhenHighlighted of UIButton is false
private let button: NoHighlightButton = NoHighlightButton()
class NoHighlightButton: UIButton {
override var highlighted: Bool {
didSet{
super.highlighted = false
}
}
}

Disabling user input for UITextfield in swift

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

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