How do I find all the property keys of a KVC compliant Objective-C object?

十年热恋 提交于 2019-11-28 16:52:50
oxigen
#import "objc/runtime.h"

unsigned int outCount, i;

objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *propName = property_getName(property);
    if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithUTF8String:propName];
            NSString *propertyType = [NSString stringWithUTF8String:propType];
    }
}
free(properties);

Use class_getPropertyList. That will tell you all the @properties of the object.

It won't necessarily list every KVC-compliant property, because any method that takes no arguments and returns a value is a valid KVC-compliant getter. There's no 100%-reliable way for the runtime to know which ones behave as properties (e.g., -[NSString length]) and which ones behave as commands (e.g., -[NSFileHandle readDataToEndOfFile]).

You should be declaring your KVC-compliant properties as @properties anyway, so this shouldn't be too big of a problem.

There is no such method as the KVO system does not require objects/classes to register with it which properties they support KVO for. Any key could potentially support KVO, the only way to know is from the author's documentation.

And of course, there is no guarantee that an @property will support KVO; it's quite possible to write a property that doesn't (and may be necessary sometimes). So, getting a list of a class's @propertys and then assuming they're KVO-compliant would be a dangerous choice in my opinion.

Chatchavan

You need a getPropertyType function. See this post: Get an object attributes list in Objective-C

For Swift onlookers, you can get this functionality by utilising the Encodable functionality. I will explain how:

  1. Conform your object to Encodable protocol

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Create extension for Encodable to provide toDictionary functionality

     public func toDictionary() -> [String: AnyObject]? {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data =  try? encoder.encode(self),
              let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [String: AnyObject] else {
            return nil
        }
        return jsonDict
    }
    
  3. Call toDictionary on your object instance and access keys property.

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. Voila! Access your properties like so:

    for k in exampleObj!.keys {
        print(k)
    }
    // Prints "prop1"
    // Prints "prop2"
    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!