Adding a rule to a custom rule in Eureka - swift

So I've created a custom row which is just a row with a simply UITextView now I want to create a rule such that if the UITextView has under 100 characters the variable row.isValid will evaluate to false.
<<< TextViewRow("About Me") {
let cell = $0.baseCell as! TextViewCell
cell.textView.text = currentUser.aboutMe
$0.disabled = Condition.function([]) {
form in
print("in disabled")
let section = form.sectionBy(tag: "About Me")
let view = section!.header?.viewForSection(section!, type: .header) as! TitleHeaderView
if view.isLocked {
return true
} else {
return false
}
}
$0.cellUpdate({ (cell, row) in
if row.isDisabled {
cell.textView.isUserInteractionEnabled = false
cell.textView.textColor = UIColor.gray
} else {
cell.textView.isUserInteractionEnabled = true
cell.textView.textColor = UIColor.black
}
})
let ruleRequiredViaClosure = RuleClosure<String> { rowValue in
guard let rowValue = rowValue else {
return(ValidationError(msg : "Please write more!"))
}
let numberOfCharacters = rowValue.characters.count
return (numberOfCharacters < 250 ? ValidationError(msg: "Please write more!") : nil)
}
$0.add(rule: ruleRequiredViaClosure)
$0.validationOptions = .validatesOnDemand
}
With a normal TextRow this would compile and XCode won't throw any error, although since TextViewRow is a custom row I believe this is why it is throwing an error.
The error it gives me is that I need to use:
$0.add(ruleSet: ...)
but I can't find any documentation on it.
Also I'm not sure whether I am able to define my rule as I have since the rowValue in the closure probably isn't referencing anything. How would I fix this problem?

Welcome to the world of Eureka, %&*# all documentation on anything. I recently took a liking to Eureka and began to convert my project to it, along the way I hit many obstacles that could easily have been avoided if the documentation was decent. Fortunately for you, custom validation rules was one such obstacle; my implementation is as follows:
struct RulePassword<T: Equatable>:RuleType {
public init() {}
public var id: String?
public var validationError: ValidationError = ValidationError(msg: "Invalid password.")
public func isValid(value: T?) -> ValidationError? {
if let str = value as? String {
let errorMsg = RGOValidationHelper.passwordValidation(str)
return errorMsg != nil ? ValidationError(msg: errorMsg!) : nil
}
return validationError
}
}
Note the call to RGOValidationHelper simply returns an error string in the event that the validation fails, nil otherwise.
Before you go and create a custom rule however, it must be noted that Eureka actually includes a facility to set a minimum length on a field. RuleMinLength is the name of the rule and it can be initialised by passing in a value for min length, in your case 100. Here is Eureka's implementation for the rule:
public struct RuleMinLength: RuleType {
let min: UInt
public var id: String?
public var validationError: ValidationError
public init(minLength: UInt, msg: String? = nil){
let ruleMsg = msg ?? "Field value must have at least \(minLength) characters"
min = minLength
validationError = ValidationError(msg: ruleMsg)
}
public func isValid(value: String?) -> ValidationError? {
guard let value = value else { return nil }
return value.characters.count < Int(min) ? validationError : nil
}
}
I hope this helps somewhat, if you have any further problems with Eureka chances are I've come across and solved them before, so feel free to send me a message.

Related

Swift: How to determine object type based on the outcome of switch statement

I have a function that returns whether an item exists in 1 of 3 CoreData entities, depending on the list: CoreDataList enum argument passed to that function:
static func listContains(word: String, list: CoreDataList) -> Bool {
var reply = false
switch list {
case .itemsSearched:
let request : NSFetchRequest<ItemsSearched> = ItemsSearched.fetchRequest()
case .itemsAdded:
let request : NSFetchRequest<ItemsAdded> = ItemsAdded.fetchRequest()
case .itemsFinished:
let request : NSFetchRequest<ItemsFinished> = ItemsFinished.fetchRequest()
}
do {
request.predicate = NSPredicate(format: "item == %#", word)
let fetchedResults = try context.fetch(request)
if fetchedResults.count == 1 {
reply = true
}
} catch {
print ("fetch task failed", error)
}
return reply
}
The problem here is that let request cannot be initialized before the switch statement because its type will depend on the outcome of the switch.
Therefore I cannot find a way to do this function without repeating the entire do catch block for each case, which will result in repeating the same code three times. The other option is to separate into three different function, but this presents the same code repetition problem.
You can create a generic function for this
static func checkCount<T: NSManagedObject>(word: String, context: NSManagedObjectContext, type: T.Type) -> Bool {
let request = T.fetchRequest()
request.predicate = NSPredicate(format: "item == %#", word)
do {
let fetchedResults = try context.fetch(request)
if fetchedResults.count == 1 {
return true
}
} catch {
print ("fetch task failed", error)
}
return false
}
and then call it from inside the switch
case .itemsSearched:
return checkCount(word: word, context: context, type: ItemsSearched.self)
Note that I added context as a parameter to the function since I didn't know how it is declared, perhaps that parameter isn't needed.

