Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective-C中的类属性列表_Objective C_Ios_Class_Object - Fatal编程技术网

Objective-C中的类属性列表

Objective-C中的类属性列表,objective-c,ios,class,object,Objective C,Ios,Class,Object,有没有办法获得某种类型的类属性数组?例如,如果我有这样的接口 @interface MyClass : NSObject @property (strong,nonatomic) UILabel *firstLabel; @property (strong,nonatomic) UILabel *secondLabel; @end 我是否可以在不知道标签名称的情况下获取对这些标签的引用 @implementation MyClass -(NSArray*

有没有办法获得某种类型的类属性数组?例如,如果我有这样的接口

@interface MyClass : NSObject
    @property (strong,nonatomic) UILabel *firstLabel;
    @property (strong,nonatomic) UILabel *secondLabel;        
@end
我是否可以在不知道标签名称的情况下获取对这些标签的引用

@implementation MyClass
    -(NSArray*)getListOfAllLabels
    {
            ?????
    }        
@end
我知道我可以很容易地使用
[NSArray arraywhithobjects:firstLabel,secondLabel,nil]
,但是我想使用一些类枚举,比如
for(UILabel*oneLabel in???[self objects]?)
检查一下这个。它是objective c运行时上的objective 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);
uint计数;
objc_property_t*properties=class_copyPropertyList(self.class,&count);
NSMutableArray*propertyArray=[NSMutableArray阵列容量:计数];
for(int i=0;i
更准确地说,如果我没有弄错的话,您需要动态的、运行时的属性观察。执行类似的操作(在你想要内省的类self上实现此方法):


希望这有帮助。

您必须包含运行时标题

 #import<objc/runtime.h>
uint propertiesCount;
objc_property_t *classPropertiesArray = class_copyPropertyList([self class], &propertiesCount);
free(classPropertiesArray);
#导入
单位财产数;
objc_property_t*classPropertiesArray=class_copyPropertyList([self class],&propertiesCount);
免费(类别财产阵列);
使用NSObject的方法

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

        id attribute = [self valueForKey:key];

        if([attribute isKindOfClass:[UILabel  class]])
        {
         //put attribute to your array
        }
    }

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

@user529758的答案不适用于ARC,也不会列出任何祖先类的属性

要解决此问题,需要遍历类层次结构,并使用ARC兼容的
[NSObject valueForKey://code>获取属性值

第h人:

#import <Foundation/Foundation.h>

extern NSMutableArray *propertyNamesOfClass(Class klass);

@interface Person : NSObject

@property (nonatomic) NSString *name;

@end
学生m:

#import "Student.h"

@implementation Student

@end
main.m:

#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Student *student = [[Student alloc] init];
        student.name = @"John Doe";
        student.studentID = @"123456789";
        NSLog(@"student - %@", student);
    }
    return 0;
}
#导入
#导入“Student.h”
int main(int argc,const char*argv[]{
@自动释放池{
//在这里插入代码。。。
学生*Student=[[Student alloc]init];
student.name=@“John Doe”;
student.studentID=@“123456789”;
NSLog(@“学生-%@”,学生);
}
返回0;
}

这真的很好用!仅此而已,在此之后如何访问这些属性?这给了我名称字符串,但不是指向对象的实际指针。。。我想这一定很简单:)我只是不熟悉objc/运行时类:)谢谢!一旦有了字符串,使用KVC和
[self-valueForKey:propertyName]可能就更容易了。通常情况下,使用访问器比直接使用支持ivar更好——因此,您可以利用统一的访问原则,给自己一些钩子,以便以后戴上帽子。不要使用
get
前缀命名方法;这仅限于一个非常特定的用例,而事实并非如此。@H2CO3-(嘿,伙计)我相信class_copyPropertyList只列出了当前类对象的属性,如果你想进入继承链,需要一些递归。这是根据文档,但是我没有测试,因为我在做的事情中使用了另一种方法。AllPropertyName和[self-valueForKey:propertyName]、[self-setValue:@“forKey:propertyName]的组合对我有效。使用ARC下的pointerOfIvarForPropertyNamed时出错。这看起来是最优雅的解决方案,但遗憾的是,方法attributeKeys仅在Mac OS X中可用,在iOS中不可用…不要使用
get
前缀命名方法;这仅限于一个非常具体的用例,而不是这样。在iOS上,考虑使用iButtLabVIEW。这就是它存在的目的。别忘了导入
#import <Foundation/Foundation.h>

extern NSMutableArray *propertyNamesOfClass(Class klass);

@interface Person : NSObject

@property (nonatomic) NSString *name;

@end
#import "Person.h"
#import <objc/runtime.h>

NSMutableArray *propertyNamesOfClass(Class klass) {
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList(klass, &count);

    NSMutableArray *rv = [NSMutableArray array];

    for (unsigned int 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;
}

@implementation Person

- (NSMutableArray *)allPropertyNames {
    NSMutableArray *classes = [NSMutableArray array];
    Class currentClass = [self class];
    while (currentClass != nil && currentClass != [NSObject class]) {
        [classes addObject:currentClass];
        currentClass = class_getSuperclass(currentClass);
    }

    NSMutableArray *names = [NSMutableArray array];
    [classes enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(Class currentClass, NSUInteger idx, BOOL *stop) {
        [names addObjectsFromArray:propertyNamesOfClass(currentClass)];
    }];

    return names;
}

- (NSString*)description {
    NSMutableArray *keys = [self allPropertyNames];
    NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:keys.count];
    [keys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
        properties[key] = [self valueForKey:key];
    }];

    NSString *className = NSStringFromClass([self class]);
    return [NSString stringWithFormat:@"%@ : %@", className, properties];
}
#import "Person.h"

@interface Student : Person

@property (nonatomic) NSString *studentID;

@end
#import "Student.h"

@implementation Student

@end
#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Student *student = [[Student alloc] init];
        student.name = @"John Doe";
        student.studentID = @"123456789";
        NSLog(@"student - %@", student);
    }
    return 0;
}