Satisfy one of multiple constraints in an if let construct - swift

I want to satisfy multiple constraints in an if let construct. I know we can use a "," (comma) to unwrap multiple values but they both have to be successfully unwrapped.
For example :
var str: String? = "Hello"
var x: Int? = 10
if let intValue = x, stringValue = str {
// do something here.
} else {
}
I want if one of the conditions is successfully unwrapped, then a block will execute.
for example:
class CustomClass {
var x = 10
static func someValue() -> String? {
return "some"
}
}
var flag: Bool? = false
var x: Int? = 10
var status: String
in this i want if either customclass someValue function or x value any of successfully unwrapped and flag is true then code executes

You can create a tuple and use a switch like so:
switch (str, x) {
case (.Some,.Some):
print("Both have values")
case (.Some, nil):
print("String has a value")
case (nil, .Some):
print("Int has a value")
case (nil, nil):
print("Neither has a value")
}

Related

Creating an enum instance

suppose I have
enum Example {
case one(string: String)
case two(string: String)
}
and now I have
let x = Example.one(string: "Hello")
The question:
let y = ?
how do I create another instance of the same enum in e, so that I end up with y == .one("World"))
The types of enum cases with associated values are closures with arguments corresponding to the type of the associated values, and with a return corresponding to the type of the enum (with the value of the return being the specific case). I.e., for your example above, the type of Example.one as well as Example.two is (String) -> Example, where the closures expressed by these two cases yield different results; instances of .one(...) and .two(...), respectively.
Hence, instead of writing your own method to "clone" a given case, you could simply have a computed property which returns the already existing closures Example.one and Example.two (if self is one or two, respectively), which can subsequently be invoked upon a String argument to construct a new Example instance (with value .one or .two; along with the supplied associated String value).
E.g.:
enum Example {
case one(string: String) // type: (String) -> Example
case two(string: String) // type: (String) -> Example
var caseClosure: (String) -> Example {
switch self {
case .one: return Example.one
case .two: return Example.two
}
}
}
let x = Example.one(string: "Hello") // .one("Hello")
let y = x.caseClosure("World") // .one("World")
However, since all the cases in your example are closures of the same type, namely (String) -> Example (i.e. have the same number and type(s) of associated values), you might as well, as already proposed in a comment by #Hamish, wrap an enum with no associated values in a struct along with the always-String "associated value" a separate member of the struct. E.g. expanding Hamish's example with some initializers:
struct S {
enum E {
case one
case two
}
var e: E
var string: String // Since "associated value" is always the same type
init(_ e: E, string: String) {
self.e = e
self.string = string
}
init(from s: S, string: String) {
self.e = s.e
self.string = string
}
}
let x = S(.one, string: "Hello")
let y = S(from: x, string: "World")
let z = S(x.e, string: "World")
You do that by calling the Initializer exactly like you did for x:
enum Example {
case one(string: String)
case two(string: String)
}
let x = Example.one(string: "Hello")
print(x) // Prints one("Hello")
let y = Example.one(string: "World")
print(y) // Prints one("World")
Also, The , in your enum declaration is wrong and has to be removed.
UPDATE:
The comment explained the question in more detail, so here is my updated answer:
An elegant way to solve this is to use a function on the original enum type Example.
enum Example {
case one(string: String)
case two(string: String)
func cloneWith(string: String) -> Example {
switch self {
case .one:
return .one(string: string)
case .two:
return .two(string: string)
}
}
}
let x = Example.one(string: "Hello")
print(x) // Prints one("Hello")
let y = x.cloneWith(string: "World")
print(y) // Prints one("World")

Match optional in switch statement

