如何检测 Objective-C 中的属性返回类型

发布于 2024-07-17 14:18:18 字数 105 浏览 9 评论 0原文

我在运行时在 Objective-C 中有一个对象,我只知道 KVC 键,并且我需要检测该属性的返回值类型(例如,我需要知道它是 NSArray 还是 NSMutableArray),我该怎么做?

I have an object in objective-c at runtime, from which I only know the KVC key and I need to detect the return value type (e.g. I need to know if its an NSArray or NSMutableArray) of this property, how can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

德意的啸 2024-07-24 14:18:18

您正在谈论运行时属性自省,这恰好是 Objective-C 的东西 非常擅长

在您描述的情况下,我假设您有一个像这样的类:

@interface MyClass
{
    NSArray * stuff;
}
@property (retain) NSArray * stuff;
@end

它在 XML 中进行编码,如下所示:

<class>
    <name>MyClass</name>
    <key>stuff</key>
</class>

根据此信息,您想要重新创建该类,并为它提供适当的值 stuff.

它可能是这样的:

#import <objc/runtime.h>

// ...

Class objectClass;       // read from XML (equal to MyClass)
NSString * accessorKey;  // read from XML (equals @"stuff")

objc_property_t theProperty =
    class_getProperty(objectClass, accessorKey.UTF8String);

const char * propertyAttrs = property_getAttributes(theProperty);
// at this point, propertyAttrs is equal to: T@"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string

// ... code to assign the property based on this information

Apple 的文档(上面链接)包含了您可以在 propertyAttrs 中看到的所有肮脏细节。

You're talking about runtime property introspection, which happens to be something that Objective-C is very good at.

In the case you describe, I'm assuming you have a class like this:

@interface MyClass
{
    NSArray * stuff;
}
@property (retain) NSArray * stuff;
@end

Which gets encoded in XML something like this:

<class>
    <name>MyClass</name>
    <key>stuff</key>
</class>

From this information, you want to recreate the class and also give it an appropriate value for stuff.

Here's how it might look:

#import <objc/runtime.h>

// ...

Class objectClass;       // read from XML (equal to MyClass)
NSString * accessorKey;  // read from XML (equals @"stuff")

objc_property_t theProperty =
    class_getProperty(objectClass, accessorKey.UTF8String);

const char * propertyAttrs = property_getAttributes(theProperty);
// at this point, propertyAttrs is equal to: T@"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string

// ... code to assign the property based on this information

Apple's documentation (linked above) has all of the dirty details about what you can expect to see in propertyAttrs.

烂柯人 2024-07-24 14:18:18

便宜的答案:使用此处的 NSObject+Properties 源

它实现了与上述相同的方法。

Cheap answer: use the NSObject+Properties source here.

It implements the same methodology described above.

似最初 2024-07-24 14:18:18

首选方法是使用 NSObject 协议

具体来说,要确定某物是某个类的实例还是该类的子类的实例,请使用 -isKindOfClass:。 要确定某物是否是特定类的实例,并且只是该类(即:不是子类),请使用 -isMemberOfClass:

因此,对于您的情况,您需要执行以下操作:

// Using -isKindOfClass since NSMutableArray subclasses should probably
// be handled by the NSMutableArray code, not the NSArray code
if ([anObject isKindOfClass:NSMutableArray.class]) {
    // Stuff for NSMutableArray here
} else if ([anObject isKindOfClass:NSArray.class]) {
    // Stuff for NSArray here

    // If you know for certain that anObject can only be
    // an NSArray or NSMutableArray, you could of course
    // just make this an else statement.
}

The preferred way is to use the methods defined in the NSObject Protocol.

Specifically, to determine if something is either an instance of a class or of a subclass of that class, you use -isKindOfClass:. To determine if something is an instance of a particular class, and only that class (ie: not a subclass), use -isMemberOfClass:

So, for your case, you'd want to do something like this:

// Using -isKindOfClass since NSMutableArray subclasses should probably
// be handled by the NSMutableArray code, not the NSArray code
if ([anObject isKindOfClass:NSMutableArray.class]) {
    // Stuff for NSMutableArray here
} else if ([anObject isKindOfClass:NSArray.class]) {
    // Stuff for NSArray here

    // If you know for certain that anObject can only be
    // an NSArray or NSMutableArray, you could of course
    // just make this an else statement.
}
初吻给了烟 2024-07-24 14:18:18

这实际上是针对 Greg Maletic 为回应 e.James 21APR09 提供的答案而提出的问题的评论。

同意 Objective-C 可以使用更好的实现来获取这些属性。
下面是我快速组合起来检索单个对象属性的属性的方法:

- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{

    objc_property_t prop = class_getProperty(obj.class, propName.UTF8String);
    if (!prop) {
       // doesn't exist for object
       return nil;
    }
    const char * propAttr = property_getAttributes(prop);
    NSString *propString = [NSString stringWithUTF8String:propAttr];
    NSArray *attrArray = [propString componentsSeparatedByString:@","];
    return attrArray;
}

属性键的部分列表:

  • R 只读
  • C 分配的最后一个值的副本
  • & 对最后分配值的引用
  • N 非原子属性
  • W 弱引用

完整列表位于 苹果

This is really a comment addressing an issue raised by Greg Maletic in response to answer provided by e.James 21APR09.

Agreed that Objective-C could use a better implementation for getting these attributes.
Below is a method I quickly threw together to retrieve attributes of a single object property:

- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{

    objc_property_t prop = class_getProperty(obj.class, propName.UTF8String);
    if (!prop) {
       // doesn't exist for object
       return nil;
    }
    const char * propAttr = property_getAttributes(prop);
    NSString *propString = [NSString stringWithUTF8String:propAttr];
    NSArray *attrArray = [propString componentsSeparatedByString:@","];
    return attrArray;
}

Partial list of attribute keys:

  • R Read-only
  • C Copy of last value assigned
  • & Reference to last value assigned
  • N Nonatomic property
  • W Weak reference

Full list at Apple

葬シ愛 2024-07-24 14:18:18

您可以使用 isKindOfClass 消息

if([something isKindOfClass:NSArray.class])
     [somethingElse action];

You can use isKindOfClass message

if([something isKindOfClass:NSArray.class])
     [somethingElse action];
梦太阳 2024-07-24 14:18:18

如果您知道该属性已定义:

        id vfk = [object valueForKey:propertyName];
        Class vfkClass = vfk.class;

并与 isKindOfClass、isSubClass 等进行比较。

If you know that the property is defined :

        id vfk = [object valueForKey:propertyName];
        Class vfkClass = vfk.class;

And compare with isKindOfClass, isSubClass, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文