如果来自 UIViewController 的对象如何仅获取我创建的自定义属性的名称(在 运行 时间内)?
If object from UIViewController how get only the names of custom properties that I created (in run time)?
我在定义为符合 UICollectionViewDelegate
和 UICollectionViewDataSource
的视图控制器中实现了以下代码:
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]];
}
}
当我这样做时,我不仅会看到我的自定义属性,还会看到这些协议引入的一些属性,即:hash
、superclass
、description
和 debugDescription
.
如何只显示子类的属性,而不显示那些协议引入的属性?
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 定义为符合 UICollectionViewDataSource
和 UICollectionViewDelegate
。因此,这些协议 引入的属性 被解释为您的 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。
我在定义为符合 UICollectionViewDelegate
和 UICollectionViewDataSource
的视图控制器中实现了以下代码:
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]];
}
}
当我这样做时,我不仅会看到我的自定义属性,还会看到这些协议引入的一些属性,即:hash
、superclass
、description
和 debugDescription
.
如何只显示子类的属性,而不显示那些协议引入的属性?
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 定义为符合 UICollectionViewDataSource
和 UICollectionViewDelegate
。因此,这些协议 引入的属性 被解释为您的 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。