Enum structure creation - swift

I'm working on a model definition with Swift 3.
I have two simple enum :
enum CompanyField: String {
case id
case name
}
enum UserField: String {
case email
case id
case id_company
}
When using collections I would to like to conform to a generic type. Something like Field e.g:
let fields: [Field : String] = [UserField.id : "1", CompanyField.name : "A name"]
or
let fields: [Field] = [UserField.id, CompanyField.name]
I was trying to create a Field protocol but without success. (e.g: enum UserField: Field {})
Is there any solution to have my two enum conforming to one single custom type ?

This can give you a flexible way to express you enums conform a custom domain protocol and still be used as dictionary and array elements. but again, this avoid to mix different enum types as dict key:
func map<K,V>(forFields fields: (K,V)...) -> [K:V] where K : Hashable{
var dict = [K:V]()
fields.forEach { (key, value) in
dict[key as K] = value
}
return dict
}
map(forFields: (UserField.email, "email"), (UserField.id,"id"))

Related

Get coding value for a Codable value in Swift

I am working on a Swift service that stores codable types in JSON. The type also defines a nested CodingKeys enum to define the property names when coded to JSON. For example, I might have a type that looks like this:
struct MyType : Codable {
let myIntProperty: Int
let myStringProperty: String
enum CodingKeys: String, CodingKey {
case myIntProperty = "int_property"
case myStringProperty = "string_property"
}
}
Now I have a function that wants to operate on one of these properties, as specified by a key path to that property. Using the type from the example, I want a function that can be called like this:
let result = myFunc(usingProperty: \MyType.myIntProperty)
My function is declared using the KeyPath type:
func myFunc<T: Codable, G>(usingProperty: KeyPath<T, G>) -> G {
...
}
In order to implement my function, I would like to somehow get access to not just the key path parameter named usingProperty, but also to the coding key that it is associated with. So when called with the key path to the myIntProperty property, I would want to get the name used when encoding it, which is int_property.
Is there any way to derive this value from the KeyPath parameter and its root type's CodingKeys enumeration?

Is it possible to get Enum Type from String in Swift?

Is it possible to get Enum Type from String?
ex: let type1 = WSCLogin.self <-- OK
ex: let type2 = someFunction(typeString: "WSCLogin") -> WSCLogin.Type <-- issue
I can save "WSCLogin" as string in somewhere
and letter I want to use this string("WSCLogin") to implement WSCLogin.Type.
Is it possible?
does someone who can figure out someFunction(typeString: "WSCLogin") -> WSCLogin.Type function?
thanks
enum WSCLogin: String {
case mail
case password
}
You can use the following enum constructor:
let x: WSCLogin? = WSCLogin(rawValue: String)
This will provide an optional variable with a value if the string is a valid raw value or nil if the rawValue is invalid
// the type without a String
let type1 = WSCLogin.self
// the type with a String, without extension
let mail = WSCLogin(rawValue: "mail")
let type2 = type(of: mail)
// the type with a String, with extension
extension WSCLogin {
var kind: WSCLogin.Type {
return type(of: self)
}
}
let type3 = WSCLogin(rawValue: "mail")?.kind
Because we're initializing WSCLogin through the RawRepresentable initializer we always get an Optional type back. You just need to unwrap this first.
Please notice that you cannot use type or Type as property name because in both ways you'd run into name clashes. With backticks like so
var `type`: WSCLogin.Type
you can force the naming but in that case you override the type() function you use in this computed property.

Is it possible to access a struct member using a variable in Swift 4?

I've got a list of instances of the following struct called payment_list:
struct Payment: Codable {
let id: Int
let payment_hash: String
let destination: String
let msatoshi: Int
let timestamp: Int
let created_at: Int
let status: String
enum PaymentKeys: String, CodingKey {
case payments
}
}
I can access the members of each struct instance in the list in the following manner:
print(payment_list[0].id) // 1
print(payment_list[0].timestamp) // 1517083775
Is it possible to access those struct instance members using a variable to determine which member is being accessed? Something along the lines of:
var column = "id"
print(payment_list[0][column]) // 1
I've read about people using NSObject and value(forKey key: String), but this is a struct so it can't inherit from NSObject. If it was an object I think it would look something like this:
var column = "id"
print(payment_list[0].value(forKey key: column)) // 1
Is this type of thing possible with struct?
Swift 4 added support for key paths, which allow to do something similar to what you want:
let keyPath: KeyPath<Payment, Int> = \Payment.id
var payment = Payment(id: 42)
let value = payment[keyPath: keyPath] // returns 42
A key path has two generic parameters: first the type it operates on (in your example Payment), and the type of the property it accesses (Int). Note that you'll have to specify the key path for every property you want to access.

