防止 UIAlertController 关闭
Prevent UIAlertController to dismiss
我想阻止 UIAlertController
解雇。
我有一个 UIAlertAction
,它只是将一个字符串附加到 UIAlertTextField 中,但是,一旦点击它就会关闭视图控制器 [不需要]。我试过添加一个 NSNotification,结果不理想。
UIAlertAction *pasteMessage = [UIAlertAction actionWithTitle:@"Paste Message" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
UITextField *textField = alertC.textFields.firstObject;
textField.text = [textField.text stringByAppendingString:[NSString stringWithFormat:@"%@", copiedString]];
}];
我还尝试通过以下方式设置否以粘贴消息:
[alertC canPerformAction:@selector(dismissViewControllerAnimated:completion:) withSender:pasteMessage];
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
UIAlertController *alertController = (UIAlertController *)self.presentedViewController;
UIAlertAction *paste = alertController.actions.firstObject;
if (paste) {
flag = NO;
} else {
flag = YES;
}
}
编辑,我不是要阻止 UIAlertAction
的点击,而是要防止 UIAlertController
在点击上述操作时消失。该操作可以是 enabled/disabled 任何内容,但我的目标是通过按下一个操作将复制的消息简单地粘贴到 UITextField
中(因此我不希望它被取消)
我还意识到将 BOOL 设置为 dismissViewControllerAnimated:
只是将其设置为 而不是 动画视图控制器关闭,我不希望它暗示它是为了停止实际解雇过程。简单地提供我已经尝试过的与我的目标相关的事情。我还尝试在选择 pasteMessage 时显示 new UIAlertController
自动填充 new UIAlertControllers
文本字段消息,它有效,但我觉得它对于可以完成的事情来说太老套了。
编辑:更新为 Swift 5
编辑:已更新以包含@skywalker 的反馈
所以我真的让它起作用了。简而言之,它涉及向 UIAlertController
添加一个长按手势识别器,在关闭之前触发。
首先,在您的视图控制器中为您的 UIAlertController
和您要防止触发的 UIAlertAction
创建延迟加载的计算变量,以便可以通过手势识别器的选择器访问 self
您将附加到警报的方法(选择器中的self
暗示所有这些都在视图控制器中)。
lazy var alert: UIAlertController = {
let alert = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)
alert.addTextField(configurationHandler: nil)
let appendAction = self.appendAction
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(appendAction)
alert.addAction(cancelAction)
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(append(sender:)))
gestureRecognizer.minimumPressDuration = 0.0
alert.view.addGestureRecognizer(gestureRecognizer)
return alert
}()
lazy var appendAction: UIAlertAction = {
return UIAlertAction(title: "Paste Message", style: .default, handler: nil)
}()
确保你上面的手势识别器是一个 UILongPressGestureRecognizer
设置的最小按下持续时间为 0。这样你就可以在动作被触发之前访问手势状态(当用户按下时)完全。在那里你可以禁用 UIAlertAction
,实现你的自定义代码,并在手势完成后重新启用动作(用户已经触摸)。见下文:
@objc func append(sender: UILongPressGestureRecognizer) {
switch sender.state {
case .began:
appendAction.isEnabled = false
case .ended:
// Do whatever you want with the alert text fields
print(alert.textFields?[0].text)
appendAction.isEnabled = true
default:
return
}
}
此外,确保拥有此警报呈现的视图控制器符合 UIGestureRecognizerDelegate
以识别同步手势。
extension YourViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
然后,只要出示UIAlertController
就可以了。
func showAlert() {
self.present(alert, animated: true, completion: nil)
}
这显然是一个 hack,但我知道没有其他方法可以在没有 hack 的情况下实现这一点,因为它不是要实现的。例如,手势识别器与 UIAlertController
相关联,因此用户可以在点击警报上的任意位置(取消按钮除外)时触发该方法。
原始答案:
这是我能想到的最接近黑客攻击的回合了。如果有某种方法可以将关闭过渡时间自定义为空,那么您可以将 animated:
设置为 false,它看起来就像是相同的警报,但我认为这是不可能的
class ViewController: UIViewController {
@IBAction func alert(sender: AnyObject) {
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .Alert)
alert.addTextFieldWithConfigurationHandler(nil)
let appendAction = UIAlertAction(title: "Append text", style: .Default) { _ in
var textField = alert.textFields![0] as UITextField
// Append text here
self.presentViewController(alert, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alert.addAction(appendAction)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
我只熟悉swift
回答了几乎相同的问题here
警报中的文本字段支持粘贴选项,因此没有真正的理由在警报中使用单独的按钮来指示 "paste" 选项。
否则你应该模仿 UIAlertController 并用 desiread 行为重新实现它。
我想阻止 UIAlertController
解雇。
我有一个 UIAlertAction
,它只是将一个字符串附加到 UIAlertTextField 中,但是,一旦点击它就会关闭视图控制器 [不需要]。我试过添加一个 NSNotification,结果不理想。
UIAlertAction *pasteMessage = [UIAlertAction actionWithTitle:@"Paste Message" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
UITextField *textField = alertC.textFields.firstObject;
textField.text = [textField.text stringByAppendingString:[NSString stringWithFormat:@"%@", copiedString]];
}];
我还尝试通过以下方式设置否以粘贴消息:
[alertC canPerformAction:@selector(dismissViewControllerAnimated:completion:) withSender:pasteMessage];
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
UIAlertController *alertController = (UIAlertController *)self.presentedViewController;
UIAlertAction *paste = alertController.actions.firstObject;
if (paste) {
flag = NO;
} else {
flag = YES;
}
}
编辑,我不是要阻止 UIAlertAction
的点击,而是要防止 UIAlertController
在点击上述操作时消失。该操作可以是 enabled/disabled 任何内容,但我的目标是通过按下一个操作将复制的消息简单地粘贴到 UITextField
中(因此我不希望它被取消)
我还意识到将 BOOL 设置为 dismissViewControllerAnimated:
只是将其设置为 而不是 动画视图控制器关闭,我不希望它暗示它是为了停止实际解雇过程。简单地提供我已经尝试过的与我的目标相关的事情。我还尝试在选择 pasteMessage 时显示 new UIAlertController
自动填充 new UIAlertControllers
文本字段消息,它有效,但我觉得它对于可以完成的事情来说太老套了。
编辑:更新为 Swift 5
编辑:已更新以包含@skywalker 的反馈
所以我真的让它起作用了。简而言之,它涉及向 UIAlertController
添加一个长按手势识别器,在关闭之前触发。
首先,在您的视图控制器中为您的 UIAlertController
和您要防止触发的 UIAlertAction
创建延迟加载的计算变量,以便可以通过手势识别器的选择器访问 self
您将附加到警报的方法(选择器中的self
暗示所有这些都在视图控制器中)。
lazy var alert: UIAlertController = {
let alert = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)
alert.addTextField(configurationHandler: nil)
let appendAction = self.appendAction
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(appendAction)
alert.addAction(cancelAction)
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(append(sender:)))
gestureRecognizer.minimumPressDuration = 0.0
alert.view.addGestureRecognizer(gestureRecognizer)
return alert
}()
lazy var appendAction: UIAlertAction = {
return UIAlertAction(title: "Paste Message", style: .default, handler: nil)
}()
确保你上面的手势识别器是一个 UILongPressGestureRecognizer
设置的最小按下持续时间为 0。这样你就可以在动作被触发之前访问手势状态(当用户按下时)完全。在那里你可以禁用 UIAlertAction
,实现你的自定义代码,并在手势完成后重新启用动作(用户已经触摸)。见下文:
@objc func append(sender: UILongPressGestureRecognizer) {
switch sender.state {
case .began:
appendAction.isEnabled = false
case .ended:
// Do whatever you want with the alert text fields
print(alert.textFields?[0].text)
appendAction.isEnabled = true
default:
return
}
}
此外,确保拥有此警报呈现的视图控制器符合 UIGestureRecognizerDelegate
以识别同步手势。
extension YourViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
然后,只要出示UIAlertController
就可以了。
func showAlert() {
self.present(alert, animated: true, completion: nil)
}
这显然是一个 hack,但我知道没有其他方法可以在没有 hack 的情况下实现这一点,因为它不是要实现的。例如,手势识别器与 UIAlertController
相关联,因此用户可以在点击警报上的任意位置(取消按钮除外)时触发该方法。
原始答案:
这是我能想到的最接近黑客攻击的回合了。如果有某种方法可以将关闭过渡时间自定义为空,那么您可以将 animated:
设置为 false,它看起来就像是相同的警报,但我认为这是不可能的
class ViewController: UIViewController {
@IBAction func alert(sender: AnyObject) {
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .Alert)
alert.addTextFieldWithConfigurationHandler(nil)
let appendAction = UIAlertAction(title: "Append text", style: .Default) { _ in
var textField = alert.textFields![0] as UITextField
// Append text here
self.presentViewController(alert, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alert.addAction(appendAction)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
我只熟悉swift
回答了几乎相同的问题here
警报中的文本字段支持粘贴选项,因此没有真正的理由在警报中使用单独的按钮来指示 "paste" 选项。
否则你应该模仿 UIAlertController 并用 desiread 行为重新实现它。