How can I check if a String (for example "apple") contains text that I typed in a UITextField (for example "p" or "pp").
If the String contains the UITextField's text, I want to print a message - for example: "apple contains pp".
You can achieve that like so
class youClass: NSObject {
var yourTextFieldName = UITextField()
func someMethod() {
var apple = "apple"
if apple.containsString(self.yourTextfieldName.text!) {
print("apple contains \(self.yourTextfieldName.text!)")
}
}
}
You could extend String:
extension String {
#discardableResult
func containsText(of textField: UITextField) -> Bool {
// Precondition
guard let text = textField.text else { return false }
let isContained = self.contains(text)
if isContained { print("\(self) contains \(text)") }
return isContained
}
}
Instead of just printing a result, it also returns a Bool indicating whether or not the textField's text was contained in the String. The #discardableResult attribute allows you to ignore the return value if you want to though, without generating a compiler warning.
You could also take a reversed approach, by extending UITextField:
extension UITextField {
#discardableResult
func textIsContained(in target: String) -> Bool {
// Precondition
guard let text = self.text else { return false }
let isContained = target.contains(text)
if isContained { print("\(target) contains \(text)") }
return isContained
}
}
You would use these methods as follows:
// Your `UITextField`
let textField = UITextField()
textField.text = "pp"
// String extension:
"apple".containsText(of: textField) // returns `true` and prints "apple contains pp"
// UITextField extension:
textField.textIsContained(in: "apple") // returns `true` and prints "apple contains pp"
Related
Okay so I have a UITextLabel that is being updated to whatever and whenever UITextField is changed.
So I have the following method.
func textField(_ textField: UITextField, shouldChangeCharactersInrange: NSRange, replacementString string: String) -> Bool {
payment_amount_label.text = payment_amount_tf.text!
return true
}
and I have the textfield set up as a currency field. here is the code for that.
class CurrencyField: UITextField {
var string: String { return text ?? "" }
var decimal: Decimal {
return string.digits.decimal /
Decimal(pow(10, Double(Formatter.currency.maximumFractionDigits)))
}
var decimalNumber: NSDecimalNumber { return decimal.number }
var doubleValue: Double { return decimalNumber.doubleValue }
var integerValue: Int { return decimalNumber.intValue }
let maximum: Decimal = 9_999.99
private var lastValue: String?
override func willMove(toSuperview newSuperview: UIView?) {
// you can make it a fixed locale currency if needed
// Formatter.currency.locale = Locale(identifier: "pt_BR") // or "en_US", "fr_FR", etc
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
keyboardType = .numberPad
textAlignment = .right
editingChanged()
}
override func deleteBackward() {
text = string.digits.dropLast().string
print("inside method delete" + text!)
editingChanged()
//backspace not working for editingchanged. not sure why.
}
#objc func editingChanged(_ textField: UITextField? = nil) {
guard decimal <= maximum else {
text = lastValue
return
}
text = Formatter.currency.string(for: decimal)
lastValue = text
print("inside method editing" + text! + "last value is " + lastValue!)
return
}
}
extension NumberFormatter {
convenience init(numberStyle: Style) {
self.init()
self.numberStyle = numberStyle
}
}
extension Formatter {
static let currency = NumberFormatter(numberStyle: .currency)
}
extension String {
var digits: [UInt8] {
return map(String.init).compactMap(UInt8.init)
}
}
extension Collection where Iterator.Element == UInt8 {
var string: String { return map(String.init).joined() }
var decimal: Decimal { return Decimal(string: string) ?? 0 }
}
extension Decimal {
var number: NSDecimalNumber { return NSDecimalNumber(decimal: self) }
}
When I enter in numbers into the keypad everything updates correctly. However, when I hit backspace the textfield keeps the old value. I put in some print statements to see what was happening and when backspace is hit the UITextLabel is being updated before the delete happens inside the CurrencyField code. When a number is pressed the UITextLabel is updated AFTER the the CurrencyField code. I have no idea how to fix this issue any help is appreciated.
Try below:
Add a custom method for change in value to UITextField same as UITextView.
In viewDidLoad:
payment_amount_tf.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
Declare textFieldDidChange as:
#objc func textFieldDidChange(_ sender: UITextField) {
payment_amount_label.text = payment_amount_tf.text
}
I have a function firing on two observers - keyboardWillShowNotification and KeyboardWillHideNotification, and what I basically do is resetting a text field while editing, emulating the effect of clearsOnBeginEditing. However, if the user left the field blank I want it to return the original value, before editing. Here's my experimental code:
#objc func keyboardWillChange(notification: Notification) {
if notification.name == UIResponder.keyboardWillShowNotification || notification.name == UIResponder.keyboardWillHideNotification {
if textField.isEditing {
let originalValue: String!
originalValue = textField.text!
textField.text = ""
print("content while editing is \(originalValue)")
if notification.name == UIResponder.keyboardWillHideNotification {
print("this is content on end editing \(originalValue)")
if textField!.isEmpty == true {
print("this is nill")
textField.text! = originalValue
} else {
textField.text = textField.text
print("found a value")
}
}
}
}
What's the right way to do it?
You do not need to implement keyboard delegates for this. This is easily acheivable using the UITextFieldDelegate methods textFieldDidBeginEditing and textFieldDidEndEditing.
var orignalValue: String = ""
func textFieldDidBeginEditing(_ textField: UITextField) {
originalValue = textField.text
textField.text = ""
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
if textField.text?.isEmpty {
textField.text = orignalValue
}
}
Note: Your view controller would need to conform to UITextFieldDelegate and your text fields should have their delegates set to self.
How can I prevent the user from entering special characters in UITextField?
I solved the problem using this code:
let validString = NSCharacterSet(charactersInString: " !##$%^&*()_+{}[]|\"<>,.~`/:;?-=\\¥'£•¢")
// restrict special char in test field
if (textField == self.txt_firstName || textField == self.txt_lastName)
{
if let range = string.rangeOfCharacterFromSet(validString)
{
print(range)
return false
}
else
{
}
}
Swift 4.2
for emoji and special character
override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.isFirstResponder {
let validString = CharacterSet(charactersIn: " !##$%^&*()_+{}[]|\"<>,.~`/:;?-=\\¥'£•¢")
if (textField.textInputMode?.primaryLanguage == "emoji") || textField.textInputMode?.primaryLanguage == nil {
return false
}
if let range = string.rangeOfCharacter(from: validString)
{
print(range)
return false
}
}
return true
}
One more answer with default CharacterSet
Restrict all Special characters and also, this will support if any string you dont want to restrict.
extension String {
var containsValidCharacter: Bool {
guard self != "" else { return true }
let noNeedToRestrict = CharacterSet(charactersIn: " _") // NOT RESTRICT "Underscore and Space"
if noNeedToRestrict.containsUnicodeScalars(of: self.last!) {
return true
} else {
return CharacterSet.alphanumerics.containsUnicodeScalars(of: self.last!)
}
}
}
extension CharacterSet {
func containsUnicodeScalars(of character: Character) -> Bool {
return character.unicodeScalars.allSatisfy(contains(_:))
}
}
Usage:
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return string.containsValidCharacter
}
}
Here's an example of how you can allow users to only type alphanumeric characters using RxSwift.
Add the RxSwift pod
pod 'RxSwift', '~> 5'
Create a String extension to remove characters in a set
extension String {
func removeChars(in set: CharacterSet) -> String {
let filtered = self.unicodeScalars.filter { (scalarElement) -> Bool in
if (set.contains(scalarElement)) {
return false
}
return true
}
let trimmed = String(filtered.map({ (scalar) -> Character in
return Character(scalar)
}))
return trimmed
}
}
Use the RxSwift extension to remove invalid chars when the text changes
import UIKit
import RxSwift
class MyViewController: UIViewController {
private let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
}
private func setUpView() {
//Do view set up stuff here
//Use the extension here to listen to text changes and remove chars
myTextField.rx.text
.asDriver(onErrorJustReturn: "")
.drive(onNext: { [weak self] (text: String?) in
//Here you would change the character set to what you need
let newText = text?.removeChars(in: CharacterSet.alphanumerics.inverted)
self?.myTextField.text = newText
})
.disposed(by: disposeBag)
}
}
try with this
self.DataTblView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
This is an extension, not a duplicate, of How to check if a text field is empty or not in swift
The given answer,
#IBAction func Button(sender: AnyObject) {
if textField1.text != "" {
// textfield 1
}
}
does not work for me, i.e., the if-loop is triggered even when nothing is entered in the text field. (I have modified it from the original because I'm looking to trigger the code only when the field contains text).
The second answer
#IBAction func Button(sender: AnyObject) {
if !textField1.text.isEmpty{
}
}
comes much closer, but it accepts strings like " " as not empty. I could build something myself, but is there a function that will check if a string contains something other than whitespace?
This answer was last revised for Swift 5.2 and iOS 13.5 SDK.
You can trim whitespace characters from your string and check if it's empty:
if !textField1.text.trimmingCharacters(in: .whitespaces).isEmpty {
// string contains non-whitespace characters
}
You can also use .whitespacesAndNewlines to remove newline characters too.
Below is the extension I wrote that works nicely, especially for those that come from a .NET background:
extension String {
func isEmptyOrWhitespace() -> Bool {
if(self.isEmpty) {
return true
}
return (self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) == "")
}
}
Swift 4.2
Extension for String is empty or whitespace
extension String {
func isEmptyOrWhitespace() -> Bool {
// Check empty string
if self.isEmpty {
return true
}
// Trim and check empty string
return (self.trimmingCharacters(in: .whitespaces) == "")
}
}
The original poster's code is checking text on a textfield which is optional. So he will need some code to check optional strings. So let's create a function to handle that too:
Extension for Optional String is nil, empty or whitespace
extension Optional where Wrapped == String {
func isEmptyOrWhitespace() -> Bool {
// Check nil
guard let this = self else { return true }
// Check empty string
if this.isEmpty {
return true
}
// Trim and check empty string
return (this.trimmingCharacters(in: .whitespaces) == "")
}
}
akashivskyy answer in Swift 3.0:
let whitespaceSet = CharacterSet.whitespaces
if !str.trimmingCharacters(in: whitespaceSet).isEmpty {
// string contains non-whitespace characters
}
extension StringProtocol where Index == String.Index {
var isEmptyField: Bool {
return trimmingCharacters(in: .whitespaces) == ""
}
}
if yourTextField.text.isEmptyField {
// Field is empty
} else {
// Field is NOT empty
}
Answer in swift 4:
extension String {
func isEmptyOrWhitespace() -> Bool {
if(self.isEmpty) {
return true
}
return (self.trimmingCharacters(in: NSCharacterSet.whitespaces) == "")
}
}
Answer in Swift 3.0
if stringValue.trimmingCharacters(in: CharacterSet.whitespaces).isEmpty
{}
Answer in Swift 3.*, considers newlines, tabs
extension String {
var containsNonWhitespace: Bool {
return !self.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}
}
Answer with a picture in case you need a demo
// MY FUNCTIONS
private func checkMandatoryFields(){
//CHECK EMPTY OR SPACES ONLY FIELDS
if let type = typeOutle.text, let name = nameOutlet.text, let address = addressOutlet.text, type.trimmingCharacters(in: .whitespaces).isEmpty || name.trimmingCharacters(in: .whitespaces).isEmpty || address.trimmingCharacters(in: .whitespaces).isEmpty {
print("Mandatory fields are: ")
errorDisplay(error: "Mandatory fields are: Type, Name, Address.")
return
}
}
swift 4.2
#IBAction func checkSendButton(_ sender: UITextField) {
if((sender.text?.count)! > 0 && !(sender.text!.trimmingCharacters(in: .whitespaces)).isEmpty){
self.sendButton.isEnabled = true
}
else{
self.sendButton.isEnabled = false
}
}
Method
func trim() -> String {
return self.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
}
Use
if textField.text.trim().count == 0 {
// Do your stuff
}
I am working on the code below to check the textField1 and textField2 text fields whether there is any input in them or not.
The IF statement is not doing anything when I press the button.
#IBOutlet var textField1 : UITextField = UITextField()
#IBOutlet var textField2 : UITextField = UITextField()
#IBAction func Button(sender : AnyObject)
{
if textField1 == "" || textField2 == ""
{
//then do something
}
}
Simply comparing the textfield object to the empty string "" is not the right way to go about this. You have to compare the textfield's text property, as it is a compatible type and holds the information you are looking for.
#IBAction func Button(sender: AnyObject) {
if textField1.text == "" || textField2.text == "" {
// either textfield 1 or 2's text is empty
}
}
Swift 2.0:
Guard:
guard let text = descriptionLabel.text where !text.isEmpty else {
return
}
text.characters.count //do something if it's not empty
if:
if let text = descriptionLabel.text where !text.isEmpty
{
//do something if it's not empty
text.characters.count
}
Swift 3.0:
Guard:
guard let text = descriptionLabel.text, !text.isEmpty else {
return
}
text.characters.count //do something if it's not empty
if:
if let text = descriptionLabel.text, !text.isEmpty
{
//do something if it's not empty
text.characters.count
}
Better and more beautiful use
#IBAction func Button(sender: AnyObject) {
if textField1.text.isEmpty || textField2.text.isEmpty {
}
}
another way to check in realtime textField source :
#IBOutlet var textField1 : UITextField = UITextField()
override func viewDidLoad()
{
....
self.textField1.addTarget(self, action: Selector("yourNameFunction:"), forControlEvents: UIControlEvents.EditingChanged)
}
func yourNameFunction(sender: UITextField) {
if sender.text.isEmpty {
// textfield is empty
} else {
// text field is not empty
}
}
if let ... where ... {
Swift 3:
if let _text = theTextField.text, _text.isEmpty {
// _text is not empty here
}
Swift 2:
if let theText = theTextField.text where !theTextField.text!.isEmpty {
// theText is not empty here
}
guard ... where ... else {
You can also use the keyword guard :
Swift 3:
guard let theText = theTextField.text where theText.isEmpty else {
// theText is empty
return // or throw
}
// you can use theText outside the guard scope !
print("user wrote \(theText)")
Swift 2:
guard let theText = theTextField.text where !theTextField.text!.isEmpty else {
// the text is empty
return
}
// you can use theText outside the guard scope !
print("user wrote \(theText)")
This is particularly great for validation chains, in forms for instance. You can write a guard let for each validation and return or throw an exception if there's a critical error.
As now in swift 3 / xcode 8 text property is optional you can do it like this:
if ((textField.text ?? "").isEmpty) {
// is empty
}
or:
if (textField.text?.isEmpty ?? true) {
// is empty
}
Alternatively you could make an extenstion such as below and use it instead:
extension UITextField {
var isEmpty: Bool {
return text?.isEmpty ?? true
}
}
...
if (textField.isEmpty) {
// is empty
}
use this extension
extension String {
func isBlankOrEmpty() -> Bool {
// Check empty string
if self.isEmpty {
return true
}
// Trim and check empty string
return (self.trimmingCharacters(in: .whitespaces) == "")
}
}
like so
// Disable the Save button if the text field is empty.
let text = nameTextField.text ?? ""
saveButton.isEnabled = !text.isBlankOrEmpty()
A compact little gem for Swift 2 / Xcode 7
#IBAction func SubmitAgeButton(sender: AnyObject) {
let newAge = String(inputField.text!)
if ((textField.text?.isEmpty) != false) {
label.text = "Enter a number!"
}
else {
label.text = "Oh, you're \(newAge)"
return
}
}
Maybe i'm a little too late, but can't we check like this:
#IBAction func Button(sender: AnyObject) {
if textField1.text.utf16Count == 0 || textField2.text.utf16Count == 0 {
}
}
Okay, this might be late, but in Xcode 8 I have a solution:
if(textbox.stringValue.isEmpty) {
// some code
} else {
//some code
}
I used UIKeyInput's built in feature hasText: docs
For Swift 2.3 I had to use it as a method instead of a property (as it is referenced in the docs):
if textField1.hasText() && textField2.hasText() {
// both textfields have some text
}
Swift 4.x Solution
#IBOutlet var yourTextField: UITextField!
override func viewDidLoad() {
....
yourTextField.addTarget(self, action: #selector(actionTextFieldIsEditingChanged), for: UIControlEvents.editingChanged)
}
#objc func actionTextFieldIsEditingChanged(sender: UITextField) {
if sender.text.isEmpty {
// textfield is empty
} else {
// text field is not empty
}
}
Swift 4.2
You can use a general function for your every textField just add the following function in your base controller
// White space validation.
func checkTextFieldIsNotEmpty(text:String) -> Bool
{
if (text.trimmingCharacters(in: .whitespaces).isEmpty)
{
return false
}else{
return true
}
}
I just tried to show you the solution in a simple code
#IBAction func Button(sender : AnyObject) {
if textField1.text != "" {
// either textfield 1 is not empty then do this task
}else{
//show error here that textfield1 is empty
}
}
It's too late and its working fine in Xcode 7.3.1
if _txtfield1.text!.isEmpty || _txtfield2.text!.isEmpty {
//is empty
}
Swift 4/xcode 9
IBAction func button(_ sender: UIButton) {
if (textField1.text?.isEmpty)! || (textfield2.text?.isEmpty)!{
..............
}
}
Easy way to Check
if TextField.stringValue.isEmpty {
}