UIPickerView Only Responds Within Area of Tab Bar - ios

I'm updating my app to iOS 8 and trying to recreate the UIPickerView inside a UIActionSheet with UIAlertController as described here. Using the answer from Nada Gamal, I was able to recreate the functionality, but the UIPickerView only responds within the tab bar (even though the tab bar is hidden behind the picker view). The tab bar controller is the root view controller.
-(void)loadPickerView{
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
pickerView.backgroundColor = [UIColor whiteColor];
[pickerView selectRow:pickerViewRow inComponent:0 animated:NO];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
pickerToolbar.tintColor = self.navigationController.navigationBar.tintColor;
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissActionSheet)];
[barItems addObject:doneBtn];
[pickerToolbar setItems:barItems animated:YES];
UIAlertController * searchActionSheet=[UIAlertController alertControllerWithTitle:#"" message:#"" preferredStyle:UIAlertControllerStyleActionSheet];
[ searchActionSheet.view setBounds:CGRectMake(8, 208, self.view.frame.size.width, pickerView.frame.size.height+pickerToolbar.frame.size.height)];
[searchActionSheet.view addSubview:pickerToolbar];
[searchActionSheet.view addSubview:pickerView];
[self presentViewController:searchActionSheet animated:YES completion:nil];
}
The presentViewController in the last line seems to be the issue. I've tried many different ways to get the pickerView to respond outside the tab bar area, including:
self
self.tabBarController
self.navigationController (pickerView doesn't show up at all)
[[UIApplication sharedApplication] keyWindow].rootViewController
The other option is to make a separate view controller for this, but I'm concerned that won't work either because UIAlertController is a subclass of UIViewController, but perhaps this is an issue with adding subviews to UIAlertController.

Related

Dynamically created UIBarButtonItem doesn't trigger on tap

I've got a UIPickerView that has a UIToolbar attached to it on the parent view's load with this code:
- (void)viewDidLoad {
[super viewDidLoad];
self.itemSortPicker.hidden = false;
pickerData = #[#"Name",#"Item Level",#"Crafting Level",#"Profit",#"Profit Percentage",#"Sell Price",#"Buy Price",#"Supply",#"Demand",#"Rarity"];
self.itemSortPicker.dataSource = self;
self.itemSortPicker.delegate = self;
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerToolbar.barStyle = UIBarStyleDefault;
[pickerToolbar sizeToFit];
[pickerToolbar setFrame:CGRectMake(0, -pickerToolbar.bounds.size.height, 320, 44)];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(pickerCancel)];
[barItems addObject:cancelBtn];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone)];
[barItems addObject:doneBtn];
[pickerToolbar setItems:barItems animated:YES];
CGRect pickerRect = self.itemSortPicker.bounds;
self.itemSortPicker.bounds = pickerRect;
self.itemSortPicker.frame = CGRectMake(0, 44, 320, 216);
[self.itemSortPicker addSubview:pickerToolbar];
}
Now the problem is, when I tap on either the 'done' or 'cancel' buttons, the associated method doesn't trigger. The method doesn't take any parameters and just does an NSLog action. The PickerView isn't taking focus from the bar because when I tap and drag on the buttons, the PickerView doesn't change.
The problem is that the UIToolbar isn't entirely inside the frame of the UIPickerView. As your code is written, although UIToolbar is a subview of UIPickerView, the toolbar is -pickerToolbar.bounds.size.height above the UIPickerView:
[pickerToolbar setFrame:CGRectMake(0, -pickerToolbar.bounds.size.height, 320, 44)];
so you're unable to interact with its buttons because it's hanging off the edge of its superview's frame. For example, if you changed the pickerToolbar frame like so:
[pickerToolbar setFrame:CGRectMake(0, 0, 320, 44)];
you should be able to interact with it.
If you need this specific placement -pickerToolbar.bounds.size.height above the UIPickerView though, I suggest not adding it as a subview to UIPickerView and placing it appropriately as a subview to UIPickerView's superview instead. In general, if you need to interact with a subview it needs to be entirely within its superview's frame.
Edit: In this case, if you're going to instead add the toolbar to the superview, like so:
[self.view addSubview:pickerToolbar];
I suggest trying out this frame to maintain your original placement:
[pickerToolbar setFrame:CGRectMake(self.itemSortPicker.frame.origin.x, self.itemSortPicker.frame.origin.y - pickerToolbar.bounds.size.height, 320, 44)];
(To calculate this new frame, I've added the UIPicker's x and y origin values to the frame's x and y to adjust for the change in the view's coordinate system.)
I'm not sure of wether the problem is because of the button or the toolbar itself nor the pickerview but a better way of doing this is to do it all programmatically and you have to remove the pickerview from the view:
- (void)viewDidLoad {
[super viewDidLoad];
pickerData = #[#"Name",#"Item Level",#"Crafting Level",#"Profit",#"Profit Percentage",#"Sell Price",#"Buy Price",#"Supply",#"Demand",#"Rarity"];
UIPickerView *itemSortPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 320, 162)];
itemSortPicker.dataSource = self;
itemSortPicker.delegate = self;
itemSortPicker.showsSelectionIndicator = YES;
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(pickerCancel)];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone)];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[pickerToolbar setBarStyle:UIBarStyleDefault];
[pickerToolbar sizeToFit];
[toolBar setItems:#[cancelBtn,flexSpace,doneBtn]];
BlaBlaTextField.delegate = self;
BlaBlaTextField.inputView = itemSortPicker;
BlaBlaTextField.inputAccessoryView = pickerToolbar;
}
And not to forget your pickerCancel and pickerDone functions, and of course the delegate methods of your itemSortPicker.
I hope that solves your problem.

