5

Iterating over all UIViews in the subviews of a class and then checking the type in the loop using isKindOfClass made my code look redundant. So I wrote the following method which executes a block for each subview.

@implementation Util

+ (void)iterateOverSubviewsOfType:(Class)viewType 
                   view:(UIView*)view
                   blockToExecute:(void (^)(id subview))block
{
    for (UIView* subview in view.subviews) {
        if ([subview isKindOfClass:viewType]) {
            block(subview);
        }
    }
}

@end

The block passed to this method takes an argument of type id. The type used here should be of course the same as passed as the first argument. However so far I haven't figured out a way to make this more type safe.

Nils
  • 13,319
  • 19
  • 86
  • 108

1 Answers1

11

Try it like this, should be safe enough.

for (id subview in view.subviews) {
        if ([subview isMemberOfClass:viewType]) {
            block(subview);
        }
    }
Kyr Dunenkoff
  • 8,090
  • 3
  • 23
  • 21
  • I agree that I should use isMemberOfClass instead of isKindOfClass. However the problem I was pointing to is more that I could pass a block which takes an argument of any type. Where the argument must be of kind UIView or derived from it. More specifically it must be of the same class as the viewType passed to the method. – Nils Jan 25 '12 at 09:54
  • 1
    Then you'll have to pass class to block as well and check for class safety inside the block. The other way is to use `typeof(class) subview` in your block argument, but that will make your method dependent of some external variable. – Kyr Dunenkoff Jan 25 '12 at 10:20
  • That doesn't sound very elegant. So you would not change anything on the method above? – Nils Jan 25 '12 at 10:51
  • No. By far, the solution you have is the most elegant and safe at the same time. – Kyr Dunenkoff Jan 25 '12 at 11:56