【问题标题】:How to detect if a property is an IBOutlet programmatically at runtime?如何在运行时以编程方式检测属性是否为 IBOutlet?
【发布时间】:2015-06-15 18:12:17
【问题描述】:

我正在我的项目上设置单元测试,以确保所有 UIViewController IBOutlets 都连接到它们各自的 Xib 对象(即,在 viewDidLoad 之后不为零。)我正在考虑将协议应用于这些 UIViewControllers 具有所需的功能“ getAllOutletNames”,像这样:

-(NSArray*)getAllOutletNames
{
    return @[ @"outletproperty1", @"outletProperty2", ...];
}

...然后使用 [viewController valueForKey:outletName] 确保这些都不为零。问题在于它有点笨拙。必须为添加到 xib 的每个出口更新“getAllOutletNames”,这很容易被忽略。我更喜欢以编程方式执行此操作,以便可以自动检测和迭代所有 IBOutlet 属性。

我在this NSHipster article(cmd+f 表示“属性支持的属性”)中读到,一个属性应用于 IBOutlets(或者,一个“属性支持的属性”,我不太明白。)

看起来我可以使用this answer 的一部分来获取一个类中所有属性的列表,并且我可以使用this answer 的一部分来获取它们的属性。但是,使用以下代码从 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"
)

非 IBOutlet

(
    "T@\"UIView\"",
    "&",
    N,
    "V_programmaticallySetupView"
)

有什么方法可以访问 NSHipster 文章中提到的这个“属性支持的属性”,或者以其他方式确定一个属性是否是 IBOutlet 编程,还是我在这里找错了树?

【问题讨论】:

  • 在 1 到 10 的范围内,你对 Objective-C++ 有多害怕?如果你在乎,我确实有解决方案。
  • 不要太害怕,事实上我喜欢任何了解内部结构的机会 :) 所以可能是 3/10?

标签: objective-c unit-testing properties objective-c-runtime


【解决方案1】:

这是我之前用来将方法标记为特殊的技巧,它也可以用于属性:

#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

这是因为分布式对象类型编码,记录在这里:

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-BABHAIFA

您可以使用其中任何一个来表示您喜欢的方法,并且由于 iOS 上不存在分布式对象,编译器和运行时会忽略它们。

【讨论】:

  • 很有趣,也很聪明!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
  • 2012-12-31
  • 1970-01-01
  • 2010-11-14
  • 2010-12-10
  • 2012-03-17
  • 1970-01-01
相关资源
最近更新 更多