Showing a UIPickerView with UIActionSheet in iOS8 not working
Solution 1
From the reference for UIActionSheet:
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:.
My guess is your seeing exactly why.
The reference for UIAlertController doesn't have a similar disclaimer, but looking at its interface, my guess is Apple will add it before release.
My recommendation would be to just create a small view containing your picker and buttons and show and hide it as needed. It's not that hard to do and your not pushing interfaces beyond their intended uses.
Solution 2
I write the time picker by my self instead UIActionSheet in iOS8:
date = [NSDate date];
timePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 0, 0)];
timePicker.datePickerMode = UIDatePickerModeDateAndTime;
timePicker.hidden = NO;
timePicker.date = date;
displayFormatter = [[NSDateFormatter alloc] init];
[displayFormatter setTimeZone:[NSTimeZone localTimeZone]];
[displayFormatter setDateFormat:@"MM月dd日 EEE HH:mm"];
formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone localTimeZone]];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
startDisplayTimeString = [displayFormatter stringFromDate:timePicker.date];
startTimeString = [formatter stringFromDate:timePicker.date];
NSTimeInterval interval = 24*60*60*1;
NSDate *endDate = [[NSDate alloc] initWithTimeIntervalSinceNow:interval];
endDisplayTimeString = [displayFormatter stringFromDate:endDate];
endTimeString = [formatter stringFromDate:endDate];
[_startTimeLabel setText:startDisplayTimeString];
[_endTimeLabel setText:endDisplayTimeString];
[pickerViewPopup dismissWithClickedButtonIndex:1 animated:YES];
NSDateFormatter *dateFormatter =[[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 64)];
pickerToolbar.tintColor = [UIColor whiteColor];
[pickerToolbar sizeToFit];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelBtnPressed:)];
[cancelBtn setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:253.0/255.0 green:68.0/255.0 blue:142.0/255.0 alpha:1.0],
NSForegroundColorAttributeName,
nil] forState:UIControlStateNormal];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *titleButton;
float pickerMarginHeight = 168;
titleButton = [[UIBarButtonItem alloc] initWithTitle:@"title" style:UIBarButtonItemStylePlain target: nil action: nil];
[titleButton setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:253.0/255.0 green:68.0/255.0 blue:142.0/255.0 alpha:1.0],
NSForegroundColorAttributeName,
nil] forState:UIControlStateNormal];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:@"OK" style:UIBarButtonItemStyleDone target:self action:@selector(setTimePicker)];
[doneBtn setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:253.0/255.0 green:68.0/255.0 blue:142.0/255.0 alpha:1.0],
NSForegroundColorAttributeName,
nil] forState:UIControlStateNormal];
NSArray *itemArray = [[NSArray alloc] initWithObjects:cancelBtn, flexSpace, titleButton, flexSpace, doneBtn, nil];
[pickerToolbar setItems:itemArray animated:YES];
if(iPad){
[pickerToolbar setFrame:CGRectMake(0, 0, 320, 44)];
UIViewController* popoverContent = [[UIViewController alloc] init];
popoverContent.preferredContentSize = CGSizeMake(320, 216);
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 216)];
popoverView.backgroundColor = [UIColor whiteColor];
[popoverView addSubview:timePicker];
[popoverView addSubview:pickerToolbar];
popoverContent.view = popoverView;
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[popoverController presentPopoverFromRect:CGRectMake(0, pickerMarginHeight, 320, 216) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}else{
timeBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-300, 320, 246)];
[timeBackgroundView setBackgroundColor:[UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0]];
[timeBackgroundView addSubview:pickerToolbar];
[timeBackgroundView addSubview:timePicker];
[self.view addSubview:timeBackgroundView];}
Solution 3
UIActionSheet is depricated in iOS8. Use UIAlertController for iOS8 or later
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"
message:@"This is an action shhet."
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* cameraAction = [UIAlertAction actionWithTitle:@"Take A Photo" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
UIAlertAction* galleryAction = [UIAlertAction actionWithTitle:@"From Gallery" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
UIAlertAction * defaultAct = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {}];
[alert addAction:cameraAction];
[alert addAction:galleryAction];
[alert addAction:defaultAct];
[self presentViewController:alert animated:YES completion:nil];
Ref : UIAlertController
Example : https://github.com/KiritVaghela/UIAlertController
Solution 4
swift 5
You can use an UIAlertController
to do this.
@IBAction func btnActionDate(_ sender: Any) {
let picker = UIPickerView(frame: CGRect(x: 0, y: 50, width: self.view.frame.size.width - 16.0, height: 150))
picker.delegate = self
picker.dataSource = self
// let message = "\n\n\n\n\n\n"
let alert = UIAlertController(title: "Title of Action Sheet", message: "", preferredStyle: UIAlertController.Style.actionSheet)
alert.isModalInPopover = true
picker.reloadAllComponents()
//Add the picker to the alert controller
alert.view.addSubview(picker)
// For setting height of Action sheet
let height:NSLayoutConstraint = NSLayoutConstraint(item: alert.view!, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 350)
alert.view.addConstraint(height)
let okAction = UIAlertAction(title: "Done", style: .default, handler: {
(alert: UIAlertAction!) -> Void in
let fetchedObj = picker.selectedRow(inComponent: 0)
})
alert.addAction(okAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
Set the delegates & data source of pickerView like this
class MyViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
set the delegate & datasource functions
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arrayMonthData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arrayMonthData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
return self.view.frame.size.width - 16.0
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 36.0
}
Solution 5
I have faced the same issue and solved it by this way it will work in all ios version
In ios 8 apple has changed so many things i here faced one problem in my own project so , i just want to provide the solution in replacement of UIActionsheet
.
in ios 8 UIActionsheet
deprecated as well its delegate methods also deprecated. Instead of that UIAlertController
with prefferedstyle
UIAlertControllerStyleActionSheet
is used. you can check this thread as well:
https://developer.apple.com/library/ios/documentation/Uikit/reference/UIActionSheet_Class/index.html
This example will work both in ios 8 and previous version of it.
in .h file declare this variable
@interface demoProfileForBuyer{
UIActionSheet *ac_sheet_fordate;
UIToolbar *pickerToolBar_fordate;
UIDatePicker *optionPickerDate;
UIAlertController *alertController;
}
in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
pickerToolBar_fordate = [[UIToolbar alloc] initWithFrame:CGRectMake(-8, 0, 320, 44)];
pickerToolBar_fordate.barStyle = UIBarStyleBlack;
[pickerToolBar_fordate sizeToFit];
NSMutableArray *barItemsDate = [[NSMutableArray allkioc] init];
UIBarButtonItem *flexSpaceDate = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItemsDate addObject:flexSpaceDate];
UIBarButtonItem *doneBtnDate = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(pickerViewDoneBirthday)];
[barItemsDate addObject:doneBtnDate];
[pickerToolBar_fordate setItems:barItemsDate animated:YES];
optionPickerDate = [[UIDatePicker alloc] initWithFrame:CGRectMake(-8, 44, 320, 200)];
optionPickerDate.datePickerMode = UIDatePickerModeDate;
[optionPickerDate setMaximumDate: [NSDate date]];
optionPickerDate.datePickerMode = UIDatePickerModeDate;
optionPickerDate.hidden = NO;
optionPickerDate.date = [NSDate date];
optionPickerDate.backgroundColor = [UIColor whiteColor];
if(IS_IOS_8){
alertController = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:alertAction];
[alertController addAction:alertAction];
[alertController addAction:alertAction];
[alertController addAction:alertAction];
[alertController.view addSubview:pickerToolBar_fordate];
[alertController.view addSubview:optionPickerDate];
} else {
ac_sheet_fordate = [[UIActionSheet alloc] initWithTitle:@"test"
delegate:self
cancelButtonTitle:@"cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"dev",@"dev", nil];
[ac_sheet_fordate setActionSheetStyle:UIActionSheetStyleBlackOpaque];
[ac_sheet_fordate setBackgroundColor:[UIColor blackColor]];
[ac_sheet_fordate addSubview:pickerToolBar_fordate];
[ac_sheet_fordate addSubview:optionPickerDate];
}
}
// when date picker open
- (IBAction)showBirthdayPicker:(id)sender{
// self.view.frame = CGRectMake(0, -220, self.view.frame.size.width, self.view.frame.size.height);
UIButton *btnsender = sender;
//[ac_sheet_fordate showInView:self.view];
self.scrForEditProfile.contentSize = CGSizeMake(320, 1000);
if(IS_IOS_8){
popover = alertController.popoverPresentationController;
if (popover)
{
popover.sourceView = sender;
popover.sourceRect = CGRectMake(0, btnsender.bounds.origin.y, btnsender.bounds.size.width, btnsender.bounds.size.height);
popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
}
[self presentViewController:alertController animated:YES completion:nil];
} else {
if(IS_IOS_7){
[ac_sheet_fordate showInView:[UIApplication sharedApplication].keyWindow];
ac_sheet_fordate.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height-ac_sheet_fordate.frame.size.height, [UIScreen mainScreen].bounds.size.width, ac_sheet_fordate.frame.size.height);
}
else{
[ac_sheet_fordate showInView:self.view];
}
}
if(IS_IOS_7==FALSE && IS_HEIGHT_GTE_568==FALSE){
[self.scrForEditProfile scrollRectToVisible:CGRectMake(self.txtDOB.frame.origin.x, self.txtDOB.frame.origin.y + 200, self.txtDOB.frame.size.width, self.txtDOB.frame.size.height) animated:NO];
}
else{
[self.scrForEditProfile scrollRectToVisible:CGRectMake(self.txtDOB.frame.origin.x, self.txtDOB.frame.origin.y +300, self.txtDOB.frame.size.width, self.txtDOB.frame.size.height) animated:NO];
}
}
// when date picker open user tap on done button
- (IBAction)pickerViewDoneBirthday{
if(IS_IOS_8){
[self.presentedViewController dismissViewControllerAnimated:NO completion:nil];
} else {
[ac_sheet_fordate dismissWithClickedButtonIndex:0 animated:YES];
}
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"dd/MM/yyyy"];
birthday_date = optionPickerDate.date;
[self.btnShowDatePicker setTitle:[formatter stringFromDate:optionPickerDate.date] forState:UIControlStateNormal];
[self.btnShowDatePicker setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.btnShowDatePicker setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
self.scrForEditProfile.contentSize=CGSizeMake(320 , 700);
[self.scrForEditProfile scrollsToTop];
}
you can check my blog also, http://ioscodesample.blogspot.in/2014/10/ios-8-changes-for-actionsheet.html
Thanks.
![Gabriel.Massana](https://i.stack.imgur.com/t2iTl.jpg?s=256&g=1)
Gabriel.Massana
http://www.linkedin.com/in/gabrielmassana/en https://github.com/GabrielMassana https://cocoapods.org/owners/10374 https://somethingaboutios.wordpress.com/
Updated on October 06, 2020Comments
-
Gabriel.Massana over 3 years
Showing a
UIPickerView
withUIActionSheet
in iOS8 not workingThe code works in iOS7, however it is not working in iOS8. I'm sure it is because UIActionSheet is deprecated in iOS8 and Apple recommends to use
UIAlertController
.However, how to do it in iOS8? I should use
UIAlertController
?iOS7:
iOS8:
EDIT: