30

特定の種類のクラス プロパティの配列を取得する方法はありますか? たとえば、このようなインターフェースがある場合

@interface MyClass : NSObject
    @property (strong,nonatomic) UILabel *firstLabel;
    @property (strong,nonatomic) UILabel *secondLabel;        
@end

名前を知らなくても、実装でそれらのラベルへの参照を取得できますか?

@implementation MyClass
    -(NSArray*)getListOfAllLabels
    {
            ?????
    }        
@end

で簡単に実行できることはわかっていますが、次[NSArray arrayWithObjects:firstLabel,secondLabel,nil]のようなある種のクラス列挙で実行したいと思いますfor (UILabel* oneLabel in ???[self objects]???)

4

6 に答える 6

79

より正確には、私が正しく取得した場合、プロパティの動的なランタイム監視が必要です。次のようにします (内省したいクラスである self にこのメソッドを実装します)。

#import <objc/runtime.h>

- (NSArray *)allPropertyNames
{
    unsigned count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);

    NSMutableArray *rv = [NSMutableArray array];

    unsigned i;
    for (i = 0; i < count; i++)
    {
        objc_property_t property = properties[i];
        NSString *name = [NSString stringWithUTF8String:property_getName(property)];
        [rv addObject:name];
    }

    free(properties);

    return rv;
}

- (void *)pointerOfIvarForPropertyNamed:(NSString *)name
{
    objc_property_t property = class_getProperty([self class], [name UTF8String]);

    const char *attr = property_getAttributes(property);
    const char *ivarName = strchr(attr, 'V') + 1;

    Ivar ivar = object_getInstanceVariable(self, ivarName, NULL);

    return (char *)self + ivar_getOffset(ivar);
}

次のように使用します。

SomeType myProperty;
NSArray *properties = [self allPropertyNames];
NSString *firstPropertyName = [properties objectAtIndex:0];
void *propertyIvarAddress = [self getPointerOfIvarForPropertyNamed:firstPropertyName];
myProperty = *(SomeType *)propertyIvarAddress;

// Simpler alternative using KVC:
myProperty = [self valueForKey:firstPropertyName];

お役に立てれば。

于 2012-08-02T09:05:21.777 に答える
12

NSObject のattributeKeysメソッドを使用します。

    for (NSString *key in [self attributeKeys]) {

        id attribute = [self valueForKey:key];

        if([attribute isKindOfClass:[UILabel  class]])
        {
         //put attribute to your array
        }
    }
于 2012-08-02T10:08:56.653 に答える
8

このリンクをチェックしてください。これは、客観的な C ランタイムに対する客観的な C ラッパーです。

以下のようなコードを使用できます

uint count;
objc_property_t* properties = class_copyPropertyList(self.class, &count);
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    }
    free(properties);
于 2012-08-02T09:03:52.503 に答える
6

ランタイム ヘッダーを含める必要があります

 #import<objc/runtime.h>
uint propertiesCount;
objc_property_t *classPropertiesArray = class_copyPropertyList([self class], &propertiesCount);
free(classPropertiesArray);
于 2012-08-02T09:20:46.603 に答える
-1

Serhats の解決策は素晴らしいですが、残念ながら iOS では機能しません (前述のとおり) (この質問は iOS 用にタグ付けされています)。回避策は、オブジェクトの NSDictionary 表現を取得し、キーと値のペアとして通常どおりアクセスすることです。NSObject のカテゴリをお勧めします。

ヘッダー ファイル:

@interface NSObject (NSDictionaryRepresentation)

/**
 Returns an NSDictionary containing the properties of an object that are not nil.
 */
- (NSDictionary *)dictionaryRepresentation;

@end

実装ファイル:

#import "NSObject+NSDictionaryRepresentation.h"
#import <objc/runtime.h>

@implementation NSObject (NSDictionaryRepresentation)

- (NSDictionary *)dictionaryRepresentation {
    unsigned int count = 0;
    // Get a list of all properties in the class.
    objc_property_t *properties = class_copyPropertyList([self class], &count);

    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:count];

    for (int i = 0; i < count; i++) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        NSString *value = [self valueForKey:key];

        // Only add to the NSDictionary if it's not nil.
        if (value)
            [dictionary setObject:value forKey:key];
    }

    free(properties);

    return dictionary;
}

@end

この記事から借用: http://hesh.am/2013/01/transform-properties-of-an-nsobject-into-an-nsdictionary/

このようにして、serhatsが言及したのと同様のことができます:

for (NSString *key in objectDic.allKeys) {
   if([objectDic[key] isKindOfClass:[UILabel  class]])
   {
       //put attribute to your array
   }
}
于 2015-07-02T10:10:57.530 に答える