DatePicker does not show on input click on iOS 8

I am showing pickerView on input field click it worked fine on other iOS but when I updated to iOS 8 it did not work. When i click on input field it does not show up the date picker.
Here is the code I am using.
- (void)textFieldDidBeginEditing:(UITextField *)aTextField{
appDelegate.recentAddSowID = #"";
if (aTextField == dateTextField) {
[dateTextField resignFirstResponder];
pickerViewPopup = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"" destructiveButtonTitle:nil otherButtonTitles:nil];
pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 0, 0)];
pickerView.datePickerMode=UIDatePickerModeDate;
pickerView.hidden = NO;
pickerView.date = [NSDate date];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonPressed:)];
[barItems addObject:doneBtn];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelButtonPressed:)];
[barItems addObject:cancelBtn];
[pickerToolbar setItems:barItems animated:YES];
[pickerViewPopup addSubview:pickerToolbar];
[pickerViewPopup addSubview:pickerView];
[pickerView addTarget:self action:#selector(updateTextField:) forControlEvents:UIControlEventValueChanged];
[dateTextField setInputView:pickerView];
[pickerViewPopup showInView:self.view];
[pickerViewPopup setBounds:CGRectMake(0,0,320, 464)];
}
}
I am testing on iPhone 5S.
They changed the implementation of UIActionSheet in iOS 8. You can no longer add views to its view hierarchy
The documentation (https://developer.apple.com/library/ios/documentation/uikit/Reference/UIActionSheet_Class/index.html) states:
UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy. If you need to present a sheet with more customization than provided by the UIActionSheet API, you can create your own and present it modally with presentViewController:animated:completion:.
Also, the UIActionSheet is deprecated in iOS 8
Important: UIActionSheet is deprecated in iOS 8. (Note that UIActionSheetDelegate is also deprecated.) To create and manage action sheets in iOS 8 and later, instead use UIAlertController with a preferredStyle of UIAlertControllerStyleActionSheet.
As an alternative, try this: https://github.com/skywinder/ActionSheetPicker-3.0. It works with iOS 8 and might be what you need
Source: Add UIPickerView in UIActionSheet from IOS 8 not working

ios 6: UIDatePicker in the UITextField

I have problems with connecting datepicker with text field. I have tried all solution from stackoverflow but they don't work in ios 6. Can you desribe how to make it, I want to tap on text field and choose date via datepicker.
You should use the inputView property of your UITextField to make the picker show in place of the keyboard. iOS6 will take care of everything for you then (showing the picker with the animation instead of the keyboard, etc).
Note: You will probably want to add some inputAccessoryView too (generally an UIToolBar with some "OK" button in it) to make the user be able to dismiss the picker (the IBAction of your "OK" button will simply call [textField resignFirstResponder] for that to happen of course) as an UIDatePicker does not have any button to validate your input (whereas the keyboard has its "Return Key")
#import "TextfieldwithDatepickerViewController.h"
UIActionSheet *pickerViewPopup;
#implementation TextfieldwithDatepickerViewController
- (void)textFieldDidBeginEditing:(UITextField *)aTextField{
[aTextField resignFirstResponder];
pickerViewPopup = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
UIDatePicker *pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 0, 0)];
pickerView.datePickerMode = UIDatePickerModeDate;
pickerView.hidden = NO;
pickerView.date = [NSDate date];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonPressed:)];
[barItems addObject:doneBtn];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelButtonPressed:)];
[barItems addObject:cancelBtn];
[pickerToolbar setItems:barItems animated:YES];
[pickerViewPopup addSubview:pickerToolbar];
[pickerViewPopup addSubview:pickerView];
[pickerViewPopup showInView:self.view];
[pickerViewPopup setBounds:CGRectMake(0,0,320, 464)];
}
-(void)doneButtonPressed:(id)sender{
//Do something here here with the value selected using [pickerView date] to get that value
[pickerViewPopup dismissWithClickedButtonIndex:1 animated:YES];
}
-(void)cancelButtonPressed:(id)sender{
[pickerViewPopup dismissWithClickedButtonIndex:1 animated:YES];
}

