开发者

Find all controls of a type in a UIView

开发者 https://www.devze.com 2023-01-18 17:42 出处:网络
I am looking for a way to automatically localize texts on buttons/textfields etc and for this method I need to find all (for example) UIButton\'s on a UIView.

I am looking for a way to automatically localize texts on buttons/textfields etc and for this method I need to find all (for example) UIButton's on a UIView.

I tried the following 2 methods, but they both do no work like I want them to work:

for (UIView* subView in self.view.subviews)
{
    NSLog(@"object class : %@", [subView class]);

    if ([subView isMemberOfClass:[UIButton class]])
        NSLog(@"Button found!");
}

The problem with this piece of code is that a开发者_如何学Python RoundedRectButton does not match the UIButton class, while it really is just a UIButton.

I also tried the following:

for (UIButton* button in self.view.subviews)
{
// Do my stuff
}

But the stupid thing is, is that cocoa-touch actually just lists all subviews in that for-loop (also the UITextFields etc).

Is there a way to actually just get all UIButtons from a view? Or do I really need to find controls by looking at their selectors.


Why write one-off code like this when you can dial up the awesomeness by adding a category method to UIView using blocks? Take a look at the code at the very bottom. Using this recursive method with blocks you can do things like disable all UITextFields in a view controller's view:

[self.view forEachUITextFieldDoBlock:^(UITextField *textField) {
   textfield.enabled = NO;
}];

Or fade out all UITextFields in a view controller's view:

[UIView animateWithDuration:0.25 animations:^{

   [self.view forEachUITextFieldDoBlock:^(UITextField *textField) {
      textField.alpha = 0.0;
   }];

}
completion:^(BOOL finished){
   // nothing to do for now
}];

Blocks are pretty amazing in that you can even pass other methods inside a block. For example, the code below passes each UITextField found to my inserAdornmentImage:forTextView method, which adds a custom background image to each text view:

[self.view forEachUITextFieldDoBlock:^(UITextField *textField) {
    [self insertAdornmentImage:textFieldBGImage forTextField:textField];
}];

Blocks make the method incredibly flexible so you aren't having to write a specialized method each time you want to do something new with the controls you find. Here's the magic sauce:

@implementation UIView (Helper)

- (void) forEachUITextFieldDoBlock:(void (^)(UITextField *textField))block
{
   for (UIView *subview in self.subviews)
   {
      if ([subview isKindOfClass:[UITextField class]])
      {

        block((UITextField *)subview);

      } else {

         [subview forEachUITextFieldDoBlock:block];

      }
   }
}

@end


the first method is correct, except you need to change isMemberOfClass function to isKindOfClass:

isKindOfClass: Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号