Reflection in swift 2

2020-07-20 04:29发布

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.

2条回答
The star\"
2楼-- · 2020-07-20 04:46

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
}
查看更多
疯言疯语
3楼-- · 2020-07-20 05:05

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.

查看更多
登录 后发表回答