swift 获取对象的类型

2017-03-27 16:45:06 Story51314 阅读数 9088

本文转载自《获取对象类型》

我们一再强调,如果遵循规则的话,Swift 会是一门相当安全的语言:不会存在类型的疑惑,绝大多数的内容应该能在编译期间就唯一确定。但是不论是 Objective-C 里很多开发者早已习惯的灵活性,还是在程序世界里总是千变万化的需求,都不可能保证一成不变。我们有时候也需要引入一定的动态特性。而其中最为基本但却是最为有用的技巧是获取任意一个实例类型。

在 Objective-C 中我们可以轻而易举地做到这件事,使用-class 方法就可以拿到对象的类,我们甚至可以用 NSStringFromClass 将它转换为一个能够打印出来的字符串:

NSDate *date = [NSDate date];
NSLog(@"%@",NSStringFromClass([date class]));
// 输出:
// __NSDate

在 Swift 中,我们会发现不管是纯 Swift 的 class 还是 NSObject 的子类,都没有像原来那样的 class() 方法来获取类型了。对于 NSObject 的子类,因为其实类的信息的存储方式并没有发生什么大的变化,因此我们可以求助于 Objective-C 的运行时,来获取类并按照原来的方式转换:

let date = NSDate()
let name: AnyClass! = object_getClass(date)
print(name)
// 输出:
// __NSDate

其中object_getClass 是一个定义在 ObjectiveC 的 runtime 中的方法,它可以接受任意的 AnyObject! 并返回它的类型 AnyClass! (注意这里的叹号,它表明我们甚至可以输入 nil,并期待其返回一个 nil)。在 Swift 中其实为了获取一个 NSObject 或其子类的对象的实际类型,对这个调用其实有一个好看一些的写法,那就是dynamicType。上面的代码用一种 “更 Swift” 一些的语言转换一下,会是这个样子:

let date = NSDate()
let name = date.dynamicType
print(name)
// 输出:
// __NSDate

很好,似乎我们的问题能解决了。但是仔细想想,我们上面用的都是 Objective-C 的动态特性,要是换成一个 Swift 内建类型的话,会怎么样呢?比如原生的 String,

let string = "Hello"
let name = string.dynamicType
print(name)
// 输出:
// String

可以看到对于 Swift 的原生类型,这种方式也是可行的。(值得指出的是,其实这里的真正的类型名字还带有 module 前缀,也就是 Swift.String。直接 print 只是调用了 CustomStringConvertible 中的相关方法而已,你可以使用 debugPrint 来进行确认。关于更多地关于 print 和 debugPrint 的细节,可以参考 print 和 debugPrint 一节的内容。)

在 Swift 1.2 之前,直接对 Swift 内建的非 AnyObject 类型使用 .dynamicType 可能会导致编译错误或者无法得到正确结果。但是随着 Swift 不断完善和改进,现在我们已经可以统一地使用 .dynamicType 来获取一个对象的类型了。

备注:dynamicType在Swift 3.0中已经被舍弃,我们可以使用type(of:...)来代替

let date = NSDate()
let name = type(of:date)
print(name)
// 输出:
// __NSDate
2019-12-02 11:40:32 wm9028 阅读数 120

Swift获取对象的类型的方法type(of: <#T##T#>)

// type(of: <#T##T#>)

eg:

let date = Date()
type(of: date) // Foundation.Date.Type
print("\(type(of: date))") // Date

let str = "12345"
type(of: str) //String.Type
print("\(type(of: str))") // String

let number = NSNumber.init(value: 10)
type(of: number) //__C.__NSCFNumber.Type
print("\(type(of: number))") //__NSCFNumber

2018-04-02 16:41:53 lvchenqiang_ 阅读数 4701
/// 获取类型
type(of: router.rootVC)

/// 获取类型 string
type(of: router.rootVC).description()

type(of: router.rootVC).description().components(separatedBy: ".")[1];

提取一下代码

extension NSObject
{
    // MARK:返回className
    var className:String{
        get{
          let name =  type(of: self).description()
            if(name.contains(".")){
                return name.components(separatedBy: ".")[1];
            }else{
                return name;
            }

        }
    }

}
2016-12-26 23:35:45 feng2qing 阅读数 3232

新建一个类:Person.swift,创建两个对象

//基本数据类型,如果定义成可选,运行时同样取不到,使用KVC就会崩溃
//var age: Int?
var age: Int = 0

//private 修饰的属性,使用运行时,同样获取不到属性(可以获取到ivar),也会让KVC崩溃
//private var title: String?
var title: String?

使用运行时获取当前类所有属性的数组

class func propertyList() -> [String] {
    var count: UInt32 = 0
    //获取类的属性列表,返回属性列表的数组,可选项
    let list = class_copyPropertyList(self, &count)
    print("属性个数:\(count)")
    //遍历数组
    for i in 0..<Int(count) {
        //根据下标获取属性
        let pty = list?[i]
        //获取属性的名称<C语言字符串>
        //转换过程:Int8 -> Byte -> Char -> C语言字符串
        let cName = property_getName(pty!)
        //转换成String的字符串
        let name = String(utf8String: cName!)
        print(name!)
    }
    free(list) //释放list
    return []
}
//控制器调用print(Person.propertyList())打印输出:
属性个数:2
age
title
[]

使用guard语法改写for循环内部实现

class func propertyList() -> [String] {
    var count: UInt32 = 0
    //1.获取类的属性列表,返回属性列表的数组,可选项
    let list = class_copyPropertyList(self, &count)
    print("属性个数:\(count)")
    for i in 0..<Int(count) {
        //使用guard语法,一次判断每一项是否有值,只要有一项为nil,就不再执行后续的代码
        guard let pty = list?[i],
            let cName = property_getName(pty),
            let name = String(utf8String: cName)
            else {
                //继续遍历下一个
                continue
        }
        print(name)
    }
    free(list)
    return []
}
2015-12-22 17:16:38 u012884714 阅读数 6524

最近开发过程中遇到了获取对象的所有属性以及设置属性值的问题,经过一番研究,最终实现了这个功能


直接上代码


extension NSObject{

    

    /**

     获取对象对于的属性值,无对于的属性则返回NIL

     

     - parameter property: 要获取值的属性

     

     - returns: 属性的值

     */

    func getValueOfProperty(property:String)->AnyObject?{

        let allPropertys = self.getAllPropertys()

        if(allPropertys.contains(property)){

            return self.valueForKey(property)


        }else{

            return nil

        }

    }

    

    /**

     设置对象属性的值

     

     - parameter property: 属性

     - parameter value:   

     

     - returns: 是否设置成功

     */

    func setValueOfProperty(property:String,value:AnyObject)->Bool{

        let allPropertys = self.getAllPropertys()

        if(allPropertys.contains(property)){

            self.setValue(value, forKey: property)

            return true

            

        }else{

            return false

        }

    }

    

    /**

     获取对象的所有属性名称

     

     - returns: 属性名称数组

     */

    func getAllPropertys()->[String]{

        

        var result = [String]()

        let count = UnsafeMutablePointer<UInt32>.alloc(0)

        let buff = class_copyPropertyList(object_getClass(self), count)

        let countInt = Int(count[0])

        

        for(var i=0;i<countInt;i++){

            let temp = buff[i]

            let tempPro = property_getName(temp)

            let proper = String.init(UTF8String: tempPro)

            result.append(proper!)

            

        }

        

        return result

    }

}



如有问题欢迎随时联系我 ———— LC



Swift3.0 类型检查

阅读数 2123