Monday, January 13, 2014

Objective C - Iterate over class properties and access property by class type for iOS

I needed a way to add an input accessory on some of my view controllers that have properties for many UITextView and UITextField properties. I didn't want to do it one at a time, I could miss one, or if I added or deleted one I would have to fix that manually as well.

So, I needed a way to walk the properties of my view controller, find all of the UITextView and UITextField properties, and call the method to set the input accessory view.

Here is the resulting code:


+ (NSArray *)allPropertyNamesFor: (id)target
{
    unsigned count;
    objc_property_t *properties = class_copyPropertyList([target class], &count);
    
    NSMutableArray *results= [NSMutableArray array];
    
    unsigned i;
    for (i = 0; i < count; i++)
    {
        objc_property_t property = properties[i];
        NSString *name = [NSString stringWithUTF8String:property_getName(property)];
        [results addObject:name];
    }
    
    free(properties);
    
    return results;
}



+ (void) attachToSubViewsOf: (NSObject *) target withAccessoryView: (UIView *)accesoryView {
    
    NSArray *properties = [self allPropertyNamesFor:target];
    
    for (NSString *propertyName in properties) {
        
        SEL sel =  NSSelectorFromString(propertyName);
        
        if ([target respondsToSelector:sel]) {
            
            id results = [target performSelector:sel withObject:nil];
            
            if( ([results isKindOfClass:[UITextView class]]) || ([results isKindOfClass:[UITextField class]]) ) {
                
                SEL setInputAccessoryViewSel = sel_registerName("setInputAccessoryView:");
                if ([results respondsToSelector:setInputAccessoryViewSel]) {
                    
                    [results performSelector:setInputAccessoryViewSel withObject:accesoryView];
                }
                
            }

        }
        
    }
    
}




No comments: