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.
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.
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]];
// ...
}
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)UIView in such a way that subviews contains non-UIView-inherited objects, and thus objects that don't respond to @selector(subviews)?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 ;)addSubview or Interface Builder automatically has the subviews array.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
UITextField's to an NSMutableArray as and when you create themUITextField add it to an array when you create it (and already have the reference).-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);
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]
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];
}
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;
}
NSMutableArray ]alloc] init ]autorelease XCode spoils me so :P