Pickerview for TextField

I have this code, it's inside an action that it's triggered when the user selects the textfield to show the datepicker:
pickerViewPopup = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 0, 0)];
pickerView.datePickerMode = UIDatePickerModeDateAndTime;
pickerView.hidden = NO;
pickerView.date = [NSDate date];
UIToolbar *pickerToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerToolbar.barStyle = UIBarStyleBlackTranslucent;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneButtonPressed:)];
[barItems addObject:doneBtn];
[pickerToolbar setItems:barItems animated:YES];
[pickerViewPopup addSubview:pickerToolbar];
[pickerViewPopup addSubview:pickerView];
[pickerViewPopup showFromTabBar:self.tabBarController.tabBar];
[pickerViewPopup setBounds:CGRectMake(0,0,320, 500)];
I was using this code in an app with a tab bar for navigation. Now I would like to use it in an app without it, but when the process reaches [pickerViewPopup showFromTabBar:self.tabBarController.tabBar]; it crashes.
Any idea on how I could fix it?
Use one of the following,
– showFromToolbar:
– showInView:
– showFromBarButtonItem:animated:
– showFromRect:inView:animated:
For eg:-
[pickerViewPopup showFromToolbar:pickerToolbar];
The problem was that you dont have a tab bar and you are trying to access the tab bar object to show the picker from it. Since tabbar is nil for you, it will crash.
For more details check the apple documentation.

How to get a UIBarButtonSystemItem on a UIToolBar to take me to another view

Accept my early apologies as totally new to this so my terminology may not be accurate, hope you can understand what it is that i'm asking.
I am having issues getting a UIBarButtonSystemItem to take me back to a different view when pushed. I have defined a UIToolBar with a UIBarButtonSystemItem on it which compiles and works perfectly. However, when the button is pushed the app crashes.
This is the code i have used to define the UIToolBar and UIButton:
//create toolbar using new
toolbar = [UIToolbar new];
toolbar.barStyle = UIBarStyleBlackTranslucent;
[toolbar sizeToFit];
toolbar.frame = CGRectMake(0, 410, 320, 50);
//Add buttons
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction
target:self
action:#selector(pressButton1:)];
I have then added flexitem to this and added the button to the array using the following code:
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
//Add buttons to the array
NSArray *items = [NSArray arrayWithObjects: systemItem1, flexItem, nil];
This is where I fall down and I have attempted to get the button to take me to a previous view when pushed by using the following code:
-(void)pressButton1:(id)sender {
BMR_TDEE_CalculatorViewController *controller1 = [[BMR_TDEE_CalculatorViewController alloc] initWithNibName:#"BMR_TDEE_ViewController" bundle:nil];
controller1.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller1 animated:YES];
[controller1 release];
}
Like I said, this just crashes my simulator. It compiles without issue but Im guessing the code is fundamentally wrong as i am new to this. Any help explained dumbed down would be fantastic ;-)
Thanks All
This:
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(pressButton1:)
should be:
UIButton *button=[[UIButton alloc] init];
button.frame=CGRectMake(0, 0, 65, 32);
[button addTarget:self action:#selector(pressButton1:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
For the (void)pressbutton code it should now be:
-(IBAction)pressButton1:(id)sender {
BMR_TDEE_CalculatorViewController *controller = [[BMR_TDEE_CalculatorViewController alloc] initWithNibName:#"BMR_TDEE_CalculatorViewController" bundle:nil];
[self.navigationController presentModalViewController:controller animated:TRUE];
}

Resources