Finding Subview of a Particular Class in Cocoa

Many of the UIView subclasses in Cocoa, and especially Cocoa Touch are created by combining many different simple views into a more complex view. UITableViewCell is a good example, concisting of almost a dozen subviews, UIImageView for the image, UILabel for the text, etc.

It is often nice to be able to reuse existing functionality when you subclass UITableViewCell. Properties such as image and textColor maps directly to the embedded UILabel and UIImageView subviews, and reimplementing them all when introducing a custom layout is tedious and error prone. Would it not be better to be able to get access to the original subview instances and just add a custom layout to them?

You can find subviews by class

Would it not be nice if the Cocoa Touch framework had a method such as this:

- (UIView*)viewWithKindOfClass:(Class)aClass;

Kind of like what viewWithTag:, does but instead of searching for a subview matching a tag, it searches for a subview matching a class.

Good news for us is that this is very easy to implement, by just adding a new category to UIView. Add a new .h/.m file pair to your Xcode project and type this down in the header file:


@interface UIView (CWViewWithKindOfClass)

- (UIView*)viewWithKindOfClass:(Class)aClass;


Now we have to implement it. The existing viewWithTag: method is not documented as such, but my experimentation tells me that it uses a breadth first search algorithm. Quite logical as the wanted subview most commonly is close to the root view, and we want to find it fast. Since viewWithTag: always returns the first found matching view, we can do the same assumption.

The quite short implementation goes like this:

#import "UIView+CWViewWithKindOfClass.h"

@implementation UIView (CWViewWithKindOfClass)

- (UIView*)viewWithKindOfClass:(Class)aClass;
  NSMutableArray* nodeQueue = [NSMutableArray arrayWithObject:self];
  while ([nodeQueue count] > 0) {
    UIView* node = [nodeQueue objectAtIndex:0];
    [nodeQueue removeObjectAtIndex:0];
    if ([node isKindOfClass:aClass]) {
      return node;
    } else {
      [nodeQueue addObjectsFromArray:node.subviews];
  return nil;


And that is it, not you can use it with something like for example this:

UITabBar* tabBar = [myTabBarController.view viewWithKindOfClass:[UITabBar class]];

Wich is an introduction to a future post, where I will discuss how to access the managed UITabBar of a UITabBarController, and introduce a UITabBarDelegate without interfering with the delegate already in place from the Cocoa Touch framework.

This Post Has 8 Comments

  1. Sara

    Using the above method, I was able to get the UITabBar and hide it. I have a question though. After hiding the UITabBar, do you know how to resize the rest of the view?


  2. Jonah

    Sara, Can you show us the code for how you were able to use this method to hide your UITabBar?

  3. satya


    I have a Tabbarcontroller that contains a navigation controller which inturn contains a tableview controller .Upon selection in tableview controller I push another Tablview controller which should always be shown in landscape mode only.But my view doesnt rotate to landscape. Earlier it worked fine when I have only navigation controller. Now as my UI changed I had to put my Nav controller in a Tab controller.

    Can you tell me what could be the problem?


  4. No one in particular

    > *Many of the UIView subclasses in Cocoa, and especially Cocoa Touch*

    Cocoa doesn’t have UIView.

  5. maya

    How I can touch one image that can jump to other view?

  6. Cool Techie

    I am expecting more than one subviews of particular class, hence I just modified
    [self.view.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger index, BOOL *stop) {
    BOOL state = [view isKindOfClass:[TouchImageView class]];
    if (state) {
    //add to subview array

  7. Ed H

    Nice looping algo. I like it.

  8. lukenothing

    Terrific !!!

Leave a Reply