Given a non-optional value, how can I match against an optional in a switch statement?
For example:
let test = "some string"
let x: String? = nil
let y: String? = "some string"
let z: String? = "another string"
switch test {
case x:
print(x)
case y:
print(y)
case z:
print(z)
default: break
}
results in:
Expression pattern of type 'String?' cannot match values of type 'String'
for each case...
I've read the swift docs on patterns and switch but I can't seem to find a way of making this work.
I know I can work around this, but there must be a way of making this work...
Edit
As requested, here is my actual use case. Note all text fields are optional...
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// TODO: Replace with switch if possible
// switch textField {
// case nameTextField:
// usernameTextField?.becomeFirstResponder()
// case usernameTextField:
// dateOfBirthTextField?.becomeFirstResponder()
// case dateOfBirthTextField:
// phoneTextField?.becomeFirstResponder()
// case phoneTextField:
// phoneTextField?.resignFirstResponder()
// default: break
// }
if textField == nameTextField {
usernameTextField?.becomeFirstResponder()
} else if textField == usernameTextField {
dateOfBirthTextField?.becomeFirstResponder()
} else if textField == dateOfBirthTextField {
phoneTextField?.becomeFirstResponder()
} else if textField == phoneTextField {
phoneTextField?.resignFirstResponder()
}
return false
}
Swift 4.0
You can check with optional case as like below.
Hope this will help you.
let test = "some string"
let x: String? = nil
let y: String? = "some string"
let z: String? = "another string"
switch test {
case let val where val == x:
print(x)
case let val where val == y:
print(y)
case let val where val == z:
print(z)
default:
break
}
For your actual use-case: I would create an array of all non-nil
text fields. Then you can lookup the current text field in that
array and make the next one in the list the first responder:
let fields = [nameTextField, usernameTextField, dateOfBirthTextField, phoneTextField]
.flatMap { $0 }
if let idx = fields.index(of: textField), idx + 1 < fields.count {
fields[idx + 1].becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
This is less error-prone and can easily be modified if the number or
order of the text fields changes.

Given a Swift `Any` type can I determine if it's an `Optional`?

Given a value of type Any is it possible to check and see if it's an Optional or not?
This code doesn't work because instead of checking to see if it's optional or not it's trying to cast it, and it passes
let a: Any = "5"
switch a {
case let optional as Optional<Any>:
if case .some(let value) = optional {
print("wrapped value of `\(a)` is `\(value)`")
}
default:
print("\(a) is not an optional")
}
Base on #dfri's solution
private func isOptional(input: Any) -> Bool {
let mirror = Mirror(reflecting: input)
let style = mirror.displayStyle
switch style {
case .some(.optional):
return true
default:
return false
}
}
You can use runtime introspection using Mirror:
let foo: String? = "foo"
let bar: String = "bar"
var a: Any = foo
// if wrapping an optional, the reflection of the value has
// a displaystyle "optional"
if let displayStyle = Mirror.init(reflecting: a).displayStyle {
print(displayStyle) // optional
}
// for a non-optional fundamental native type: no displaystyle
a = bar
if let displayStyle = Mirror.init(reflecting: a).displayStyle {
print(displayStyle)
} // prints nothing
Optional/non-optional example where the underlying type is user-defined (non native):
struct Foo {}
let foo: Foo? = Foo()
let bar: Foo = Foo()
var a: Any = foo
// if wrapping an optional, the reflection of the value has
// a displaystyle "optional"
if let displayStyle = Mirror(reflecting: a).displayStyle {
print(displayStyle) // optional
}
// for a non-optional non-fundamental type:
a = bar
if let displayStyle = Mirror(reflecting: a).displayStyle {
print(displayStyle) // struct
}
If you don't want need to use the binded displayStyle variable (e.g. for printing) but simply want check whether the wrapped value is any kind of optional, you can add a boolean clause to the if statement that holds the optional binding of the displayStyle case,
if let displayStyle = Mirror(reflecting: a).displayStyle,
displayStyle == .optional {
// is an optional ...
}
... or remove the binding entirely in favour of a single conditional expression using the nil coalescing operator (??)
if Mirror(reflecting: a).displayStyle ?? .class == .optional {
// is an optional
}
Note however that for all the methods above, this simply tells you as dev whether the type wrapped by the Any instance is optional or not: Swifts typing system still knows nothing of the sort.
let a: Any = "5"
let b: Any? = "5"
if type(of: a) == Optional<Any>.self {
print("a is optional")
} else {
print("a is not optional")
}
if type(of: b) == Optional<Any>.self {
print("b is optional")
} else {
print("b is not optional")
}
/*
a is not optional
b is optional
*/
another example ...
let a: Any = 5
let b: Any? = 5
let c: Any = "5"
let d: Any? = "5"
let arr: [Any] = [a,b as Any,c,d as Any]
arr.forEach { (x) in
print(type(of: x))
}
/*
Int
Optional<Any>
String
Optional<Any>
*/

Pattern match and conditionally bind in a single Switch statement

Is there a way to write this if/else if/else ladder as a switch statement?
let x: Any = "123"
if let s = x as? String {
useString(s)
}
else if let i = x as? Int {
useInt(i)
}
else if let b = x as? Bool {
useBool(b)
}
else {
fatalError()
}
Here's my attempt:
switch x {
case let s where s is String: useString(s)
case let i where i is Int: useInt(i)
case let b where b is Bool: useBool(b)
default: fatalError()
}
It successfully chooses the right path, but s/i/b are still of type Any. The is check doesn't have any effect in casting them. This forces me to force cast with as! before usage.
Is there a way to switch on the type, and bind it to a name, all in one switch statement?
Sure, you can use the conditional casting pattern case let x as Type:
let x: Any = "123"
switch x {
case let s as String:
print(s) //use s
case let i as Int:
print(i) //use i
case let b as Bool:
print(b) //use b
default:
fatalError()
}

Nicer syntax for ternary with a let?

Is there a nicer way to do the assignment to DEF in the following example? I want to convert type A to Type B, but still preserve the nil possibility whenever I can.
Can't seem to stumble into a better way of doing this, however. Suggestions?
class ABC {
var DEF: Int?
func X (someValue: Int8?) {
DEF = someValue != nil ? Int(someValue) : nil
}
}
Swift 1:
class ABC {
var DEF: Int?
func X (someValue: Int8?) {
DEF = someValue.map{Int($0)}
}
}
Swift 2:
class ABC {
var DEF: Int?
func X (someValue: Int8?) {
DEF = someValue.map(Int.init)
}
}
map() takes an optional, unwraps it, and applies a function to it. If the optional resolves to nil, map() returns nil.
You are describing optional map:
var i: Int? = 2
let j = i.map { $0 * 2 } // j = .Some(4)
i = nil
let k = i.map { $0 * 2 } // k = nil
Think of this map like array or other collection map, where optionals are collections that have either zero (nil) or one (non-nil) element.
Note, if the operation you want to perform itself returns an optional, you need flatMap to avoid getting a double-optional:
let s: String? = "2"
let i = s.map { Int($0) } // i will be an Int??
let j = s.flatMap { Int($0) } // flattens to Int?