如果来自 UIViewController 的对象如何仅获取我创建的自定义属性的名称(在 运行 时间内)?

If object from UIViewController how get only the names of custom properties that I created (in run time)?

我在定义为符合 UICollectionViewDelegateUICollectionViewDataSource 的视图控制器中实现了以下代码:

objc_property_t *properties = class_copyPropertyList(self, &outCount);

for (i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *propName = property_getName(property);
    if(propName) {
        [properitiesList addObject:[NSString stringWithUTF8String:propName]];
    }
}

当我这样做时,我不仅会看到我的自定义属性,还会看到这些协议引入的一些属性,即:hashsuperclassdescriptiondebugDescription.

如何只显示子类的属性,而不显示那些协议引入的属性?

class_copyPropertyList 方法只会 return 为 class 声明的属性,而不是为 superclass 声明的属性。正如 header for class_copyPropertyList 所说,它 returns

An array of pointers of type objc_property_t describing the properties declared by the class. Any properties declared by superclasses are not included.

但问题是您已经将 class 定义为符合 UICollectionViewDataSourceUICollectionViewDelegate。因此,这些协议 引入的属性 被解释为您的 subclass 的属性,而不是某些 superclass.

的属性

最简单的解决方案是删除那些协议声明,然后错误就会消失。

如果您不想删除那些协议声明(例如,您仍然想享受那些协议方法的代码完成),您可以创建一个符合这些协议的抽象 class,然后子class那个。例如:

@interface AbstractViewControllerForCollectionView : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource>
@end

@implementation AbstractViewControllerForCollectionView

// we have to implement the required methods; let's just warn the developer if they accidentally fail to subclass

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    NSAssert(FALSE, @"this must be subclassed");
    return 0;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSAssert(FALSE, @"this must be subclassed");
    return nil;
}

@end

并且:

@interface ViewController : AbstractViewControllerForCollectionView

@property (nonatomic, strong) NSString *myPropertyName;
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSArray *objects;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;

    NSLog(@"%@", [[self class] properties]);
}

+ (NSArray *)properties {
    NSMutableArray *propertyList = [NSMutableArray array];

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(self, &outCount);
    for(i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if (propName) {
            [propertyList addObject:[NSString stringWithUTF8String:propName]];
        }
    }
    free(properties);

    return propertyList;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.objects.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

    // configure cell

    return cell;
}
@end

这里唯一的缺点是,如果您未能子class 所需的方法,编译器不会警告您。但至少你会得到一个描述问题的运行时failure/warning。