Question

I have a UIPickerView where I have a Male and a Female option.

What I have is when I click on label, the UIPickerView is shown, and based on the selection in UIPickerView, the same text is shown on label.

All is working well, but tapping on UIPickerView is not working properly.

When I tap on UIPickerView,

  1. For iOS6, UIPickerView gets dismissed.

  2. For iOS7, UIPickerView DOESN'T get dismissed.

So what I wanted to do is to not dismiss UIPickerView when I click on it.

Any idea how to do that for iOS 6?

Dropbox link

Code

.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UIPickerViewDelegate, UIPickerViewDataSource>
@property (retain, nonatomic) IBOutlet UIPickerView *myPicker;
@property (retain, nonatomic) IBOutlet UILabel *myLabel;
@property (retain, nonatomic) IBOutlet NSMutableArray *arrayGender;
@end

.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize myPicker, myLabel, arrayGender;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    arrayGender = [[NSMutableArray alloc] init];
    [arrayGender addObject:@"Male"];
    [arrayGender addObject:@"Female"];

    myLabel.text = @"Choose gender...";

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideAllKeyboards)];
    tapGesture.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapGesture];

    myLabel.userInteractionEnabled = YES;
    UITapGestureRecognizer *tapGestureRecognizergenderLabel = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(genderLabelTapped)];
    tapGestureRecognizergenderLabel.numberOfTapsRequired = 1;
    [myLabel addGestureRecognizer:tapGestureRecognizergenderLabel];
    [tapGestureRecognizergenderLabel release];

    myPicker.hidden = NO;
}

-(void) genderLabelTapped {
    NSLog(@"genderLabelTapped");
    [myPicker reloadAllComponents];
    myPicker.hidden = NO;
}

-(IBAction)hideAllKeyboards {
    NSLog(@"hideAllKeyboards");
    myPicker.hidden = YES;
}

- (void)viewWillAppear:(BOOL)animated
{
    NSLog(@"viewWillAppear");
    [super viewWillAppear:animated];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void) dealloc {
    [myPicker release];
    [myLabel release];
    [super dealloc];
}

- (IBAction)takeMeBack:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark -
#pragma mark PickerView DataSource

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    NSLog(@"custom data..");
    if (IS_DEVICE_RUNNING_IOS_7_AND_ABOVE()) {
        //        NSLog(@"changing font...");
        UILabel *label;
        //        = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 233, 44)]; // your frame, so picker gets "colored"

            label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 233, 44)];


        label.textColor = [UIColor whiteColor];
        label.font = [UIFont fontWithName:@"Trebuchet MS" size:14];

        label.textAlignment = NSTextAlignmentCenter;

        label.text = [arrayGender objectAtIndex:row];

        return label;
    } else {
        //        NSLog(@"changing font...");
        UILabel *label;
        //        = [[UILabel alloc] initWithFrame:CGRectMake(40, 0, 193, 44)];
            label = [[UILabel alloc] initWithFrame:CGRectMake(40, 0, 193, 44)];

        label.backgroundColor = [UIColor clearColor];
        label.textColor = [UIColor blackColor];
        label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18];

            label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];

        label.text = [arrayGender objectAtIndex:row];

        return label;
    }
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [arrayGender count];
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return [arrayGender objectAtIndex:row];
}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
      inComponent:(NSInteger)component
{
    myLabel.text = [NSString stringWithFormat:@"%@", [arrayGender objectAtIndex:row]];
    myPicker.accessibilityValue = [NSString stringWithFormat:@"%@", [arrayGender objectAtIndex:row]];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

- (BOOL)shouldAutorotate
{
    return NO;
}

@end

I know because of gesture recognizer, picker is getting hided in iOS6. The problem is why it is not getting hided in iOS7?

Was it helpful?

Solution

Did you write this yourself if you just copy-pasted it from somewhere and you didn't know what it does so you came to Stack Overflow with close to zero research done? By close to zero research, I mean you didn't even read the code...

What do you think these lines do?

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideAllKeyboards)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];

-(IBAction)hideAllKeyboards {
     NSLog(@"hideAllKeyboards");
     myPicker.hidden = YES;
}

It turns out, when a touch happens (on the pickerview) in iOS7, the view that catches the tap is of class UIPickerTableViewWrapperCell, while in iOS6, it's of class UIPickerTableView (if not tapping on a row) or UITableViewCellContentView (when tapping on a row). My guess is, the later two let the tap pass through as if the tap happened on their superview (in your case, self.view). <- The last sentence is just a guess, not for sure.

The way you can make sure the picker only gets hidden in case the tap happened on self.view is to set a delegate self as delegate to tapGesture, then implement the gestureRecognizer:shouldReceiveTouch method:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (touch.view == self.view) {
        return YES;
    } else {
        return NO;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top