Presenting a UIAlertController properly on an iPad using iOS 8
You can present a UIAlertController
from a popover by using UIPopoverPresentationController
.
In Obj-C:
UIViewController *self; // code assumes you're in a view controller
UIButton *button; // the button you want to show the popup sheet from
UIAlertController *alertController;
UIAlertAction *destroyAction;
UIAlertAction *otherAction;
alertController = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
destroyAction = [UIAlertAction actionWithTitle:@"Remove All Data"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
// do destructive stuff here
}];
otherAction = [UIAlertAction actionWithTitle:@"Blah"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
// do something here
}];
// note: you can control the order buttons are shown, unlike UIActionSheet
[alertController addAction:destroyAction];
[alertController addAction:otherAction];
[alertController setModalPresentationStyle:UIModalPresentationPopover];
UIPopoverPresentationController *popPresenter = [alertController
popoverPresentationController];
popPresenter.sourceView = button;
popPresenter.sourceRect = button.bounds;
[self presentViewController:alertController animated:YES completion:nil];
Editing for Swift 4.2, though there are many blogs available for the same but it may save your time to go and search for them.
if let popoverController = yourAlert.popoverPresentationController {
popoverController.sourceView = self.view //to set the source of your alert
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) // you can set this as per your requirement.
popoverController.permittedArrowDirections = [] //to hide the arrow of any particular direction
}
Swift UIAlertController - ActionSheet iPad iOS8 Crashes
The error message is telling you that you need to give the alert controller's popoverPresentationController
a location so that it can position itself properly. This is easy to do -- just check to see if there's a popover controller and add the sender as the source.
If your button is a UIBarButtonItem
:
if let popoverController = alertController.popoverPresentationController {
popoverController.barButtonItem = sender
}
self.presentViewController(alertController, animated: true, completion: nil)
Otherwise:
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = sender
popoverController.sourceRect = sender.bounds
}
self.presentViewController(alertController, animated: true, completion: nil)
Present a UIAlertController from within a Popover in iOS8
Found it !
If this AlertController is presented inside a popover, it must provide the location information, either a sourceView and sourceRect, or a barButtonItem.
Like
resetWarning.popoverPresentationController?.sourceView = selectedCell?.contentView
resetWarning.popoverPresentationController?.sourceRect = selectedCell!.contentView.frame
My code had to look like that:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var previouslySelectedCell: UITableViewCell?
if checkedIndexPath != nil {
previouslySelectedCell = tableView.cellForRowAtIndexPath(checkedIndexPath)
}
var selectedCell = tableView.cellForRowAtIndexPath(indexPath)
let selectedCurrency = PortfolioCurrencyStore.sharedStore.allCurrencies[indexPath.row]
if selectedCurrency.symbol != GlobalSettings.sharedStore.portfolioCurrency {
// Warning : changing the portfolio currency will reset the portfolio
var resetWarning = UIAlertController(title: NSLocalizedString("Currency Picker VC:AS title", comment: "Changing currency will reset portfolio"), message: nil, preferredStyle: .ActionSheet)
// destructive button
let resetAction = UIAlertAction(title: NSLocalizedString("Currency Picker VC:AS destructive", comment: "Destructive button title"), style: .Destructive, handler: { (action: UIAlertAction!) in
// Remove checkmark from the previously marked cell
previouslySelectedCell?.accessoryType = .None
// Add checkmark to the selected cell
selectedCell?.accessoryType = .Checkmark
self.checkedIndexPath = indexPath
// Animate deselection of cell
self.tableView.deselectRowAtIndexPath(indexPath, animated:true)
// Stock the portfolio currency as NSUserDefaults
GlobalSettings.sharedStore.portfolioCurrency = selectedCurrency.symbol // link between portfolioCurrency as a String and currency.symbol as the property of a Currency instance.
// Delete all items from the StockStore
StockStore.sharedStore.removeAllStocks()
println("StockStore : all entries were deleted")
// Delete all items from the CurrencyRateStore
CurrencyRateStore.sharedStore.deleteAllRates()
println("CurrencyStore : all entries were deleted")
// Delete all items from the SalesJournal
SalesJournal.sharedStore.removeAllEntries()
println("SalesJournal : all Sales journal entries were deleted")
// Reload tableView
self.tableView.reloadData()
// On Regular sizes, the currency picker is presented inside a popover : reloadData of the List View
NSNotificationCenter.defaultCenter().postNotificationName("CurrencyPickerVC_PortfolioCurrencyDidChangeNotification", object:nil, userInfo:nil)
// Animate deselection of cell
tableView.deselectRowAtIndexPath(indexPath, animated:true)
// Return to root VC
self.navigationController?.popToRootViewControllerAnimated(true)
})
// cancel button
let cancelAction = UIAlertAction(title: NSLocalizedString("Currency Picker VC:AS cancel", comment: "Cancel button title"), style: .Cancel, handler: { (alertAction: UIAlertAction!) -> Void in
// Animate deselection of cell
self.tableView.deselectRowAtIndexPath(indexPath, animated:true)
})
resetWarning.addAction(resetAction)
resetWarning.addAction(cancelAction)
// If this AlertController is presented inside a popover, it must provide the location information, either a sourceView and sourceRect or a barButtonItem.
resetWarning.popoverPresentationController?.sourceView = selectedCell?.contentView
resetWarning.popoverPresentationController?.sourceRect = selectedCell!.contentView.frame
presentViewController(resetWarning, animated: true, completion: nil)
} else {
// Animate deselection of cell
tableView.deselectRowAtIndexPath(indexPath, animated:true)
}
}
Now the image looks like this:
UIAlertController shown on iPhone, not on iPad
If you look at the documentation for the sourceView
property (https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller/1622313-sourceview), you see that it is defined as "The view containing the anchor rectangle for the popover."
This means that your popover is appearing off screen, since the anchor rectangle is the view itself.
To fix this, try modify the sourceRect
property as well. Here's an example:
alertController.popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds), 1, 1);
You will see that this causes the alert to appear in the middle of the view.
Action Sheet is not working in ipad ios 13.6
I have tried your code on iPhone(Device:- iPhone 11 Pro 13.6) and iPad(iPad pro (12.9- 4th generation) both and it works. But If you said, I have changed some popover frame, Use the following code:-
let alert = UIAlertController(title: "Select Image", message: nil, preferredStyle:
UIAlertController.Style.actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: UIAlertAction.Style.default,
handler: { (res) in
self.btnClickedCamera(tag:2)
}))
alert.addAction(UIAlertAction(title: "Gallery", style: UIAlertAction.Style.default,
handler: { (res) in
self.btnClickedGallery(tag:2)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (res) in
}))
if let popoverPresentationController = alert.popoverPresentationController {
popoverPresentationController.sourceRect = sender.frame
popoverPresentationController.sourceView = self.view
}
self.present(alert, animated: true, completion: nil)
}
Related Topics
Changing Navigation Bar Color in Swift
Rsa Implementations in Objective C
Afnetworking 3.0 Migration: How to Post with Headers and Http Body
How to Create Layout Constraints Programmatically
How to Change Color of Single Word in Uitextview and Uitextfield
Autolayout with Hidden Uiviews
Xcode 9 Swift Language Version (Swift_Version)
Store [String] in Nsuserdefaults
Dynamically Changing Font Size of Uilabel
How to Edit Empty Spaces of Left, Right Uibarbuttonitem in Uinavigationbar [iOS 7]
In Swift, Array [String] Slicing Return Type Doesn't Seem to Be [String]
iOS 8 Rotation Methods Deprecation - Backwards Compatibility
Detecting Collisions in Sprite Kit
Converting iPhone Xib to iPad Xib
Uicollectionview Reloaddata Not Functioning Properly in iOS 7