7

How can I get an array of all UITextFields in a view controller?

EDIT: I do not want to hardcode the textfields into an array. I actually want to get the list inside the delegate of all the fields from the caller of that delegate.

2
  • Add them to an array when you create them??? Commented Jan 13, 2012 at 22:25
  • Please note that the delegate does not contain references to the textfields, it's the other way around and there's no way to find the fields from the delegate alone. developer.apple.com/library/ios/#documentation/uikit/reference/… Commented Jan 17, 2012 at 19:46

6 Answers 6

17

Recursive implementation to search all subviews' subviews: (this way you catch textfields embedded in uiscrollview, etc)

-(NSArray*)findAllTextFieldsInView:(UIView*)view{
    NSMutableArray* textfieldarray = [[[NSMutableArray alloc] init] autorelease];
    for(id x in [view subviews]){
        if([x isKindOfClass:[UITextField class]])
            [textfieldarray addObject:x];

        if([x respondsToSelector:@selector(subviews)]){
            // if it has subviews, loop through those, too
            [textfieldarray addObjectsFromArray:[self findAllTextFieldsInView:x]];
        }
    }
    return textfieldarray;
}

-(void)myMethod{
   NSArray* allTextFields = [self findAllTextFieldsInView:[self view]];
   // ...
 }
Sign up to request clarification or add additional context in comments.

11 Comments

Isn't this if([x respondsToSelector:@selector(subviews)]){ redundant as -subviews returns @property(nonatomic, readonly, copy) NSArray *subviews. Therefore any item in that array will be of type UIView or a subclass or UIView, which responds to @selector(subviews)
I'm just very shaky about throwing messages to objects for which I don't even know the class - what if some bonehead subclassed UIView in such a way that subviews contains non-UIView-inherited objects, and thus objects that don't respond to @selector(subviews)?
It doesn't really make sense to override the method and add non UIView's - if a user does they would most likely be clever enough to know why they are doing it and any risks that it may involve. At least that's what one would hope ;)
@jostster This solution doesn't require you hardcode an array. Any UITextField which is added to a view either through addSubview or Interface Builder automatically has the subviews array.
@Tim I am using your code with a few alterations. Basically I put findAllTextFieldsInView in my TextFieldDelegate class and in my views calling that on load. I will need to set a variable in TextFieldDelegate from the view to the controller so when the delegate calls findAllTextFieldsInView it will parse the controller. How can I do this? My controllers can be either a UIViewController or UITableViewController.
|
3

If you know you need an NSArray containing all the UITextField's then why not add them to an array?

NSMutableArray *textFields = [[NSMutableArray alloc] init];

UITextField *textField = [[UITextField alloc] initWithFrame:myFrame];

[textFields addObject:textField]; // <- repeat for each UITextField

If you are using a nib then use an IBOutletCollection

@property (nonatomic, retain) IBOutletCollection(UITextField) NSArray *textFields;

Then connect all the UITextField's to that array

4 Comments

hard coding them into an array is pointless... Defeats the purpose of me wanting to get an array of all textfields as I can just create it manually...
There is no hardcoding if you add the UITextField's to an NSMutableArray as and when you create them
I will be creating textfields based off data coming from an API so I won't know what text fields are there. I could just add them programmatically when I create them but I would prefer to just grab a list of fields that already exist instead of depending on a developer to add each field to an array.
Why add them and then in a second pass go and find them? That sounds very inefficient. If you want a reference to the UITextField add it to an array when you create it (and already have the reference).
1

-Use following code to get array that contains text values of all UITextField presented on View:

   NSMutableArray *addressArray=[[NSMutableArray alloc] init];

   for(id aSubView in [self.view subviews])
   {
           if([aSubView isKindOfClass:[UITextField class]])
           {
                  UITextField *textField=(UITextField*)aSubView;
                  [addressArray addObject:textField.text];
           }
   }
   NSLog(@"%@", addressArray);

Comments

1
extension UIView 
{
   class func getAllSubviewsOfType<T: UIView>(view: UIView) -> [T] 
   {
       return view.subviews.flatMap { subView -> [T] in
       var result = UIView.getAllSubviewsOfType(view: subView) as [T]
       if let view = subView as? T {
           result.append(view)
       }
       return result
     }
   }

   func getAllSubviewsWithType<T: UIView>() -> [T] {
       return UIView.getAllSubviewsOfType(view: self.view) as [T]
   }
}

How to use with Text Fields:

let textFields = self.view.getAllSubviewsWithType() as [UITextField]

Comments

-1

You can loop through the controller's view's subviews.

Here's a rough example:

NSMutableArray *arrOfTextFields = [NSMutableArray array];
for (id subView in self.view.subviews)
{
    if ([subView isKindOfClass:[UITextField class]])
       [arrOfTextFields addObject:subView]; 
}

1 Comment

This will not catch the UITextFields embedded in other views.
-1

EDIT Recursion without global variable (Just for Tim)

-(NSArray*)performUIElementSearchForClass:(Class)targetClass onView:(UIView*)root{

    NSMutableArray *searchCollection = [[[NSMutableArray alloc] init] autorelease];

    for(UIView *subview in root.subviews){

        if ([subView isKindOfClass:targetClass])  
            [searchCollection addObject:subview];

        if(subview.subviews.count > 0)
            [searchCollection addObjectsFromArray:[self performUIElementSearchForClass:targetClass onView:subview]];

    }

    return searchCollection;
}

3 Comments

I find myself often typing like this on SO: NSMutableArray ]alloc] init ]autorelease XCode spoils me so :P
This will not catch the UITextFields embedded in other views.
Recursion, but using a global variable? UNHOLY!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.