Storing Generic Objects in a Heterogeneous Array and retrieving object parameter as the correct type - swift

Ahoy everyone,
I have recently been trying to implement a Node based graph system that passes data between nodes using plugs. Similar to many of the 3D applications like houdini and maya.
I have written a similar system before using Python, and wanted to try this with Swift as my first learning excersise. Boy did I jump into the deep end on this one.
I am stuck now with Swifts Arrays, as I would like to store a list of Generic plugs.
Each plug can have its own value type float, int, color, string, Vector Matrix.
I have read up about Type Erasers and opaque types, but still cant seem to get my values our of a list in a way that I can perform some arithmetic on them.
All and any help that might put me in the direction would be greatly appreciated :D
import Foundation
import MetalKit
protocol genericPlug {
associatedtype T
func GetValue() -> T
}
class Plug<T>:genericPlug{
var _value:T?
var value:T {
get{GetValue()}
set(val){
value = val
}
}
func GetValue() -> T{
return _value!
}
init(_ newValue:T){
_value=newValue
}
}
class Node{
var plugs:[genericPlug] = []
init(){
var p1 = Plug<Int>(0)
var p2 = Plug(vector2(1.2, 3.1))
var p3 = Plug([0.0, 3.1, 0.6, 1])
plugs.append(p1)
plugs.append(p2)
plugs.append(p3)
}
func execute(){
// will access the plugs in the array and perform some sort of calculations on them.
plugs[0].value + 1 // should equal 1
plugs[1].value.x + 0.8 // should have x=2.0 y=3.1
plugs[2].value[1] - 0.1 // should equal 3.0
}
}
Thanks everyone

