3

I have a class User:

import UIKit
import ObjectMapper


class User: NSObject, CustomStringConvertible, Mappable {

    var FirstName: NSString! ;
    var LastName: NSString! ;


    required init?(_ map: Map){

    }


    func mapping(map: Map) {

        FirstName <- map["FirstName"]
        LastName <- map["LastName"]

    }


    override var description:String {
        var s:String=""

  //USE REFLECTION TO GET NAME AND VALUE OF DATA MEMBERS      
        for var index=1; index<reflect(self).count; ++index {
            s += (reflect(self)[index].0 + ": "+reflect(self)[index].1.summary+"\t")
        }

        return s
    }
}

In swift 1.2, I was using reflect() method to get array of all the data members with their names and values.

Now, after I have updated to swift 2, I am getting the following error:

'reflect' is unavailable: call the 'Mirror(reflecting:)' initializer

With some trials, I was able to get the count of data members by this: Int(Mirror(reflecting: self).children.count), but still, I am unable to get the member name and its value.

I have looked into the following resources:

  1. https://netguru.co/blog/reflection-swift
  2. http://nshipster.com/mirrortype/

UPDATE I have found the an answer here: https://stackoverflow.com/a/32846514/4959077. But this doesn't tell how to find out the type of reflected value. If the value is int and we parse it into String then it gives error.

Community
  • 1
  • 1
Vishal
  • 467
  • 1
  • 8
  • 17
  • Is this what you are looking for: http://stackoverflow.com/questions/32691894/reflect-property-value-on-swift-2-0 ? – Martin R Oct 04 '15 at 10:29
  • 1
    each element in your .childrend will have a .label and .value If you wan to get the type, then you can get the .value.dynamicType. For more info see https://github.com/evermeer/EVReflection/blob/0879793e6d4ed5e554211eea7d654c7a0bfcdb82/EVReflection/pod/EVReflection.swift#L434-434 – Edwin Vermeer Oct 12 '15 at 14:39
  • one other tip: you should call reflect once before you enter the loop. Then in the loop use that variable. each time you do a reflect(self) a snapshot of the object will be created. In theory the object could even have been changed in the mean time resulting in a different outcome. – Edwin Vermeer Oct 22 '15 at 11:39

2 Answers2

3

You may access the reflected attribute "label" name, value and type as follows:

let mirror = Mirror(reflecting: SomeObject)

var dictionary = [String: Any]() 
for child in mirror.children {
    guard let key = child.label else { continue }
    let value: Any = child.value

    dictionary[key] = value

    switch value {
    case is Int: print("integer = \(anyValue)")
    case is String: print("string = \(anyValue)")
    default: print("other type = \(anyValue)")
    }

    switch value {
    case let i as Int: print("• integer = \(i)")
    case let s as String: print("• string = \(s)")
    default: print("• other type = \(anyValue)")
    }

    if let i = value as? Int {
        print("•• integer = \(i)")
    }
}

Note: per the question followup, three approaches to determine the type of the reflected value are shown.

marc-medley
  • 8,931
  • 5
  • 60
  • 66
1

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
}
Community
  • 1
  • 1
Sajjon
  • 8,938
  • 5
  • 60
  • 94