I am trying to validate UITextField if it has greater than 3 characters it should return true else return false. I tried using the below code but it is not working. What am I doing wrong?
let validUserNameSignal = self.nameTextField.reactive.trigger(for: .valueChanged).observeValues {
value in
}.map { (value) in
String(describing: value).characters.count > 3 ? true:false
}
print("user name valid result is \(validUserNameSignal)")
Here's how the code should look.
let validUserNameSignal =
self.nameTextField
.reactive
.continuousTextValues
.skipNil()
.map { $0.characters.count > 3 }
validUserNameSignal.observeValues { value in
print("user name valid result is \(value)")
}
Related
I am not sure how to call this scenario. Say i have this variable
let text: String?
How can it be coded such that my if condition would be something like this:
if (text == nil || Float(text) > 0) {
print("i am in")
}
I keep getting No exact matches in call to initializer
You have two issues here:
text is a String? and therefore it needs to be unwrapped to pass it to Float()
Float() returns an optional, this also should be unwrapped to be used with the > operator.
I would avoid force unwrapping, you can do something like:
let text: String? = nil
if let textString = text, let number = Float(textString) {
if number > 0 {
print("I am in")
}
else {
print("I am out")
}
}
else {
print("I am in")
}
First of all, looks like you want to check if text != nil then if text is number check if text > 0
Because in here you have optional String so you should have a specific to check if string text not nil. Then check if it is number.
Code will be like this
extension String {
var isNumber: Bool {
return Double(self) != nil
}
}
Then combine to your condition
if text == nil || (text!.isNumber && Float(text!)! > 0) {
print("i am in")
}
The result will be like this
let text: String? = "2.0" // i am in
let text: String? = nil // i am in
let text: String? = "-1.0" // nothing print
text is an optional
if (text == nil) || Float(text ?? "") ?? 0 > 0 {
print("i am in")
}
Two additional things must be done:
After your check if text is nil you must still unwrap the optional text to use it with the Float() constructor. Here I’ve used a forced unwrap ! which in general is dangerous, but we know at this point text cannot be nil due to the first test. If text is nil, the || uses short-circuit evaluation to return true without executing the right side.
Next, Float(text!) returns a Float? because that text might not convert to a valid Float. In order to unwrap that I’ve used the nil-coalescing operator ?? to unwrap the Float value or use 0 if the value is nil.
if text == nil || Float(text!) ?? 0 > 0 {
print("i am in")
}
This question already has answers here:
How to check if a text field is empty or not in swift
(16 answers)
Checking if textfields are empty Swift
(6 answers)
Closed 4 years ago.
I'm currently working on a project where I use lots of UITextFields. For validation I need to check if the UITextFields are empty. I got a working solution, but it's not that elegant. Maybe someone knows a better way of doing it.
Here is my solution:
// Check if text field is empty
if let text = textField.text, !text.isEmpty {
// Text field is not empty
} else {
// Text field is empty
}
Is there a faster way without unwrapping the text attribute of the text field to find out if it's empty?
Thanks!
How about extending UITextField…
extension UITextField {
var isEmpty: Bool {
if let text = textField.text, !text.isEmpty {
return false
}
return true
}
}
so then…
if myTextField.isEmpty {
}
You can use UIKeyInput property hasText. It works for both UITextField and UITextView:
if textField.hasText {
// Text field is not empty
} else {
// Text field is empty
}
If you would like to check if the text has not only spaces on it:
extension UITextField {
var isEmpty: Bool {
return text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
}
}
let tf = UITextField()
tf.text = " \n \n "
tf.isEmpty // true
If you have several textfields that you want to check, you could put them all in a guard statement
guard let text1 = textField1.text, let text2 = textField2.text, let text3 = textField3.text, !text1.isEmpty, !text2.isEmpty, !text3.isEmpty else {
//error handling
return
}
//Do stuff
I like to validate each text field depending on the content that should be provided by the user, i.e. emailTextField should contain a valid email address etc. While Ashley Mills answer is convenient, if you regard whitespace " " as text this will return false.
In your case, since you need to validate multiple text fields in the same way, why not extend UITextField as Ashley did with a static class method that can validate each text field passed as an array, in addition to this have other validation methods for each type of text field. Instead of returning a Boolean value I've learned to use guard instead. In this way guard let can be used to check if the validation fails (is nil) and execute the proper code, such as displaying a prompt to the user, or otherwise continue execution.
UITextFieldExtension.swift
import Foundation
import UIKit
extension UITextField {
/// Validates all text field are non-nil and non-empty, Returns true if all fields pass.
/// - Returns: Bool
static func validateAll(textFields:[UITextField]) -> Bool {
// Check each field for nil and not empty.
for field in textFields {
// Remove space and new lines while unwrapping.
guard let fieldText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
return false
}
// Are there no other charaters?
if (fieldText.isEmpty) {
return false
}
}
// All fields passed.
return true
}
//A function that validates the email address...
func validateEmail(field: UITextField) -> String? {
guard let trimmedText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
return nil
}
//email addresses are automatically detected as links in i0S...
guard let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
return nil
}
let range = NSMakeRange(0, NSString(string: trimmedText).length)
let allMatches = dataDetector.matches(in: trimmedText,
options: [],
range: range)
if allMatches.count == 1,
allMatches.first?.url?.absoluteString.contains("mailto:") == true
{
return trimmedText
}
return nil
}
func validateUserName(field: UITextField) -> String? {
guard let text:String = field.text else {
return nil
}
/* 3 to 12 characters, no numbers or special characters */
let RegEx = "^[^\\d!##£$%^&*<>()/\\\\~\\[\\]\\{\\}\\?\\_\\.\\`\\'\\,\\:\\;|\"+=-]+$"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
let isValid = Test.evaluate(with: text)
if (isValid) {
return text
}
return nil
}
/*6 to 16 Characters */
func validatePassword(field: UITextField) -> String?{
guard let text:String = field.text else {
return nil
}
/*6-16 charaters, and at least one number*/
let RegEx = "^(?=.*\\d)(.+){6,16}$"
let Test = NSPredicate(format:"SELF MATCHES%#", RegEx)
let isValid = Test.evaluate(with: text)
if (isValid) {
return text
}
return nil
}
}
Meanwhile, elsewhere...
if (UITextField.validateAll(textFields: [emailTextField, nameTextField])) {
// Do something
}
Using this code, I tried to do an insensitive-case search to find companies for a certain major, but I get the error "Expression 'Bool' is ambiguous without more context" at let isFound =.
Why? How do I solve this?
company.majors is a String array. searchValue is a lowercase String
let searchValue = filterOptItem.searchValue?.lowercased()
for company in allCompanies {
//Insensitive case search
let isFound = company.majors.contains({ $0.caseInsensitiveCompare(searchValue) == ComparisonResult.orderedSame })
if (isFound) {
filteredCompanies.insert(company)
}
}
SearchValue is an optional string.
If you are sure that searchValue can't be nil. Please use:
let isFound = company.majors.contains({ $0.caseInsensitiveCompare(searchValue!) == ComparisonResult.orderedSame })
If you are not sure, use:
if let searchValue = filterOptItem.searchValue?.lowercased(){
for company in allCompanies {
//Insensitive case search
let isFound = company.majors.contains({ $0.caseInsensitiveCompare(searchValue) == ComparisonResult.orderedSame })
if (isFound) {
filteredCompanies.insert(company)
}
}
}
Depends very much of a context and possible extensions, however cod itself seems wrong: you should either implicit closure let isFound = company.majors.contains{ $0.caseInsensitiveCompare(searchValue) == ComparisonResult.orderedSame } or use parameter name where:.
Fixed code work fine for Swift4 playgrounds:
let company = (name: "Name", majors: ["a", "b", "cas"])
let searchValue = "a"
let isFound = company.majors.contains{ $0.caseInsensitiveCompare(searchValue) == ComparisonResult.orderedSame }
Swift 5 , Swift 4
//MARK:- You will find the array when its filter in "filteredStrings" variable you can check it by count if count > 0 its means you have find the results
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
let searchToSearch = "go"
let filteredStrings = itemsArray.filter({(item: String) -> Bool in
let stringMatch = item.lowercased().range(of: searchToSearch.lowercased())
return stringMatch != nil ? true : false
})
print(filteredStrings)
if (filteredStrings as NSArray).count > 0
{
//Record found
}
else
{
//Record Not found
}
This question already has answers here:
Password validation in UITextField in iOS
(11 answers)
Closed 6 years ago.
I'm trying to set up specific criteria the user must create in order to create a new account. The criteria is as follows:
Password must start with a letter
At least 1 upper case letter
At least 1 lower case letter
At least 1 number
At least 1 Special Character
The password may not contain username
There was more criteria but these are the ones giving me the most problems. Any help on any of them is greatly appreciated!
Try this method:
func validate(pass: String, userName: String) -> Bool {
guard pass.characters.count > 0 else {return false }
guard pass != userName else {return false }
//Checks if the first character is a lowercase letter
let firstIndex = pass.index(pass.startIndex, offsetBy: 1)
guard pass.substring(to: firstIndex).rangeOfCharacter(from: CharacterSet.lowercaseLetters) != nil else { return false }
guard pass.rangeOfCharacter(from: CharacterSet.uppercaseLetters) != nil else { return false }
guard pass.rangeOfCharacter(from: CharacterSet.lowercaseLetters) != nil else { return false }
guard pass.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil else { return false }
let characterSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789")
guard pass.rangeOfCharacter(from: characterSet.inverted) != nil else { return false }
return true
}
Create functions that loop through each character of the entered password and check to see if it is contained in a particular string. For the upper case letter,
loop through each character of the password, like this:
for c in password.characters {
if "ABCDEFGHIJKLMNOPQRSTUVWXYZ".range(of:String(c)) != nil {
return
}
}
//if for loop is exited, alert user that their password is invalid.
Here is the code:
let answer = randomIntBetween(1, high: 100)
print("Enter a number between 1 and 100!")
let userInput = input()
let inputAsInt = userInput.toInt()
if let guess = inputAsInt {
if (guess > answer) {
print("Your guess was too high!")
} else if (guess < answer) {
print("Your guess was too low!")
} else {
print("You got it dead on! The answer was \(answer)!")
}
} else {
print("Not a valid answer, try adding a number!")
}
I am following a guide (only been learning for about a month) and I know .toInt() was removed but what would I need to put in its place?
Down cast replaced it.
let inputAsInt = Int(userInput)