Use a generic something to extract what you need. Your options are methods and subscripts.
protocol PlugValue {
init()
}
extension Int: PlugValue { }
extension Float: PlugValue { }
extension Double: PlugValue { }
extension SIMD3: PlugValue where Scalar == Int32 { }
struct Plug<Value: PlugValue> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
protocol AnyPlug {
var anyValue: PlugValue { get }
}
extension AnyPlug {
subscript<Value: PlugValue>(type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
func callAsFunction<Value: PlugValue>(_ type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
}
extension Plug: AnyPlug {
var anyValue: PlugValue { value }
}
let plugs: [AnyPlug] = [
Plug(1),
Plug(2.3 as Float),
Plug(4.5),
Plug([6, 7, 8] as SIMD3)
]
plugs[0][Int.self] // 1
plugs[1][Double.self] // 0
plugs[1][] as Float // 2.3
let double: Double = plugs[2]() // 4.5
plugs[3](SIMD3.self).y // 7
With the array of protocols, do you have to down cast them into their Plug when retrieving them every time?
Essentially. This is true of all heterogenous sequences. Here are your options:
extension Array: PlugValue where Element: PlugValue { }
let plug: AnyPlug = Plug([0.1, 1.1, 2.1])
(plug as? Plug<[Double]>)?.value[1]
(plug.anyValue as? [Double])?[1]
extension Plug {
enum Error: Swift.Error {
case typeMismatch
}
}
extension AnyPlug {
func callAsFunction<Value: PlugValue, Return>(_ closure: (Value) -> Return) throws {
guard let value = anyValue as? Value
else { throw Plug<Value>.Error.typeMismatch }
closure(value)
}
}
try plug { (doubles: [Double]) in doubles[1] } // 1.1
try plug { ($0 as [Double])[1] } // 1.1
try plug { $0 as Int } // <Swift.Int>.Error.typeMismatch

I managed to find a solution that worked for my needs.
I am still looking at finding a better way to handle getting the data and their correct type.
import Foundation
import MetalKit
// Creating the PlugType Enum
enum PlugType{
case Integer(Int?)
case Float_(Float?)
case Double_(Double?)
case Vector3(simd_int3)
// default types
static func IntegerType() -> PlugType{ return PlugType.Integer(nil)}
static func FloatType() -> PlugType{ return PlugType.Float_(nil)}
static func DoubleType() -> PlugType{ return PlugType.Double_(nil)}
}
// Implements a way to retrieve the correct value type
extension PlugType{
var IntegerValue: Int{
switch self{
case .Integer(let value):
return value ?? 0
default:
return 0
}
}
var FloatValue: Float{
switch self
{
case .Float_(let value):
return value ?? 0
default:
return 0
}
}
var DoubleValue: Double{
switch self
{
case .Double_(let value):
return value ?? 0
default:
return 0
}
}
}
// Get the string representation of the PlugType
extension PlugType {
var typeName: String{
switch self {
case .Integer: return "Integer"
case .Float_: return "Float"
case .Double_: return "Double"
case .Vector3: return "Vector3"
}
}
var swiftType: Any.Type {
switch self {
case .Integer: return Int.self
case .Float_: return Float.self
case .Double_: return Double.self
case .Vector3: return simd_int3.self
}
}
}
class Plug{
var _value:PlugType?
var type:String? { get{ return _value?.typeName } }
init(_ newValue:PlugType){
_value = newValue
}
func geee<T>(_ input:T) -> T{
switch type {
case "Integer":
return getVal(_value!.IntegerValue) as! T
case "Double":
return getVal(_value!.DoubleValue) as! T
default:
return 0 as! T
}
}
func getVal(_ val:Int) -> Int {
return val
}
func getVal(_ val:Float) -> Float {
return val
}
func getVal(_ val:Double) -> Double {
return val
}
}
var plugs:[Plug] = []
var p1 = Plug(PlugType.Integer(2))

Related

Swift Recursion/ Class constructors

I am writing a Swift program that will solve post script equations. I have two Classes: ExpressionTree, and ExpressionTreeLeaf, which inherits Expression Tree. In the ExpressionTree Class, I need a method that solves the tree. I also need to override that function in the ExpressionTreeLeaf Class to just return the data of the leaf. I'll give some code for context:
ExpressionTree class:
class ExpressionTree{
let Left: ExpressionTree?
let Right: ExpressionTree?
let Data: String
// constructor for tree with known left and right
init(Data: String, Left: ExpressionTree? = nil, Right: ExpressionTree? = nil) {
self.Data = Data
self.Left = Left
self.Right = Right
}
// constructor for tree with only data
init(Data:String){
self.Data = Data
self.Left = nil
self.Right = nil
}
// this method returns double regardless of inputs
func ApplyOp(val1: Double, val2: Double, op:String) -> Double?{
switch op {
case "+":
return val1 + val2
case "-":
return val1 - val2
case "*":
return val1 * val2
case "/":
if( val2 != 0 ){
return val1 / val2
}
else{
return nil
}
default:
return nil
}
}
func Solve() -> Double{
return ApplyOp(val1: (Left?.Solve())!, val2: (Right?.Solve())!, op: Data)!
}
ExpressionTreeLeaf Class:
class ExpressionTreeLeaf: ExpressionTree {
init(_ Data: String) {
super.init(Data: "\(Data)")
}
func Solve() -> String {
return Data
}
}
My question is this: While using the debugger, I never seem to go into the ExpressionTreeLeaf constructor. I recursively go into the same solve method, and get error because the parameters are in the wrong place, causing them to be defaulted to 0.0. How to I get the recursive call to go into the ExpressionTreeLeaf class, so that when called, it will return the data of the leaf?
Thank you
EDIT:
here is the method to make the Tree:
expression is in postfix notation
func MakeTree(expression: [String]) -> ExpressionTree{
let precedance: [String: Int] = ["+": 1 , "-": 1, "*": 2, "/": 2]
var stack: Deque<ExpressionTree> = []
for piece in expression {
if(isNumber(check: "\(piece)")){
let tree: ExpressionTreeLeaf = ExpressionTreeLeaf("\(piece)")
stack.append(tree)
}
else if precedance["\(piece)"] != nil{
let tree1: ExpressionTree = stack.removeLast()
let tree2: ExpressionTree = stack.removeLast()
let newTree: ExpressionTree = ExpressionTree(Data: "\(piece)", Left: tree1, Right: tree2)
stack.append(newTree)
}
}
return stack.removeLast()
}
I realize you solved your problem but I would suggest using protocols rather than inheritance. Also, in Swift, value types such as enums and structs are preferred over classes.
First, here are a couple of utils for parsing the expression:
extension String {
var isDigits: Bool {
onlyConsistsOf(charactersIn: .decimalDigits)
}
var isMathOperation: Bool {
onlyConsistsOf(charactersIn: .init(charactersIn: "+-*/"))
}
func onlyConsistsOf(charactersIn set: CharacterSet) -> Bool {
rangeOfCharacter(from: set.inverted) == nil
}
}
extension Character {
var isDigit: Bool {
String(self).isDigits
}
var isMathOperation: Bool {
String(self).isMathOperation
}
}
Now we can get down to the nitty gritty. Let's start with a protocol:
protocol Evaluatable {
func evaluate() -> Double
}
Wether we are dealing with a an operation or an operand we can treat the types the same with protocol conformance. Notice how the Operand and Operation only store properties that they need. In your implementation your ExpressionTreeLeaf inherited from ExpressionTree even though it didn't need the Left or Right properties.
struct Operand: Evaluatable {
let value: Double
func evaluate() -> Double {
value
}
}
struct Operation: Evaluatable {
let lhs: Evaluatable
let rhs: Evaluatable
let op: Character
private var operation: (Double, Double) -> Double {
switch op {
case "+":
return (+)
case "-":
return (-)
case "*":
return (*)
case "/":
return (/)
default:
fatalError("Bad op: \(op)")
}
}
func evaluate() -> Double {
operation(lhs.evaluate(), rhs.evaluate())
}
}
Now let's create a top-level Tree type to store the root component to be evaluated. If you like, you can even make Tree conform to Evaluatable.
struct Tree: Evaluatable {
let root: Evaluatable
func evaluate() -> Double {
root.evaluate()
}
}
This factory method constructs the Tree using the same stack-based algorithm you posted. The stack is declared using the protocol we defined so we can store Operations or Operands.
enum TreeFactory {
static func makeTree(fromExpression expression: String) -> Evaluatable {
var stack: [Evaluatable] = []
for symbol in expression {
if symbol.isDigit {
stack.append(Operand(value: Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(Operation(lhs: lhs, rhs: rhs, op: symbol))
} else {
stack.removeAll()
break
}
}
return Tree(root: stack.isEmpty ? Operand(value: .zero) : stack.removeLast())
}
}
Let's conform to CustomStringConvertible for debugging purposes:
extension Operand: CustomStringConvertible {
var description: String { "\(value)" }
}
extension Operation: CustomStringConvertible {
var description: String { "(\(lhs) \(op) \(rhs))" }
}
extension Tree: CustomStringConvertible {
var description: String { "Tree: \(root) = \(evaluate())" }
}
Let's try this out:
let expression = "32+32+*3*2+1-2/"
let tree = TreeFactory.makeTree(fromExpression: expression)
print(tree)
Which results in:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0
This problem can also be solved using an enum rather than with structs. Here's an alternate solution.
indirect enum TreeNode: Evaluatable {
case operand(Double)
case operation(Character, TreeNode, TreeNode)
case root(TreeNode)
func evaluate() -> Double {
switch self {
case .operand(let value):
return value
case .operation(let op, let lhs, let rhs):
switch op {
case "+":
return lhs.evaluate() + rhs.evaluate()
case "-":
return lhs.evaluate() - rhs.evaluate()
case "*":
return lhs.evaluate() * rhs.evaluate()
case "/":
return lhs.evaluate() / rhs.evaluate()
default:
return .zero
}
case .root(let node):
return node.evaluate()
}
}
}
Let's make another factory method to create an enum-based tree:
extension TreeFactory {
static func makeNodeTree(fromExpression expression: String) -> Evaluatable {
var stack: [TreeNode] = []
for symbol in expression {
if symbol.isDigit {
stack.append(.operand(Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(.operation(symbol, lhs, rhs))
} else {
stack.removeAll()
break
}
}
return TreeNode.root(stack.isEmpty ? .operand(.zero) : stack.removeLast())
}
}
Let's make our TreeNode debug friendly:
extension TreeNode: CustomStringConvertible {
var description: String {
switch self {
case .operand(let value):
return "\(value)"
case .operation(let op, let lhs, let rhs):
return "(\(lhs) \(op) \(rhs))"
case .root(let node):
return "Tree: \(node) = \(evaluate())"
}
}
}
And now to test it out:
let expression = "32+32+*3*2+1-2/"
let nodeTree = TreeFactory.makeNodeTree(fromExpression: expression)
print(nodeTree)
Here are the results:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0
The problem is solved. I originally had incorrect return types which was not allowing me to call functions properly.

Get index of enum with extension of String,

I have an Enum that looks like this:
enum Status: String {
case online = "online"
case offline = "offline"
case na = "na"
}
I need the String value and I know how to get it, but my question is if it´s possible to get the index value too for each case in the enum.
0 for online, 1 for offline and 2 for na.
I will add more statues in the future.
-------- UPDATE -------
Since swift 4.2 you can do following:
enum Status: String, CaseIterable {
case online
case offline
case na
}
extension CaseIterable where Self: Equatable {
var index: Self.AllCases.Index? {
return Self.allCases.index { self == $0 }
}
}
or as I wrote earlier:
enum Status: Int {
case online = 0
case offline
case na
var index: Int {
return rawValue
}
var value: String {
return String(describing: self)
}
}
-------- ORIGIN ANSWER -------
I'm using this extension:
protocol EnumIterable: RawRepresentable {
static var allValues: [Self] { get }
var index: Int? { get }
}
extension EnumIterable {
static var count: Int {
return allValues.count
}
}
extension EnumIterable where Self.RawValue: Equatable {
var next: Self? {
if let index = Self.allValues.index(where: { rawValue == $0.rawValue }) {
return Self.allValues[safe: index + 1]
}
return nil
}
var index: Int? {
return Self.allValues.index { rawValue == $0.rawValue }
}
}
But you would define allValues variable:
enum Status: String, EnumIterable {
case online = "online"
case offline = "offline"
case na = "na"
static var allValues: [Status] {
return [
.online,
.offline,
.na,
]
}
}
Something similar was solved here (count of enumerations):
How do I get the count of a Swift enum?
Next possibility is to define enum like this:
enum Status: Int {
case online = 0
case offline
case na
var index: Int {
return rawValue
}
var value: String {
return String(describing: self)
}
}
print (Status.online.value) // online
print (Status.online.index) // 0
or
enum Status: Int {
case online = 0
case offline
case na
var index: Int {
return rawValue
}
var value: String {
switch self {
case .online:
return "online"
case .offline:
return "offline"
case .na:
return "na"
}
}
}
print (Status.online.value) // online
print (Status.online.index) // 0
Note: for defining string value, you can use CustomStringConvertible protocol.
Eg:
enum Status: Int, CustomStringConvertible {
case online = 0
case offline
case na
var index: Int {
return rawValue
}
var description: String {
switch self {
case .online:
return "online"
case .offline:
return "offline"
case .na:
return "na"
}
}
}
Great answer of #JMI in Swift 5.
enum MyEnum: CaseIterable {
case one
case two
}
extension CaseIterable where Self: Equatable {
var index: Self.AllCases.Index? {
return Self.allCases.firstIndex { self == $0 }
}
}
How to use:
guard let enumCaseIndex = MyEnum.one.index else { return }
print("Enum case index: ", \(enumCaseIndex)) // prints: 0
As enum in Swift does not have index of its values (please read the post in Martin R's comment), you have to create your self some 'index' function or to map all values to an Array to have the index.
You can implement as in this post or another way to do:
enum Status: String {
case online = "online"
case offline = "offline"
case na = "na"
static func index(of aStatus: Status) -> Int {
let elements = [Status.online, Status.offline, Status.na]
return elements.index(of: aStatus)!
}
static func element(at index: Int) -> Status? {
let elements = [Status.online, Status.offline, Status.na]
if index >= 0 && index < elements.count {
return elements[index]
} else {
return nil
}
}
}
let a = Status.na
//return 2
let index = Status.index(of: a)
//return Status.offline
let element2 = Status.element(at: 1)
//return nil
let element3 = Status.element(at: 3)
I did use a solution witch is almost the same than santhosh-shettigar:
func toInt() -> Int {
let allValues: NSArray = MyEnum.allCases as NSArray
let result: Int = allValues.index(of: self)
return result
}
Simple! I use the Swift built-in MyEnum.allCases, ...but I'm not sure that in Swift Specification, we have the guaranty that the Array return by MyEnum.allCases is always in the same order, the one used at the MyEnum definition???
How about this.
enum Status: Int {
case online = 0
case offline = 1
case na = 2
}
You can get the string value and the integer index both.
// enum as string
let enumName = "\(Status.online)" // `online`
// enum as int value
let enumValue = Status.online.rawValue // 0
// enum from int
let enumm = Status.init(rawValue: 1)
Hope it helps. Thanks.
Possible work around may to associate custom functions with enum
enum ToolbarType : String{
case Case = "Case", View="View", Information="Information"
static let allValues = [Case, View, Information]
func ordinal() -> Int{
return ToolbarType.allValues.index(of: self)!
}
}
Can be used as
for item in ToolbarType.allValues {
print("\(item.rawValue): \(item.ordinal())")
}
Output
Case: 0
View: 1
Information: 2

Hashing problems using a wrapper class around NSUUID as the key

** REWRITE **
OK, it turns out I'm really asking a different question. I understand about hashValue and ==, so that's not relevant.
I would like my wrapper class BUUID to "do the right thing" and act just like NSUUID's act in a Dictionary.
See below, where they don't.
import Foundation
class BUUID: NSObject {
init?(str: String) {
if let uuid = NSUUID(UUIDString: str) {
_realUUID = uuid
}
else {
return nil
}
}
override init() {
_realUUID = NSUUID()
}
private var _realUUID: NSUUID
override var description: String { get { return _realUUID.UUIDString } }
override var hashValue: Int { get { return _realUUID.hashValue } }
var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }
let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")
var d = [a: "Hi"]
print("\(d[a]) \(d[b])")
let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")
var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")
Results. Note that I can look up using NSUUID nB and get back what I put under nA. Not so with my BUUID.
a: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
b: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
a === b: false
a == b: true
Optional("Hi") nil
nA: <__NSConcreteUUID 0x7fa193c39500> BB9F9851-93CF-4263-B98A-5015810E4286
nB: <__NSConcreteUUID 0x7fa193c37dd0> BB9F9851-93CF-4263-B98A-5015810E4286
nA === nB: false
nA == nB: true
Optional("Hi") Optional("Hi")
Inheriting from NSObject also assumes isEqual(object: AnyObject?) -> Bool method overloading:
import Foundation
class BUUID: NSObject {
init?(str: String) {
if let uuid = NSUUID(UUIDString: str) {
_realUUID = uuid
}
else {
return nil
}
}
override init() {
_realUUID = NSUUID()
}
private var _realUUID: NSUUID
override func isEqual(object: AnyObject?) -> Bool {
guard let buuid = object as? BUUID else {
return false
}
return buuid._realUUID == _realUUID
}
override var description: String { get { return _realUUID.UUIDString } }
override var hashValue: Int { get { return _realUUID.hashValue } }
var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }
let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")
var d = [a: "Hi"]
print("\(d[a]) \(d[b])")
let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")
var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")
So the answer is to not make BUUID inherit from NSObject, which undercuts the Swiftiness of overriding ==.
So:
extension BUUID: Hashable {}
class BUUID: CustomStringConvertible {
// take away all 'override' keywords, nothing to override
// otherwise same as above
}
Interesting!
This answer is relevant to initially asked question: Why that's possible to get two key-value pairs with identical key's hashes in a dictionary
This example illustrates that keys in Dictionary can have identical hashes, but equality operation should return false for different keys:
func ==(lhs: FooKey, rhs: FooKey) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
class FooKey: Hashable, Equatable {
var hashValue: Int {
get {
return 123
}
}
}
var d = Dictionary<FooKey, String>()
let key1 = FooKey()
let key2 = FooKey()
d[key1] = "value1"
d[key2] = "value2"
Output
[FooKey: "value1", FooKey: "value2"]
That's definitely not good to have all keys with the same hash. In this case we are getting that worst case when search element complexity fells down to O(n) (exhaustive search). But it will work.

get the type/class of a property from its name in swift

Lets say I have this class:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children") how can I get its type? (In this case [Node]?)
I imagine having a global function like below will solve my needs:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
Swift 2 (Note: Reflection changed):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
Reflection is achieved in Swift using the global reflect() function. When passing an instance of some type to reflect() it returns a MirrorType, which has a range of properties allowing you to analyze your instance:
var value: Any { get }
var valueType: Any.Type { get }
var objectIdentifier: ObjectIdentifier? { get }
var count: Int { get }
var summary: String { get }
var quickLookObject: QuickLookObject? { get }
var disposition: MirrorDisposition { get }
subscript(i: Int) -> (String, MirrorType) { get }
This seems to work:
func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
let mirror = reflect(instance)
var variableCollection = [String: MirrorType]()
for item in 0..<mirror.count {
variableCollection[mirror[item].0] = mirror[item].1
}
if let type = variableCollection[name] {
let longName = _stdlib_getDemangledTypeName(type.value)
let shortName = split(longName, { $0 == "."}).last
return shortName ?? longName
}
return nil
}
Here's some example code on SwiftStub.
Edit:
The result for optional values is only "Optional".
The result for arrays is only "Array".
The result for dictionaries is only "Dictionary".
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
Building on #PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
extension NSObject {
// Returns the property type
func getTypeOfProperty (name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
while let parent = type.superclassMirror() {
for child in parent.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
type = parent
}
return nil
}
}
Hope this may help someone.
Swift 3 update:
// Extends NSObject to add a function which returns property type
extension NSObject {
// Returns the property type
func getTypeOfProperty (_ name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
while let parent = type.superclassMirror {
for child in parent.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
type = parent
}
return nil
}
}
The solution provided by #peter-kreinz using Swift's class Mirror works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}

Swift generic cast to Protocol fails with swift_dynamicCastUnknownClass

The following example is taken from Apple Swift Reference guide. I only added the getHasAreaInstances() and getGenericHasAreaInstances()
import UIKit
#objc protocol HasArea {
var area: Double { get }
}
#objc protocol HasExtendedArea: HasArea {
var extendedArea: Double { get }
}
class Circle: HasArea {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}
class Continent: HasExtendedArea {
var area: Double { return 300 }
var extendedArea: Double { return 3000 }
}
let objects: [HasArea] = [
Circle(radius: 2.0),
Country(area: 243_610),
Continent()
]
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
println("Extended Area is \(objectWithArea.area)")
} else {
println("Area is not extended")
}
}
// Extended Area is 300.0
// Area is not extended
// Area is not extended
The method below returns the correct array:
func getHasExtendedAreaInstances() -> [HasExtendedArea] {
var haveArea: [HasExtendedArea] = []
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areas = getHasExtendedAreaInstances()
//[Continent]
The method below returns the correct array:
func getGenericHasExtendedAreaInstances<T>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGeneric: [HasExtendedArea] = getGenericHasExtendedAreaInstances()
//[Continent]
However, as soon as a constraint is imposed on the generic type, it no longer works
func getGenericConstraintHasExtendedAreaInstances<T: HasArea>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
// the line above fails with swift_dynamicCastUnknownClass
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGenericConstraint: [HasExtendedArea] = getGenericConstraintHasExtendedAreaInstances()
Your generic function makes no sense. What would resolve it? What would satisfy it? Make a simpler example with the same basic declaration structure: it's an impossible function. For example, start with this nongeneric function:
class Thing : Printable {
var description : String {return "thing"}
}
func g() -> [Thing] {
return [Thing()]
}
let result : [Thing] = g()
Now modify g to be generic, exactly parallel to your function:
class Thing : Printable {
var description : String {return "thing"}
}
func g<T:Printable>() -> [T] {
return [Thing()]
}
let result : [Thing] = g()
It doesn't compile - because it makes no sense.
This is fixed in Swift 1.2, tested on Xcode 6.3 Beta 3
You can specify the type constraint without swift compiler failing on you