尝试在已经呈现的 View Controller 上呈现 UIAlertController (null) [Swift]
Attempt to present UIAlertController on View Controller which is already presenting (null) [Swift]
我有一个警告视图,我正试图在照片视图上显示。
照片显示在列表中,可以推送到 full-screen 视图。
正在以编程方式显示照片视图。我认为这就是导致问题的原因,因为警报视图试图在已经呈现的(照片)视图之上呈现另一个视图。
警报视图正在尝试显示,但出现此错误:
Warning: Attempt to present <UIAlertController: 0x147d2c6b0> on <LiveDeadApp.ListViewController: 0x147d614c0> which is already presenting (null)
可能有问题的是这一行:
self.present(textPrompt, animated: true, completion: nil)
这是主列表视图
这是截图时的主列表视图
这是主照片视图
这是主照片视图中的弹出窗口(通过 "i" 按钮访问)
在主照片视图截取屏幕截图时,不会出现警报视图。但是,当设备的方向发生变化时,照片视图会返回到列表并显示警报。
这就是我想要做的:
Swift 3 在 iOS 10
谢谢!
这是列表视图和照片视图的代码:
import UIKit
import Kingfisher
import SKPhotoBrowser
class ListViewCell: UITableViewCell {
@IBOutlet weak var Cellimage: UIImageView!
@IBOutlet weak var cellVenue: UILabel!
@IBOutlet weak var cellLocation: UILabel!
@IBOutlet weak var cellDate: UILabel!
@IBOutlet weak var aiView: UIActivityIndicatorView!
}
class ListViewController: UITableViewController {
var subcategory:Subcategory!
var objects:[[String:String]] = [[String:String]]()
var images = [SKPhotoProtocol]()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .none
self.view.backgroundColor = UIColor.black
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navigationController!.navigationBar.barTintColor = UIColor.black
let requireTextInput = "require text input"
// add observer for screen shot
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using:
{ notification in
self.definesPresentationContext = true
var inputTextField = UITextField()
let textPrompt = UIAlertController(title: "Test!", message: "Testing!", preferredStyle: .alert)
textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: {
(action) -> Void in
// if the input match the required text
let str = inputTextField.text
if str == requireTextInput {
print("right")
} else {
print("wrong")
}
}))
textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in
textField.placeholder = ""
inputTextField = textField
})
self.present(textPrompt, animated: true, completion: nil)
})
if subcategory != nil {
self.title = subcategory.title
self.objects = subcategory.photos
createLocalPhotos()
self.tableView.reloadData()
}
}
func createLocalPhotos() {
for item in objects {
let photo = SKPhoto.photoWithImageURL(item["url"]!)
photo.shouldCachePhotoURLImage = true
images.append(photo)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: ListViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ListViewCell
let item = objects[indexPath.row]
let title = item["title"]
let location = item["location"]
let date = item["date"]
let urlSrt = item["url"]
cell.cellVenue.text = title
cell.cellLocation.text = location
cell.cellDate.text = date
if let url = URL(string: urlSrt!) {
cell.aiView.startAnimating()
cell.Cellimage.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, url) in
cell.aiView.stopAnimating()
})
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! ListViewCell
if(cell.Cellimage.image != nil ) {
SKPhotoBrowserOptions.displayToolbar = false
SKPhotoBrowserOptions.displayCounterLabel = false
SKPhotoBrowserOptions.displayBackAndForwardButton = false
SKPhotoBrowserOptions.displayAction = false
SKPhotoBrowserOptions.displayDeleteButton = true
SKPhotoBrowserOptions.displayHorizontalScrollIndicator = false
SKPhotoBrowserOptions.displayVerticalScrollIndicator = false
SKPhotoBrowserOptions.displayStatusbar = false
SKPhotoBrowserOptions.disableVerticalSwipe = true
SKPhotoBrowserOptions.bounceAnimation = false
let browser = ExtendedSKPhotoBrowser(originImage: cell.Cellimage.image!, photos: images, animatedFromView: cell)
let btnSize = 80//24 * UIScreen.main.scale
browser.updateCloseButton(UIImage(named: "ic_close_white")!, size: CGSize(width: btnSize, height: btnSize))
browser.updateDeleteButton(UIImage(named: "ic_info_white")!, size: CGSize(width: btnSize, height: btnSize))
browser.initializePageIndex(indexPath.row)
browser.delegate = self
present(browser, animated: true, completion: {})
browser.toggleControls()
}
}
override var prefersStatusBarHidden: Bool {
get {
return true
}
}
var popOverVC:PopUpViewController!
}
extension ListViewController: SKPhotoBrowserDelegate {
func didShowPhotoAtIndex(_ index: Int) {
}
func willDismissAtPageIndex(_ index: Int) {
}
private func willShowActionSheet(photoIndex: Int) {
// do some handle if you need
}
func didDismissAtPageIndex(_ index: Int) {
}
func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int) {
// handle dismissing custom actions
}
func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
popOverVC = self.storyboard?.instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpViewController
popOverVC.photoData = objects[index]
}
func viewForPhoto(_ browser: SKPhotoBrowser, index: Int) -> UIView? {
return tableView.cellForRow(at: IndexPath(row: index, section: 0))
}
}
open class ExtendedSKPhotoBrowser: SKPhotoBrowser {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent // white statusbar, .default is black
}
open override var prefersStatusBarHidden: Bool {
return true
}
}
在 ViewDidLoad 中,
制作 weak
变量,例如 weak var weakSelf = self
在通知中心,
出席 textPropmt
喜欢
weak var weakSelf = self
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using:
{ notification in
DispatchQueue.main.async(execute: {
//create textPrompt here in Main Thread
weakSelf.present(textPrompt, animated: true, completion: nil)
})
})
问题很简单,你想在当前显示的 UIAlertController
上显示另一个 UIAlertController
。
So, how to solve such a case?
您需要获取您在当前视图控制器中使用的所有 UIAlertController
的列表。
您必须检查当前视图控制器(或其他视图控制器,如果您正在执行异步请求)中显示警报的逻辑。
当你想在另一个之上显示一个警报时,你的代码必须像这样。
假设 loadingAlert 当前显示在屏幕上:
self.loadingAlert.dismiss(animated: true, completion: {
let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
anotherAlert.addAction(okAction)
self.present(anotherAlert, animated: true, completion: nil)
})
您必须关闭第一个才能出现下一个。我做出这个回答是为了消除没有按钮的警报以提高效率。
So, what about the alert with action buttons?
It will dismiss automatically when you click one of the action
buttons on UIAlertController
that you created.
但是,如果同时显示两个包含UIButton
的UIAlertController
,问题仍然会发生。您需要重新检查每个逻辑,或者您可以在每个操作的处理程序中处理它:
self.connectionErrorAlert.dismiss(animated: true, completion: {
let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: {action in
let nextAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
self.present(nextAlert, animated: true, completion: nil)
})
anotherAlert.addAction(okAction)
self.present(anotherAlert, animated: true, completion: nil)
})
回复迈克:
DispatchQueue.main.async(execute: {
if self.presentedViewController == nil {
print("Alert comes up with the intended ViewController")
var inputTextField = UITextField()
let textPrompt = UIAlertController(title: "Test", message: "Testing", preferredStyle: .alert)
textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: {
(action) -> Void in
// if the input matches the required text
let str = inputTextField.text
if str == requireTextInput {
print("right")
} else {
print("wrong")
}
}))
textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in
textField.placeholder = ""
inputTextField = textField
})
weakSelf?.present(textPrompt, animated: true, completion: nil)
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let _ : UIAlertController = thePresentedVC as? UIAlertController {
print("Alert not necessary, already on the screen !")
} else {
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
})
感谢@Luke 回答:
我遇到过这个问题,并一直追踪到这个问题。这是一个简单的应用程序,上面有两个按钮。点击第一个按钮会导致“2019-03-05 16:58:04.094541-0500 ReadJason[41100:1610082] Warning: Attempt to present on which is already presenting”错误。
问题是由将按钮 2 复制到按钮 1 引起的。每个按钮都绑定到一个操作(btn1 和 btn2)。当我复制 btn2 来制作 btn1 时,btn2 的关系包含在 btn1 的代码中。然后我将领带添加到 btn1,这导致两个发送事件被绑定到 btn1 - 这就是导致错误的原因。
检查按钮 1 的事件揭示了两个操作:screen shot showing the two actions。删除不需要的操作会清除错误。
screen shot of main.storyboard
<pre><code>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *btn1;
@property (weak, nonatomic) IBOutlet UIButton *btn2;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)btn1:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Btn1"
message:@"This is Btn1." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
- (IBAction)btn2:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Btn2"
message:@"This is Btn2." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
</code></pre>
嘿,我尝试了一个似乎有效的更简单的解决方案,并且能够在第一个警报之前显示第二个警报,它将保留(用户回答问题之前无需关闭):
if self.presentedViewController==nil{
self.present(MyAlert, animated: true, completion: nil)
}else{
self.presentedViewController!.present(MyAlert, animated: true, completion: nil)
}
我相信,你需要确定是否已经有另一个 AlerViewController 试图在 ViewController 上代表自己。
至少那是我的问题。
嘿,就我而言,我遇到了同样的错误。
简单的解决方案
您同时显示两个警报控制器。
您需要关闭第一个警报控制器,然后 XCode 允许您显示第二个警报控制器。
您可以关闭此代码 -> self.dismiss(animated: true, completion: nil)
像这样->
let alert = UIAlertController(title: "Delete",
message: "Are you sure?",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { [self] _ in
// TODO: Your Delete Code
self.dismiss(animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
let alert = UIAlertController(title: "Alert", message: "No saved address found. Please save address first.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
self.navigationController?.popViewController(animated: false)
}))
if self.presentedViewController==nil{
self.present(alert, animated: true, completion: nil)
}else{
self.presentedViewController!.present(alert, animated: true, completion: nil)
}
我有一个警告视图,我正试图在照片视图上显示。
照片显示在列表中,可以推送到 full-screen 视图。
正在以编程方式显示照片视图。我认为这就是导致问题的原因,因为警报视图试图在已经呈现的(照片)视图之上呈现另一个视图。
警报视图正在尝试显示,但出现此错误:
Warning: Attempt to present <UIAlertController: 0x147d2c6b0> on <LiveDeadApp.ListViewController: 0x147d614c0> which is already presenting (null)
可能有问题的是这一行:
self.present(textPrompt, animated: true, completion: nil)
这是主列表视图
这是截图时的主列表视图
这是主照片视图
这是主照片视图中的弹出窗口(通过 "i" 按钮访问)
在主照片视图截取屏幕截图时,不会出现警报视图。但是,当设备的方向发生变化时,照片视图会返回到列表并显示警报。
这就是我想要做的:
Swift 3 在 iOS 10
谢谢!
这是列表视图和照片视图的代码:
import UIKit
import Kingfisher
import SKPhotoBrowser
class ListViewCell: UITableViewCell {
@IBOutlet weak var Cellimage: UIImageView!
@IBOutlet weak var cellVenue: UILabel!
@IBOutlet weak var cellLocation: UILabel!
@IBOutlet weak var cellDate: UILabel!
@IBOutlet weak var aiView: UIActivityIndicatorView!
}
class ListViewController: UITableViewController {
var subcategory:Subcategory!
var objects:[[String:String]] = [[String:String]]()
var images = [SKPhotoProtocol]()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .none
self.view.backgroundColor = UIColor.black
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navigationController!.navigationBar.barTintColor = UIColor.black
let requireTextInput = "require text input"
// add observer for screen shot
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using:
{ notification in
self.definesPresentationContext = true
var inputTextField = UITextField()
let textPrompt = UIAlertController(title: "Test!", message: "Testing!", preferredStyle: .alert)
textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: {
(action) -> Void in
// if the input match the required text
let str = inputTextField.text
if str == requireTextInput {
print("right")
} else {
print("wrong")
}
}))
textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in
textField.placeholder = ""
inputTextField = textField
})
self.present(textPrompt, animated: true, completion: nil)
})
if subcategory != nil {
self.title = subcategory.title
self.objects = subcategory.photos
createLocalPhotos()
self.tableView.reloadData()
}
}
func createLocalPhotos() {
for item in objects {
let photo = SKPhoto.photoWithImageURL(item["url"]!)
photo.shouldCachePhotoURLImage = true
images.append(photo)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: ListViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ListViewCell
let item = objects[indexPath.row]
let title = item["title"]
let location = item["location"]
let date = item["date"]
let urlSrt = item["url"]
cell.cellVenue.text = title
cell.cellLocation.text = location
cell.cellDate.text = date
if let url = URL(string: urlSrt!) {
cell.aiView.startAnimating()
cell.Cellimage.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, url) in
cell.aiView.stopAnimating()
})
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! ListViewCell
if(cell.Cellimage.image != nil ) {
SKPhotoBrowserOptions.displayToolbar = false
SKPhotoBrowserOptions.displayCounterLabel = false
SKPhotoBrowserOptions.displayBackAndForwardButton = false
SKPhotoBrowserOptions.displayAction = false
SKPhotoBrowserOptions.displayDeleteButton = true
SKPhotoBrowserOptions.displayHorizontalScrollIndicator = false
SKPhotoBrowserOptions.displayVerticalScrollIndicator = false
SKPhotoBrowserOptions.displayStatusbar = false
SKPhotoBrowserOptions.disableVerticalSwipe = true
SKPhotoBrowserOptions.bounceAnimation = false
let browser = ExtendedSKPhotoBrowser(originImage: cell.Cellimage.image!, photos: images, animatedFromView: cell)
let btnSize = 80//24 * UIScreen.main.scale
browser.updateCloseButton(UIImage(named: "ic_close_white")!, size: CGSize(width: btnSize, height: btnSize))
browser.updateDeleteButton(UIImage(named: "ic_info_white")!, size: CGSize(width: btnSize, height: btnSize))
browser.initializePageIndex(indexPath.row)
browser.delegate = self
present(browser, animated: true, completion: {})
browser.toggleControls()
}
}
override var prefersStatusBarHidden: Bool {
get {
return true
}
}
var popOverVC:PopUpViewController!
}
extension ListViewController: SKPhotoBrowserDelegate {
func didShowPhotoAtIndex(_ index: Int) {
}
func willDismissAtPageIndex(_ index: Int) {
}
private func willShowActionSheet(photoIndex: Int) {
// do some handle if you need
}
func didDismissAtPageIndex(_ index: Int) {
}
func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int) {
// handle dismissing custom actions
}
func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
popOverVC = self.storyboard?.instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpViewController
popOverVC.photoData = objects[index]
}
func viewForPhoto(_ browser: SKPhotoBrowser, index: Int) -> UIView? {
return tableView.cellForRow(at: IndexPath(row: index, section: 0))
}
}
open class ExtendedSKPhotoBrowser: SKPhotoBrowser {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent // white statusbar, .default is black
}
open override var prefersStatusBarHidden: Bool {
return true
}
}
在 ViewDidLoad 中,
制作 weak
变量,例如 weak var weakSelf = self
在通知中心,
出席 textPropmt
喜欢
weak var weakSelf = self
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using:
{ notification in
DispatchQueue.main.async(execute: {
//create textPrompt here in Main Thread
weakSelf.present(textPrompt, animated: true, completion: nil)
})
})
问题很简单,你想在当前显示的 UIAlertController
上显示另一个 UIAlertController
。
So, how to solve such a case?
您需要获取您在当前视图控制器中使用的所有
UIAlertController
的列表。您必须检查当前视图控制器(或其他视图控制器,如果您正在执行异步请求)中显示警报的逻辑。
当你想在另一个之上显示一个警报时,你的代码必须像这样。
假设 loadingAlert 当前显示在屏幕上:
self.loadingAlert.dismiss(animated: true, completion: {
let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
anotherAlert.addAction(okAction)
self.present(anotherAlert, animated: true, completion: nil)
})
您必须关闭第一个才能出现下一个。我做出这个回答是为了消除没有按钮的警报以提高效率。
So, what about the alert with action buttons?
It will dismiss automatically when you click one of the action buttons on
UIAlertController
that you created.
但是,如果同时显示两个包含UIButton
的UIAlertController
,问题仍然会发生。您需要重新检查每个逻辑,或者您可以在每个操作的处理程序中处理它:
self.connectionErrorAlert.dismiss(animated: true, completion: {
let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: {action in
let nextAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert)
self.present(nextAlert, animated: true, completion: nil)
})
anotherAlert.addAction(okAction)
self.present(anotherAlert, animated: true, completion: nil)
})
回复迈克:
DispatchQueue.main.async(execute: {
if self.presentedViewController == nil {
print("Alert comes up with the intended ViewController")
var inputTextField = UITextField()
let textPrompt = UIAlertController(title: "Test", message: "Testing", preferredStyle: .alert)
textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: {
(action) -> Void in
// if the input matches the required text
let str = inputTextField.text
if str == requireTextInput {
print("right")
} else {
print("wrong")
}
}))
textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in
textField.placeholder = ""
inputTextField = textField
})
weakSelf?.present(textPrompt, animated: true, completion: nil)
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let _ : UIAlertController = thePresentedVC as? UIAlertController {
print("Alert not necessary, already on the screen !")
} else {
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
})
感谢@Luke 回答:
我遇到过这个问题,并一直追踪到这个问题。这是一个简单的应用程序,上面有两个按钮。点击第一个按钮会导致“2019-03-05 16:58:04.094541-0500 ReadJason[41100:1610082] Warning: Attempt to present on which is already presenting”错误。
问题是由将按钮 2 复制到按钮 1 引起的。每个按钮都绑定到一个操作(btn1 和 btn2)。当我复制 btn2 来制作 btn1 时,btn2 的关系包含在 btn1 的代码中。然后我将领带添加到 btn1,这导致两个发送事件被绑定到 btn1 - 这就是导致错误的原因。
检查按钮 1 的事件揭示了两个操作:screen shot showing the two actions。删除不需要的操作会清除错误。
screen shot of main.storyboard
<pre><code>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *btn1;
@property (weak, nonatomic) IBOutlet UIButton *btn2;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)btn1:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Btn1"
message:@"This is Btn1." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
- (IBAction)btn2:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Btn2"
message:@"This is Btn2." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
</code></pre>
嘿,我尝试了一个似乎有效的更简单的解决方案,并且能够在第一个警报之前显示第二个警报,它将保留(用户回答问题之前无需关闭):
if self.presentedViewController==nil{
self.present(MyAlert, animated: true, completion: nil)
}else{
self.presentedViewController!.present(MyAlert, animated: true, completion: nil)
}
我相信,你需要确定是否已经有另一个 AlerViewController 试图在 ViewController 上代表自己。
至少那是我的问题。
嘿,就我而言,我遇到了同样的错误。
简单的解决方案
您同时显示两个警报控制器。
您需要关闭第一个警报控制器,然后 XCode 允许您显示第二个警报控制器。
您可以关闭此代码 -> self.dismiss(animated: true, completion: nil)
像这样->
let alert = UIAlertController(title: "Delete",
message: "Are you sure?",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { [self] _ in
// TODO: Your Delete Code
self.dismiss(animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
let alert = UIAlertController(title: "Alert", message: "No saved address found. Please save address first.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
self.navigationController?.popViewController(animated: false)
}))
if self.presentedViewController==nil{
self.present(alert, animated: true, completion: nil)
}else{
self.presentedViewController!.present(alert, animated: true, completion: nil)
}