如何在运行时以编程方式检测 属性 是否为 IBOutlet?
How to detect if a property is an IBOutlet programmatically at runtime?
我正在对我的项目设置单元测试,以确保所有 UIViewController IBOutlets 都连接到它们各自的 Xib 对象(即,在 viewDidLoad 之后不是 nil。)我正在考虑对这些 UIViewControllers 应用一个协议函数 "getAllOutletNames",像这样:
-(NSArray*)getAllOutletNames
{
return @[ @"outletproperty1", @"outletProperty2", ...];
}
...然后使用 [viewController valueForKey:outletName] 确保其中 none 为零。这样做的问题是它有点笨拙。 "getAllOutletNames" 必须为每个添加到 xib 的插座更新,这很容易被忽视。我更愿意以编程方式执行此操作,以便可以自动检测和迭代所有 IBOutlet 属性。
我在 this NSHipster article("attribute-backed attributes" 的 cmd+f)中读到一个属性应用于 IBOutlets(或者 "attribute-backed attribute",我不太明白。)
看来我可以使用 this answer, and I can get their attributes using part of this answer 的一部分获得 class 中所有属性的列表。但是,使用以下代码打印出 IBOutlet 与非 IBOutlet 属性 的属性,我没有发现任何区别:
const char * type = property_getAttributes(class_getProperty([self class], [outletName UTF8String]));
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString componentsSeparatedByString:@","];
NSLog(@"%@",attributes);
IBOutlet
(
"T@\"UILabel\"",
"&",
N,
"V_titleLabel"
)
非 IB 出口
(
"T@\"UIView\"",
"&",
N,
"V_programmaticallySetupView"
)
有没有什么方法可以访问 NSHipster 文章提到的这个 "attribute-backed attribute" 或者以其他方式确定 属性 是否是一个 IBOutlet 编程,或者我在这里咆哮错误的树?
这是我以前用来将方法标记为特殊的技巧,它也可以应用于属性:
#import <objc/runtime.h>
#define synthesize_nooutlet(name) \
synthesize name=_ ## name; \
- (oneway id)name { \
return _ ## name; \
}
@interface ViewController ()
@property (nonatomic, strong) UIView *theView;
@end
@implementation ViewController
@synthesize_nooutlet(theView);
- (void) viewDidLoad {
[super viewDidLoad];
[self.theView setBackgroundColor:[UIColor clearColor]];
char returnType;
method_getReturnType(class_getInstanceMethod([self class], @selector(theView)), &returnType, 1);
if (returnType == 'V') {
// Do stuff
}
}
@end
这是因为分布式对象类型编码,记录在这里:
您可以根据需要使用其中任何一个来表示方法,并且由于 iOS 上不存在分布式对象,编译器和运行时会忽略它们。
我正在对我的项目设置单元测试,以确保所有 UIViewController IBOutlets 都连接到它们各自的 Xib 对象(即,在 viewDidLoad 之后不是 nil。)我正在考虑对这些 UIViewControllers 应用一个协议函数 "getAllOutletNames",像这样:
-(NSArray*)getAllOutletNames
{
return @[ @"outletproperty1", @"outletProperty2", ...];
}
...然后使用 [viewController valueForKey:outletName] 确保其中 none 为零。这样做的问题是它有点笨拙。 "getAllOutletNames" 必须为每个添加到 xib 的插座更新,这很容易被忽视。我更愿意以编程方式执行此操作,以便可以自动检测和迭代所有 IBOutlet 属性。
我在 this NSHipster article("attribute-backed attributes" 的 cmd+f)中读到一个属性应用于 IBOutlets(或者 "attribute-backed attribute",我不太明白。)
看来我可以使用 this answer, and I can get their attributes using part of this answer 的一部分获得 class 中所有属性的列表。但是,使用以下代码打印出 IBOutlet 与非 IBOutlet 属性 的属性,我没有发现任何区别:
const char * type = property_getAttributes(class_getProperty([self class], [outletName UTF8String]));
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString componentsSeparatedByString:@","];
NSLog(@"%@",attributes);
IBOutlet
(
"T@\"UILabel\"",
"&",
N,
"V_titleLabel"
)
非 IB 出口
(
"T@\"UIView\"",
"&",
N,
"V_programmaticallySetupView"
)
有没有什么方法可以访问 NSHipster 文章提到的这个 "attribute-backed attribute" 或者以其他方式确定 属性 是否是一个 IBOutlet 编程,或者我在这里咆哮错误的树?
这是我以前用来将方法标记为特殊的技巧,它也可以应用于属性:
#import <objc/runtime.h>
#define synthesize_nooutlet(name) \
synthesize name=_ ## name; \
- (oneway id)name { \
return _ ## name; \
}
@interface ViewController ()
@property (nonatomic, strong) UIView *theView;
@end
@implementation ViewController
@synthesize_nooutlet(theView);
- (void) viewDidLoad {
[super viewDidLoad];
[self.theView setBackgroundColor:[UIColor clearColor]];
char returnType;
method_getReturnType(class_getInstanceMethod([self class], @selector(theView)), &returnType, 1);
if (returnType == 'V') {
// Do stuff
}
}
@end
这是因为分布式对象类型编码,记录在这里:
您可以根据需要使用其中任何一个来表示方法,并且由于 iOS 上不存在分布式对象,编译器和运行时会忽略它们。