Literal Convertibles in Swift

I want to know how Literal Convertibles work in Swift. The little I know is that the fact that, in var myInteger = 5, myInteger magically becomes an Int is because Int adopts a protocol, ExpressibleByIntegerLiteral and we don't have to do var myInteger = Int(5). Similarly String, Array, Dictionary etc all conform to some Literal protocols.
My Question is
Am I right in my little understanding of Literal Convertibles?
How can we implement these in our own types. For example
class Employee {
var name: String
var salary: Int
// rest of class functionality ...
}
How can I implement Literal Protocols to do var employee :Employee = "John Doe" which will automatically assign "John Doe" to employee's name property.
You are partially correct in your understanding of the various ExpressibleBy...Literal protocols. When the Swift compiler parses your source code into an Abstract Syntax Tree, it already identified what literal represents what data type: 5 is a literal of type Int, ["name": "John"] is a literal of type Dictionary, etc. Apple makes the base type conform to these protocols for the sake of completeness.
You can adopt these protocols to give your class an opportunity to be initialized from a compile-time constant. But the use case is pretty narrow and I don't see how it applies to your particular situation.
For example, if you want to make your class conform to ExpressibleByStringLiteral, add an initializer to set all your properties from a String:
class Employee: ExpressibleByStringLiteral {
typealias StringLiteralType = String
var name: String
var salary: Int
required init(stringLiteral value: StringLiteralType) {
let components = value.components(separatedBy: "|")
self.name = components[0]
self.salary = Int(components[1])!
}
}
Then you can init your class like this:
let employee1: Employee = "John Smith|50000"
But if you dream about about writing something like this, it's not allowed:
let str = "Jane Doe|60000"
let employee2: Employee = str // error
And if you pass in the wrong data type for salary, it will be a run time error instead of a compile-time error:
let employee3: Employee = "Michael Davis|x" // you won't know this until you run the app
TL, DR: it is a very bad idea to abuse these ExpressibleBy...Literal types.
This can be a scenario to work with Convertibles in custom types.
struct Employee : ExpressibleByStringLiteral {
var name: String = ""
init() {}
init(stringLiteral name: String) {
self.name = name
}
}
func reportName(_ employee: Employee) {
print("Name of employee is \(employee.name)")
}
reportName("John Doe") //Name of employee is John Doe

RealmSwift: Casting Object.subscript AnyObject? to List<>

I’m writing a custom update method to allow control over how values are represented in Realm. The approach taken is to match incoming key: values (from JSON) against objects’ objectSchema.properties and convert the values accordingly. Everything is general-purpose with values stored using Object.subscript.
For to-one relations, where property type is .Object the system can recurse and create or update the appropriate nested object of type determined by Property.objectClassName.
For to-many relations, where property type is .Array we must modify a List of objects of type objectClassName. List however is a generic so that’s List< concrete type of objectClassName >.
As Object.subscript returns values of type AnyObject? we need to cast this into something that can be treated as a list irrespective of its contained type. How can this be achieved?
(I've replaced the example below to better illustrate the problem)
e.g.
typealias ValueDictionary = Dictionary<String, AnyObject>
func update(object: Object, values: ValueDictionary) {
for property in object.objectSchema.properties {
if let value = values[property.name] {
var newValue: AnyObject?
switch property.type {
case .Object:
let objectType = NSClassFromString(
"mymodule" + property.objectClassName) as! Object.Type
newValue = relatedObjectWithType(objectType,
values: value as! ValueDictionary)
case .Array:
let objectType = NSClassFromString(
"mymodule" + property.objectClassName) as! Object.Type
newValue = listOfRelatedObjectsWithType(objectType,
values: value as! [ValueDictionary])
default:
// Convert primitive values, date strings, etc.
newValue = coerceValue(value, toPropertyType:property.type)
}
}
}
func relatedObjectWithClassName(type: Object.Type, values: ValueDictionary) -> Object {
// To-one relations can be instantiated using Object.Type.
var object = type.init()
update(object, values)
return object
}
// To-many relation are generic so there's no way to treat them dynamically.
func listOfRelatedObjectsWithType(type: Object.Type, values: [ValueDictionary]) -> List {
}