Converting a rawValue into a string in Swift

Apple has made changes from Swift 3 to 4. When I run the following code:
let metadata = [ PDFDocumentAttribute.titleAttribute,
PDFDocumentAttribute.authorAttribute,
PDFDocumentAttribute.subjectAttribute,
PDFDocumentAttribute.creatorAttribute,
PDFDocumentAttribute.producerAttribute,
PDFDocumentAttribute.creationDateAttribute,
PDFDocumentAttribute.modificationDateAttribute,
PDFDocumentAttribute.keywordsAttribute ]
if var attributes = pdfDoc.documentAttributes {
for (index, value) in metadata.enumerated() {
if attributes[value] != nil {
print("\(metadata[index])): \(String(describing: attributes[value]!))")
} else {
print("\(metadata[index]): nil")
}
}
I now get: PDFDocumentAttribute(_rawValue: Title) instead of "Title", which I got before as the value of metadata[index].
How do I get rid of the rawValue stuff?
The PDFDocumentAttribute type has a property called rawValue that contains the old string value. So you can say
print("\(metadata[index].rawValue): \(String(describing: attributes[value]!))")
As an aside, instead of force-unwrapping the attribute you can use an if let, as in
if let attr = attributes[value] {
print("\(metadata[index].rawValue): \(attr)")
} else {
print("\(metadata[index].rawValue): nil")
}
If you add this extension:
extension PDFDocumentAttribute: CustomStringConvertible {
public var description: String {
return self.rawValue
}
}
Now you can just do:
// Forcing the downcast has little risk here
// but you may want to use `as?` and test for the optional instead
let attributes = pdfDoc.documentAttributes as! [PDFDocumentAttribute:Any]
for meta in metadata {
print("\(meta): \(attributes[meta] ?? "nil")")
}
Note that you can also do:
for attribute in attributes {
print("\(attribute.key): \(attribute.value)")
}
Which will just print out the attributes that exist on the document.

Use of unresolved identifier while using extension in swift 3

I have made a String extension for validating the form in Swift 3 language.
The code is below:
import UIKit
extension String {
// Validating Email ID
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
// Validating the User name
func isValidUserName(testStr:String) -> Bool {
let RegEx = "\\A\\w{7,18}\\z"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
return Test.evaluate(with: testStr)
}
// Validating the phone number
var isPhoneNumber: Bool {
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
let matches = detector.matches(in: self, options: [], range: NSMakeRange(0, self.characters.count))
if let res = matches.first {
return res.resultType == .phoneNumber && res.range.location == 0 && res.range.length == self.characters.count
} else {
return false
}
} catch {
return false
}
}
// validating the password
/*
Use the function of Swift 3.0.
1. 8 characters length
2. alphabet
3. special character
regex Syntax Explanation :
(?=.[a-z]) for Character.
(?=.[$#$#!%?&]) for special character.
{8,} for length which you want to prefer.
*/
func isPasswordValid(_ password : String) -> Bool{
let passwordTest = NSPredicate(format: "SELF MATCHES %#", "^(?=.*[a-z])(?=.*[$#$#!%*?&])[A-Za-z\\d$#$#!%*?&]{8,}")
return passwordTest.evaluate(with: password)
}
// validating the password and confirm password are same........................
func isPasswordSame(password: String , confirmPassword : String) -> Bool {
if password == confirmPassword{
return true
} else {
return false
}
}
// validating Blank Text........................
var isBlank:Bool {
return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty
}
}
But when i am trying to use this extension class in other view controller through the code :
if isValidEmail("kirit#gmail.com"){
print("Validate EmailID")
}
else{
print("invalide EmailID")
}
I am getting the error:
isValidEmail is not a loose function. You have defined it as an instance function on String. You would need to say
"someString".isValidEmail(testStr:"someOtherString")
That makes no sense, but that's how you've configured it. If you write it that way, your code will compile (though it will be very silly code).
Just change your definition to something like
extension String {
// Validating Email ID
func isValidEmail() -> Bool {
self.validate...
}
and then use it in your code as
#someString".isValidEmail()

How do I tell which guard statement failed?

If I’ve got a bunch of chained guard let statements, how can I diagnose which condition failed, short of breaking apart my guard let into multiple statements?
Given this example:
guard let keypath = dictionary["field"] as? String,
let rule = dictionary["rule"] as? String,
let comparator = FormFieldDisplayRuleComparator(rawValue: rule),
let value = dictionary["value"]
else
{
return nil
}
How can I tell which of the 4 let statements was the one that failed and invoked the else block?
The simplest thing I can think of is to break out the statements into 4 sequential guard else statements, but that feels wrong.
guard let keypath = dictionary["field"] as? String
else
{
print("Keypath failed to load.")
self.init()
return nil
}
guard let rule = dictionary["rule"] as? String else
{
print("Rule failed to load.")
self.init()
return nil
}
guard let comparator = FormFieldDisplayRuleComparator(rawValue: rule) else
{
print("Comparator failed to load for rawValue: \(rule)")
self.init()
return nil
}
guard let value = dictionary["value"] else
{
print("Value failed to load.")
self.init()
return nil
}
If I wanted to keep them all in one guard statement, I can think of another option. Checking for nils inside the guard statement might work:
guard let keypath = dictionary["field"] as? String,
let rule = dictionary["rule"] as? String,
let comparator = FormFieldDisplayRuleComparator(rawValue: rule),
let value = dictionary["value"]
else
{
if let keypath = keypath {} else {
print("Keypath failed to load.")
}
// ... Repeat for each let...
return nil
}
I don't even know if that will compile, but then I might as well have used a bunch of if let statements or guards to begin with.
What's the idiomatic Swift way?
Erica Sadun just wrote a good blog post on this exact topic.
Her solution was to hi-jack the where clause and use it to keep track of which guard statements pass. Each successful guard condition using the diagnose method will print the file name and the line number to the console. The guard condition following the last diagnose print statement is the one that failed. The solution looked like this:
func diagnose(file: String = #file, line: Int = #line) -> Bool {
print("Testing \(file):\(line)")
return true
}
// ...
let dictionary: [String : AnyObject] = [
"one" : "one"
"two" : "two"
"three" : 3
]
guard
// This line will print the file and line number
let one = dictionary["one"] as? String where diagnose(),
// This line will print the file and line number
let two = dictionary["two"] as? String where diagnose(),
// This line will NOT be printed. So it is the one that failed.
let three = dictionary["three"] as? String where diagnose()
else {
// ...
}
Erica's write-up on this topic can be found here
Normally, a guard statement doesn't let you distinguish which of its conditions wasn't satisfied. Its purpose is that when the program executes past the guard statement, you know all the variables are non-nil. But it doesn't provide any values inside the guard/else body (you just know that the conditions weren't all satisfied).
That said, if all you want to do is print something when one of the steps returns nil, you could make use of the coalescing operator ?? to perform an extra action.
Make a generic function that prints a message and returns nil:
/// Prints a message and returns `nil`. Use this with `??`, e.g.:
///
/// guard let x = optionalValue ?? printAndFail("missing x") else {
/// // ...
/// }
func printAndFail<T>(message: String) -> T? {
print(message)
return nil
}
Then use this function as a "fallback" for each case. Since the ?? operator employs short-circuit evaluation, the right-hand side won't be executed unless the left-hand side has already returned nil.
guard
let keypath = dictionary["field"] as? String ?? printAndFail("missing keypath"),
let rule = dictionary["rule"] as? String ?? printAndFail("missing rule"),
let comparator = FormFieldDisplayRuleComparator(rawValue: rule) ?? printAndFail("missing comparator"),
let value = dictionary["value"] ?? printAndFail("missing value")
else
{
// ...
return
}
Very good question
I wish I had a good answer for that but I have not.
Let's begin
However let's take a look at the problem together. This is a simplified version of your function
func foo(dictionary:[String:AnyObject]) -> AnyObject? {
guard let
a = dictionary["a"] as? String,
b = dictionary[a] as? String,
c = dictionary[b] else {
return nil // I want to know more ☹️ !!
}
return c
}
Inside the else we don't know what did go wrong
First of all inside the else block we do NOT have access to the constants defined in the guard statement. This because the compiler doesn't know which one of the clauses did fail. So it does assume the worst case scenario where the first clause did fail.
Conclusion: we cannot write a "simple" check inside the else statement to understand what did not work.
Writing a complex check inside the else
Of course we could replicate inside the else the logic we put insito the guard statement to find out the clause which did fail but this boilerplate code is very ugly and not easy to maintain.
Beyond nil: throwing errors
So yes, we need to split the guard statement. However if we want a more detailed information about what did go wrong our foo function should no longer return a nil value to signal an error, it should throw an error instead.
So
enum AppError: ErrorType {
case MissingValueForKey(String)
}
func foo(dictionary:[String:AnyObject]) throws -> AnyObject {
guard let a = dictionary["a"] as? String else { throw AppError.MissingValueForKey("a") }
guard let b = dictionary[a] as? String else { throw AppError.MissingValueForKey(a) }
guard let c = dictionary[b] else { throw AppError.MissingValueForKey(b) }
return c
}
I am curious about what the community thinks about this.
One possible (non-idiomatic) workaround: make use of the where clause to track the success of each subsequent optional binding in the guard block
I see nothing wrong with splitting up your guard statements in separate guard blocks, in case you're interested in which guard statement that fails.
Out of a technical perspective, however, one alternative to separate guard blocks is to make use of a where clause (to each optional binding) to increment a counter each time an optional binding is successful. In case a binding fails, the value of the counter can be used to track for which binding this was. E.g.:
func foo(a: Int?, _ b: Int?) {
var i: Int = 1
guard let a = a where (i+=1) is (),
let b = b where (i+=1) is () else {
print("Failed at condition #\(i)")
return
}
}
foo(nil,1) // Failed at condition #1
foo(1,nil) // Failed at condition #2
Above we make use of the fact that the result of an assignment is the empty tuple (), whereas the side effect is the assignment to the lhs of the expression.
If you'd like to avoid introducing the mutable counter i prior the scope of guard clause, you could place the counter and the incrementing of it as a static class member, e.g.
class Foo {
static var i: Int = 1
static func reset() -> Bool { i = 1; return true }
static func success() -> Bool { i += 1; return true }
}
func foo(a: Int?, _ b: Int?) {
guard Foo.reset(),
let a = a where Foo.success(),
let b = b where Foo.success() else {
print("Failed at condition #\(Foo.i)")
return
}
}
foo(nil,1) // Failed at condition #1
foo(1,nil) // Failed at condition #2
Possibly a more natural approach is to propagate the value of the counter by letting the function throw an error:
class Foo { /* as above */ }
enum Bar: ErrorType {
case Baz(Int)
}
func foo(a: Int?, _ b: Int?) throws {
guard Foo.reset(),
let a = a where Foo.success(),
let b = b where Foo.success() else {
throw Bar.Baz(Foo.i)
}
// ...
}
do {
try foo(nil,1) // Baz error: failed at condition #1
// try foo(1,nil) // Baz error: failed at condition #2
} catch Bar.Baz(let num) {
print("Baz error: failed at condition #\(num)")
}
I should probably point out, however, that the above is probably closer to be categorized as a "hacky" construct, rather than an idiomatic one.
The simplest thing I can think of is to break out the statements into 4 sequential guard else statements, but that feels wrong.
In my personal opinion, the Swift way shouldn't require you to check whether the values are nil or not.
However, you could extend Optional to suit your needs:
extension Optional
{
public func testingForNil<T>(#noescape f: (Void -> T)) -> Optional
{
if self == nil
{
f()
}
return self
}
}
Allowing for:
guard let keypath = (dictionary["field"] as? String).testingForNil({ /* or else */ }),
let rule = (dictionary["rule"] as? String).testingForNil({ /* or else */ }),
let comparator = FormFieldDisplayRuleComparator(rawValue: rule).testingForNil({ /* or else */ }),
let value = dictionary["value"].testingForNil({ /* or else */ })
else
{
return nil
}
My two cents:
Since Swift doesn't let me add the where in the guard let, I came up with this solution instead:
func validate<T>(_ input: T?, file: String = #file, line: Int = #line) -> T? {
guard let input = input else {
print("Nil argument at \(file), line: \(line)")
return nil
}
return input
}
class Model {
let id: Int
let name: String
init?(id: Int?, name: String?) {
guard let id = validate(id),
let name = validate(name) else {
return nil
}
self.id = id
self.name = name
}
}
let t = Model(id: 0, name: "ok") // Not nil
let t2 = Model(id: 0, name: nil) // Nil
let t3 = Model(id: nil, name: "ok") // Nil
I think other answers here are better, but another approach is to define functions like this:
func checkAll<T1, T2, T3>(clauses: (T1?, T2?, T3?)) -> (T1, T2, T3)? {
guard let one = clauses.0 else {
print("1st clause is nil")
return nil
}
guard let two = clauses.1 else {
print("2nd clause is nil")
return nil
}
guard let three = clauses.2 else {
print("3rd clause is nil")
return nil
}
return (one, two, three)
}
And then use it like this
let a: Int? = 0
let b: Int? = nil
let c: Int? = 3
guard let (d, e, f) = checkAll((a, b, c)) else {
fatalError()
}
print("a: \(d)")
print("b: \(e)")
print("c: \(f)")
You could extend it to print the file & line number of the guard statement like other answers.
On the plus side, there isn't too much clutter at the call site, and you only get output for the failing cases. But since it uses tuples and you can't write a function that operates on arbitrary tuples, you would have to define a similar method for one parameter, two parameters etc up to some arity. It also breaks the visual relation between the clause and the variable it's being bound to, especially if the unwrapped clauses are long.
This code can be used for all guard and if logic tests like optional, bool and case tests. It prints a line of a logic test which failed.
class GuardLogger {
var lastGoodLine: Int
var lineWithError: Int { lastGoodLine + 1 }
var file: String
var function: String
init(file: String = #file, function: String = #function, line: Int = #line) {
self.lastGoodLine = line
self.file = file
self.function = function
}
func log(line: Int = #line) -> Bool {
lastGoodLine = line
return true
}
func print() {
Swift.print([file, function, String(lineWithError)].joined(separator: " "))
}
}
let testBoolTrue = true
let testBoolFalse = false
let guardLogger = GuardLogger()
guard
testBoolTrue, guardLogger.log(),
let testOptionalBoolTrue = Optional(testBoolTrue), guardLogger.log(),
let selfIsViewController = self as? UIViewController, guardLogger.log(),
testBoolTrue == false, guardLogger.log() // this fails
else {
print(guardLogger.lastGoodLine)
fatalError()
}

Check string for nil & empty

Is there a way to check strings for nil and "" in Swift? In Rails, I can use blank() to check.
I currently have this, but it seems overkill:
if stringA? != nil {
if !stringA!.isEmpty {
...blah blah
}
}
If you're dealing with optional Strings, this works:
(string ?? "").isEmpty
The ?? nil coalescing operator returns the left side if it's non-nil, otherwise it returns the right side.
You can also use it like this to return a default value:
(string ?? "").isEmpty ? "Default" : string!
You could perhaps use the if-let-where clause:
Swift 3:
if let string = string, !string.isEmpty {
/* string is not blank */
}
Swift 2:
if let string = string where !string.isEmpty {
/* string is not blank */
}
With Swift 5, you can implement an Optional extension for String type with a boolean property that returns if an optional string is empty or has no value:
extension Optional where Wrapped == String {
var isEmptyOrNil: Bool {
return self?.isEmpty ?? true
}
}
However, String implements isEmpty property by conforming to protocol Collection. Therefore we can replace the previous code's generic constraint (Wrapped == String) with a broader one (Wrapped: Collection) so that Array, Dictionary and Set also benefit our new isEmptyOrNil property:
extension Optional where Wrapped: Collection {
var isEmptyOrNil: Bool {
return self?.isEmpty ?? true
}
}
Usage with Strings:
let optionalString: String? = nil
print(optionalString.isEmptyOrNil) // prints: true
let optionalString: String? = ""
print(optionalString.isEmptyOrNil) // prints: true
let optionalString: String? = "Hello"
print(optionalString.isEmptyOrNil) // prints: false
Usage with Arrays:
let optionalArray: Array<Int>? = nil
print(optionalArray.isEmptyOrNil) // prints: true
let optionalArray: Array<Int>? = []
print(optionalArray.isEmptyOrNil) // prints: true
let optionalArray: Array<Int>? = [10, 22, 3]
print(optionalArray.isEmptyOrNil) // prints: false
Sources:
swiftbysundell.com - Extending optionals in Swift
objc.io - Swift Tip: Non-Empty Collections
Using the guard statement
I was using Swift for a while before I learned about the guard statement. Now I am a big fan. It is used similarly to the if statement, but it allows for early return and just makes for much cleaner code in general.
To use guard when checking to make sure that a string is neither nil nor empty, you can do the following:
let myOptionalString: String? = nil
guard let myString = myOptionalString, !myString.isEmpty else {
print("String is nil or empty.")
return // or break, continue, throw
}
/// myString is neither nil nor empty (if this point is reached)
print(myString)
This unwraps the optional string and checks that it isn't empty all at once. If it is nil (or empty), then you return from your function (or loop) immediately and everything after it is ignored. But if the guard statement passes, then you can safely use your unwrapped string.
See Also
Statements documentation
The Guard Statement in Swift 2
If you are using Swift 2, here is an example my colleague came up with, which adds isNilOrEmpty property on optional Strings:
protocol OptionalString {}
extension String: OptionalString {}
extension Optional where Wrapped: OptionalString {
var isNilOrEmpty: Bool {
return ((self as? String) ?? "").isEmpty
}
}
You can then use isNilOrEmpty on the optional string itself
func testNilOrEmpty() {
let nilString:String? = nil
XCTAssertTrue(nilString.isNilOrEmpty)
let emptyString:String? = ""
XCTAssertTrue(emptyString.isNilOrEmpty)
let someText:String? = "lorem"
XCTAssertFalse(someText.isNilOrEmpty)
}
var str: String? = nil
if str?.isEmpty ?? true {
print("str is nil or empty")
}
str = ""
if str?.isEmpty ?? true {
print("str is nil or empty")
}
I know there are a lot of answers to this question, but none of them seems to be as convenient as this (in my opinion) to validate UITextField data, which is one of the most common cases for using it:
extension Optional where Wrapped == String {
var isNilOrEmpty: Bool {
return self?.trimmingCharacters(in: .whitespaces).isEmpty ?? true
}
}
You can just use
textField.text.isNilOrEmpty
You can also skip the .trimmingCharacters(in:.whitespaces) if you don't consider whitespaces as an empty string or use it for more complex input tests like
var isValidInput: Bool {
return !isNilOrEmpty && self!.trimmingCharacters(in: .whitespaces).characters.count >= MIN_CHARS
}
If you want to access the string as a non-optional, you should use Ryan's Answer, but if you only care about the non-emptiness of the string, my preferred shorthand for this is
if stringA?.isEmpty == false {
...blah blah
}
Since == works fine with optional booleans, I think this leaves the code readable without obscuring the original intention.
If you want to check the opposite: if the string is nil or "", I prefer to check both cases explicitly to show the correct intention:
if stringA == nil || stringA?.isEmpty == true {
...blah blah
}
I would recommend.
if stringA.map(isEmpty) == false {
println("blah blah")
}
map applies the function argument if the optional is .Some.
The playground capture also shows another possibility with the new Swift 1.2 if let optional binding.
SWIFT 3
extension Optional where Wrapped == String {
/// Checks to see whether the optional string is nil or empty ("")
public var isNilOrEmpty: Bool {
if let text = self, !text.isEmpty { return false }
return true
}
}
Use like this on optional string:
if myString.isNilOrEmpty { print("Crap, how'd this happen?") }
Swift 3
For check Empty String best way
if !string.isEmpty{
// do stuff
}
Swift 3 solution
Use the optional unwrapped value and check against the boolean.
if (string?.isempty == true) {
// Perform action
}
You should do something like this:
if !(string?.isEmpty ?? true) { //Not nil nor empty }
Nil coalescing operator checks if the optional is not nil, in case it is not nil it then checks its property, in this case isEmpty. Because this optional can be nil you provide a default value which will be used when your optional is nil.
Based on this Medium post, with a little tweak for Swift 5, I got to this code that worked.
if let stringA, !stringA.isEmpty {
...blah blah
}
Although I understand the benefits of creating an extension, I thought it might help someone needing just for a small component / package.
You can create your own custom function, if that is something you expect to do a lot.
func isBlank (optionalString :String?) -> Bool {
if let string = optionalString {
return string.isEmpty
} else {
return true
}
}
var optionalString :String? = nil
if isBlank(optionalString) {
println("here")
}
else {
println("there")
}
Create a String class extension:
extension String
{ // returns false if passed string is nil or empty
static func isNilOrEmpty(_ string:String?) -> Bool
{ if string == nil { return true }
return string!.isEmpty
}
}// extension: String
Notice this will return TRUE if the string contains one or more blanks. To treat blank string as "empty", use...
return string!.trimmingCharacters(in: CharacterSet.whitespaces).isEmpty
... instead. This requires Foundation.
Use it thus...
if String.isNilOrEmpty("hello world") == true
{ print("it's a string!")
}
Swift 3
This works well to check if the string is really empty. Because isEmpty returns true when there's a whitespace.
extension String {
func isEmptyAndContainsNoWhitespace() -> Bool {
guard self.isEmpty, self.trimmingCharacters(in: .whitespaces).isEmpty
else {
return false
}
return true
}
}
Examples:
let myString = "My String"
myString.isEmptyAndContainsNoWhitespace() // returns false
let myString = ""
myString.isEmptyAndContainsNoWhitespace() // returns true
let myString = " "
myString.isEmptyAndContainsNoWhitespace() // returns false
Using isEmpty
"Hello".isEmpty // false
"".isEmpty // true
Using allSatisfy
extension String {
var isBlank: Bool {
return allSatisfy({ $0.isWhitespace })
}
}
"Hello".isBlank // false
"".isBlank // true
Using optional String
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
var title: String? = nil
title.isBlank // true
title = ""
title.isBlank // true
Reference : https://useyourloaf.com/blog/empty-strings-in-swift/
This is a general solution for all types that conform to the Collection protocol, which includes String:
extension Optional where Wrapped: Collection {
var isNilOrEmpty: Bool {
self?.isEmpty ?? true
}
}
When dealing with passing values from local db to server and vice versa, I was having too much trouble with ?'s and !'s and what not.
So I made a Swift3.0 utility to handle null cases and i can almost totally avoid ?'s and !'s in the code.
func str(_ string: String?) -> String {
return (string != nil ? string! : "")
}
Ex:-
Before :
let myDictionary: [String: String] =
["title": (dbObject?.title != nil ? dbObject?.title! : "")]
After :
let myDictionary: [String: String] =
["title": str(dbObject.title)]
and when its required to check for a valid string,
if !str(dbObject.title).isEmpty {
//do stuff
}
This saved me having to go through the trouble of adding and removing numerous ?'s and !'s after writing code that reasonably make sense.
Use the ternary operator (also known as the conditional operator, C++ forever!):
if stringA != nil ? stringA!.isEmpty == false : false { /* ... */ }
The stringA! force-unwrapping happens only when stringA != nil, so it is safe. The == false verbosity is somewhat more readable than yet another exclamation mark in !(stringA!.isEmpty).
I personally prefer a slightly different form:
if stringA == nil ? false : stringA!.isEmpty == false { /* ... */ }
In the statement above, it is immediately very clear that the entire if block does not execute when a variable is nil.
helpful when getting value from UITextField and checking for nil & empty string
#IBOutlet weak var myTextField: UITextField!
Heres your function (when you tap on a button) that gets string from UITextField and does some other stuff
#IBAction func getStringFrom_myTextField(_ sender: Any) {
guard let string = myTextField.text, !(myTextField.text?.isEmpty)! else { return }
//use "string" to do your stuff.
}
This will take care of nil value as well as empty string.
It worked perfectly well for me.
Swift 5.6 - Xcode 13
extension Optional where Wrapped: Collection {
var isEmptyOrNil: Bool {
guard let self = self else { return true }
return self.isEmpty
}
}
Usage:
var name: String?
if name.isEmptyOrNil {
///true
}
name = "John Peter"
guard !name.isEmptyOrNil else { return }
/// Name is not empty
you can use this func
class func stringIsNilOrEmpty(aString: String) -> Bool { return (aString).isEmpty }