I am setting up unit tests on my project to make sure that all UIViewController IBOutlets are connected to their respective Xib objects (i.e., are not nil after viewDidLoad.) I was considering applying a protocol to these UIViewControllers with a required function "getAllOutletNames", like so:
-(NSArray*)getAllOutletNames
{
return @[ @"outletproperty1", @"outletProperty2", ...];
}
...and then using [viewController valueForKey:outletName] to make sure none of these are nil. The problem with this is that it's a little unwieldy; "getAllOutletNames" has to be updated for each outlet added to the xib, which could easily be overlooked. I would prefer to do this in programmatic fashion, so that all IBOutlet properties can be automatically detected and iterated over.
I read in this NSHipster article (cmd+f for "attribute-backed attributes") that an attribute is applied to IBOutlets (or, an "attribute-backed attribute", which I don't quite understand.)
It looks like I can get a list of all properties in a class using part of this answer, and I can get their attributes using part of this answer. But, printing out the attributes from an IBOutlet versus a non-IBOutlet property using the following code, I don't find any difference:
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"
)
Non-IBOutlet
(
"T@\"UIView\"",
"&",
N,
"V_programmaticallySetupView"
)
Is there any way to access this "attribute-backed attribute" that the NSHipster article had mentioned or otherwise determine if a property is an IBOutlet programmatically, or am I barking up the wrong tree here?
Here's a trick I've used before to mark methods as special, it can be adopted to properties as well:
This works because of the distributed objects type encodings, documented here:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-BABHAIFA
You can use any of these to denote methods however you'd like, and as distributed objects don't exist on iOS, the compiler & runtime just ignore them.