I'm trying to extend Swift's Optional type with default values. Providing empty values in API requests should raise an exception. I've done this for the String type, but I can't achieve the same result with the Integer type:
extension Optional where Wrapped == String {
var unwrappedValue: String {
get {
switch self {
case .some(let value):
return value
case .none:
return ""
}
}
}
}
The Integer version is throwing the following Error:
Protocol 'Integer' can only be used as a generic constraint because it
has Self or associated type requirements
extension Optional where Wrapped == Integer {
var unwrappedValue: Integer {
get {
switch self {
case .some(let value):
return value
case .none:
return 0
}
}
}
}
If you use this for a lot of Types you might want to consider the following addition to the answer of Leo Dabus:
protocol Defaultable {
static var defaultValue: Self { get }
}
extension Optional where Wrapped: Defaultable {
var unwrappedValue: Wrapped { return self ?? Wrapped.defaultValue }
}
This way you can extend your types very easily:
extension Int: Defaultable {
static var defaultValue: Int { return 0 }
}
extension String: Defaultable {
static var defaultValue: String { return "" }
}
extension Array: Defaultable {
static var defaultValue: Array<Element> { return [] }
}
And usage goes like this:
let optionalInt: Int? = 10 // Optional(10)
let unwrappedInt = optionalInt.unwrappedValue // 10
let optionalString: String? = "Hello" // Optional("Hello")
let unwrappedString = optionalString.unwrappedValue // "Hello"
let optionalArray: [Int]? = nil // nil
let unwrappedArray = optionalArray.unwrappedValue // []
You just need to return Wrapped instead of Integer
extension Optional where Wrapped: Integer {
var unwrappedValue: Wrapped {
switch self {
case .some(let value):
return value
case .none:
return 0
}
}
}
or simply
extension Optional where Wrapped: Integer {
var safelyUnwrapped: Wrapped { return self ?? 0 }
}
let optionalInt = Int("10")
let unwrappedValue = optionalInt.safelyUnwrapped // 10
You can also achieve using below code:
extension Optional {
func defaultValue(_ val: Wrapped) -> Wrapped { return self ?? val }
}
var str: String?
str.defaultValue("User")
var a: Int?
a.defaultValue(2)
This will work for both data types.
Related
I am getting data from different sources, the variable could be a number or a string of number. How do I make sure that "(number as? NSString)" or "(number as? NSNumber)" always success? Something similar to Java optInt, which will never fail even if the number is a String. See example below:
func testNumber()
{
var number = 123
guard let a = (number as? NSNumber)?.intValue else { print("1");return; }
}
func testNumberString()
{
var number = "123"
guard let a = (number as? NSNumber)?.intValue else { print("2");return; } // this failed.
}
func testNumberToString()
{
var number = 123
guard let a = (number as? NSString)?.intValue else { print("2");return; } // this sometimes failed too depend on datasource.
}
As I understand from your question, you want an integer value at the end, no matter if the input type is string or integer.
You can achieve this by using ExpressibleByStringLiteral.
Here is the demo
extension Int: ExpressibleByStringLiteral {
public typealias StringLiteralType = String
public init(stringLiteral value: StringLiteralType) {
self = Int(value) ?? 0
}
}
This Int extension allows you to accept string value as Int and return int value. If it did not convert it will give you 0 by default.
Example
func testInt() {
let numberOne: Int = "5656"
let numberTwo: Int = 1234
print(numberOne)
print(numberTwo)
}
Or another way is to create your own ExpressibleByStringLiteral, which helps you to give default value as you want.
struct StringInt: ExpressibleByStringLiteral {
var value: Int?
init(stringLiteral value: String) {
self.value = Int("\(value)")
}
func wrapped(with defaultValue: Int) -> Int {
return self.value ?? defaultValue
}
}
Example
func testInt() {
var numberThree: StringInt = "5656"
print(numberThree.value as Any) // with nil or optional value
numberThree = "asf"
print(numberThree.wrapped(with: 15)) // with default value
/**
Output
Optional(5656)
15
*/
}
I have an enum with associated value ConfigurationValue that gets stored in a map. I have type specific getters for each possible enum value.
How do I minimize the code duplication between these getters
enum ConfigurationValue {
case bool(Bool)
case int(Int)
case string(String)
}
var map: [T:ConfigurationValue] = [:]
public mutating func set(key: T, _ value: Bool) {
map[key] = .bool(value)
}
public mutating func set(key: T, _ value: Int) {
map[key] = .int(value)
}
public mutating func set(key: T, _ value: String) {
map[key] = .string(value)
}
private func getValue(key: T) -> ConfigurationValue? {
return map[key]
}
public func get(key: T) -> Bool? {
guard let value = getValue(key: key),
case .bool(let innerValue) = value else {
return nil
}
return innerValue
}
public func get(key: T) -> Int? {
guard let value = getValue(key: key),
case .int(let innerValue) = value else {
return nil
}
return innerValue
}
public func get(key: T) -> String? {
guard let value = getValue(key: key),
case .string(let innerValue) = value else {
return nil
}
return innerValue
}
I would not use protocols but instead I would add two methods in ConfigurationValue the first to create a configuration value and the other to get the inner value of a case.
enum ConfigurationValue {
case bool(Bool)
case int(Int)
case string(String)
static func with<Value>(value: Value?) -> ConfigurationValue? {
if let value = value as? Bool {
return .bool(value)
}
if let value = value as? Int {
return .int(value)
}
if let value = value as? String {
return .string(value)
}
return nil
}
func get<Value>(ofType type: Value.Type = Value.self) -> Value? {
switch self {
case .bool(let bool):
return bool as? Value
case .int(let int):
return int as? Value
case .string(let string):
return string as? Value
}
}
}
let boolValue: Bool? = ConfigurationValue.bool(false).get() // Optional(false)
let intValue: Int? = ConfigurationValue.bool(false).get() // nil
let stringValue: String? = ConfigurationValue.bool(false).get() // nil
let boolConfiguration: ConfigurationValue? = .with(value: true) // bool(true)
let intConfiguration: ConfigurationValue? = .with(value: 42) // int(42)
let stringConfiguration: ConfigurationValue? = .with(value: "42") // string("42")
let doubleConfiguration: ConfigurationValue? = .with(value: 42.0) // nil
Now you can avoid boilerplate, let's say you have a struct Foo:
struct Foo<T: Hashable> {
var map: [T:ConfigurationValue] = [:]
mutating func set<Value>(_ value: Value?, forKey key: T) {
map[key] = .with(value: value)
}
func get<Value>(key: T) -> Value? {
guard let value = map[key] else {
return nil
}
return value.get()
}
}
var map: [String:ConfigurationValue] = [
"bool": .bool(false),
"int": .int(0),
"string": .string("string")
]
var bar = Foo(map: map)
var bool: Bool? = bar.get(key: "bool") // Optional(false)
var int: Int? = bar.get(key: "int") // 0
var string: String? = bar.get(key: "string") // string
bar.set(true, forKey: "bool")
bool = bar.get(key: "bool") // Optional(true)
bar.set(42, forKey: "int")
int = bar.get(key: "int") // 42
bar.set("Hello World!", forKey: "string")
string = bar.get(key: "string") // Hello World!
It doesn't seem like an enum is the right tool for the job here since you can get the same usefulness out of just casting the values (though admittedly you wouldn't get the benefit of exhaustive switch errors). If you're wanting to utilize generics to cut down on some of this duplication, I'd go with a wrapper around the map like so:
protocol Configurable {}
extension Int: Configurable {}
extension Bool: Configurable {}
extension String: Configurable {}
class ConfigurationMap<Key: Hashable> {
private var map = [Key: Configurable]()
func getValue(at key: Key) -> Configurable? {
return map[key]
}
func setValue(_ value: Configurable, at key: Key) {
map[key] = value
}
}
Here Key would replace your T generic. To incorporate more data types, just extend the type that you want to use to be Configurable. The ConfigurationMap can also be a struct if you don't mind the mutating methods.
In Swift, this is not called a "map", but instead, a "dictionary". Type restriction can be achieved with a protocol, and explicit typing for retrieval.
public protocol ConfigurationValue { }
extension Int: ConfigurationValue { }
extension Bool: ConfigurationValue { }
extension String: ConfigurationValue { }
public struct ConfigurationDictionary<Key: Hashable> {
private var dictionary: [Key: ConfigurationValue] = [:]
}
public extension ConfigurationDictionary {
subscript<Value: ConfigurationValue>(key: Key) -> Value? {
get { dictionary[key] as? Value }
set { dictionary[key] = newValue }
}
}
var configurationDictionary = ConfigurationDictionary<String>()
configurationDictionary["i"] = 1
configurationDictionary["i"] as Int? // 1
configurationDictionary["i"] as Bool? // nil
configurationDictionary["b"] = true
let b: Bool? = configurationDictionary["b"] // true
let i: Int? = configurationDictionary["b"] // nil
I have some generic code that allows me to read and write various types to the defaults system, e.g. value getters and setters:
var value : T {
get {
if T.self == Int.self {
return UserDefaults.standard.integer(forKey: storageKey) as! T
} else if T.self == Double.self {
return UserDefaults.standard.double(forKey: storageKey) as! T
} else if T.self == Float.self {
return UserDefaults.standard.float(forKey: storageKey) as! T
} else if T.self == Bool.self {
return UserDefaults.standard.bool(forKey: storageKey) as! T
} else if T.self == String.self {
return UserDefaults.standard.string(forKey: storageKey) as! T
} else {
return UserDefaults.standard.value(forKey: self.storageKey) as! T
}
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
UserDefaults.standard.synchronize()
}
}
Now I want to add my own enum types to this mechanism by making them RawRepresentable<Int>, e.g.
enum Direction : Int, RawRepresentable {
case left = 0
case right = 1
}
Unfortunately, I can neither find the magic incantation to test whether T conforms to the RawRepresentable protocol, nor can I cast T to the RawRepresentable protocol, because no matter what I try, I always end up with a Protocol 'RawRepresentable' can only be used as a generic constraint because it has Self or associated type requirements.
I have tried every where and as incantation until I have started doubting that it can be done at all!?
I'm in Swift 5 and the goal is to create new instance by invoking CustomType(rawValue:) and getting the Int value by calling myValue.rawValue.
As #vadian said, all those type checks can be replaced be a single call to UserDefaults.standard.object() and conditional casting. Also the type of the value property needs to be an optional to handle the case where the property is not set (or not of the correct type):
struct DefaultKey<T> {
let storageKey: String
var value: T? {
get {
return UserDefaults.standard.object(forKey: storageKey) as? T
}
nonmutating set {
UserDefaults.standard.set(newValue, forKey: storageKey)
}
}
}
And then you can define a constrained extension method where you specialize the computed property for the case of RawRepresentable types:
extension DefaultKey where T: RawRepresentable {
var value: T? {
get {
if let rawValue = UserDefaults.standard.object(forKey: storageKey) as? T.RawValue {
return T(rawValue: rawValue)
}
return nil
}
nonmutating set {
UserDefaults.standard.set(newValue?.rawValue, forKey: storageKey)
}
}
}
Example usage:
enum Direction : Int {
case left = 0
case right = 1
}
let key1 = DefaultKey<Int>(storageKey: "foo")
key1.value = 123
let key2 = DefaultKey<Direction>(storageKey: "bar")
key2.value = .right
print(key1.value as Any) // Optional(123)
print(key2.value as Any) // Optional(Direction.right)
Note that this can still crash if used with non-property-list types. To be on the safe side, you would have to restrict the extensions to types which are known to be user defaults storable (integers, floats, strings, ...):
protocol UserDefaultsStorable {}
extension Int: UserDefaultsStorable {}
extension Float: UserDefaultsStorable {}
// ...
struct DefaultKey<T> {
let storageKey: String
}
extension DefaultKey where T: UserDefaultsStorable { .. }
extension DefaultKey where T: RawRepresentable, T.RawValue: UserDefaultsStorable { ... }
Consider the following:
struct MiniString {
private(set) var value: String
init(_ value: String) {
if value.count < 17 {
self.value = value
} else {
selfDeleteSomehow()
}
}
}
Elsewhere this could be instantiated thus:
var ms: MiniString? = MiniString("This string is too long to be accepted")
print(ms) // prints 'nil'
Context: my specific use-case is for a func declaration in a protocol that would return a Double between 0.0 and 1.0, but no higher or lower, something like:
protocol DoubleBetweenZeroAndOneProtocol {
func getResult() -> DoubleBetweenZeroAndOne
}
You could use a failable initializer:
struct MiniString {
var value: String { return value_ }
private let value_: String
init?(_ seedValue: String) {
if seedValue.count < 17 {
value_ = seedValue
} else {
return nil
}
}
}
How can you check if a type is Optional in Swift?
Say I have a variable of type PartialKeyPath where:
struct Foo {
let bar: String
let baz: String?
}
typealias Property<Root> = (key: PartialKeyPath<Root>, value: Any?)
typealias Properties<Root> = [Property<Root>]
Now say I iterate thru an instance of Properties:
properties.forEach { prop in
let valueType1 = type(of: prop.key).valueType
let valueType2 = type(of: value)
...
How can I check here whether valueType1 is Optional<valueType2>, or whether it is Optional of any other flavor for that matter?
So far the only way I’ve found is really ugly...
Using a similar approach to Optional field type doesn't conform protocol in Swift 3, you could define a 'dummy protocol' for Optional and use this to get the wrapped metatype:
protocol OptionalProtocol {
// the metatype value for the wrapped type.
static var wrappedType: Any.Type { get }
}
extension Optional : OptionalProtocol {
static var wrappedType: Any.Type { return Wrapped.self }
}
If you just want to know a type is an optional:
func isOptionalType(_ type: Any.Type) -> Bool {
return type is OptionalProtocol.Type
}
print(isOptionalType(String.self)) // false
print(isOptionalType(String?.self)) // true
If you want to check if one metatype is the 'optional version' of another metatype:
struct Foo {
let bar: String
let baz: String?
}
struct Property<Root> {
var key: PartialKeyPath<Root>
var value: Any
}
let properties = [Property(key: \Foo.baz, value: "hello")]
/// Attempt to get the `Wrapped` metatype from a metatype of an
/// `Optional<Wrapped>`. If not an `Optional`, will return `nil`.
func wrappedTypeFromOptionalType(_ type: Any.Type) -> Any.Type? {
return (type as? OptionalProtocol.Type)?.wrappedType
}
for property in properties {
let valueType1 = type(of: property.key).valueType
let valueType2 = type(of: property.value)
if wrappedTypeFromOptionalType(valueType1) == valueType2 {
print("\(valueType1) == Optional<\(valueType2)>")
}
}
// Optional<String> == Optional<String>
However there's almost certainly a better way to do whatever you're trying to do here with the key paths.
could you use a mirror reflecting Any and check displayStyle is optional?.
func isOptional(any:Any) -> Bool {
let mirror = Mirror(reflecting: any)
if mirror.displayStyle == .Optional {
return true
} else {
return false
}
}
More on mirror display style:
https://developer.apple.com/documentation/swift/mirror.displaystyle
This is a hacky but working solution:
func isOptional(_ type: Any.Type) -> Bool {
let typeName = String(describing: type)
return typeName.hasPrefix("Optional<")
}
Test:
let t1 = Int?.self
let t2 = Bool.self
print(isOptional(t1))
// true
print(isOptional(t2))
// false
A tweak of #kelin’s answer:
postfix operator ...?!
postfix func ...?!<T>(_ instance: T) -> Bool {
let subject = "\(Mirror(reflecting: instance).subjectType)"
return !subject.hasPrefix("Optional")
}
And in the vein of #Ercell0’s answer is this superior method:
func isOptional<T>(_ instance: T) -> Bool {
guard let displayStyle = Mirror(reflecting: instance).displayStyle
else { return false }
return displayStyle == .optional
}