swift - 自定义警报显示在空窗口而不是以前的 viewController
问题描述
如您所见,我将演示样式设置为.overCurrentContext
.
extension SingleQuestionViewController: AddResponseDelegate {
func save(response text: String, questionID: Int) {
questionsWrapper.add(newResponse: text, questionID: questionID) { [weak self] successful in
if successful {
self?.responseTV?.safelyReload()
} else {
DispatchQueue.main.async {
let alertViewController = AlertViewController<Any>()
alertViewController.modalPresentationStyle = .overCurrentContext
let contentModel = RegularContentsModel(title: "controllerTitle", message: "message")
let authorizeButtonModel = SimpleButtonModel(title: "yes message", action: {
//action goes here
})
let doNothingButtonModel = SimpleButtonModel(title: "noMsg", action: {
//completion?()
})
alertViewController.styleRegular(regularContentsModel: contentModel,
models: [authorizeButtonModel, doNothingButtonModel])
self?.present(alertViewController, animated: false, completion: nil)
}
}
}
questionsWrapper.goToQuestion(with: questionID)
responseTV?.safelyReload()
}
}
结果如下:
我不认为这是由于它在后台线程上造成的,因为如果我将它移动到 viewDidLoad,那么我会得到相同的结果:
override func viewDidLoad() {
super.viewDidLoad()
setUpTopBar()
setupSearchBar()
responseTV.showsVerticalScrollIndicator = false
setupArrows()
responseTV.register(SimpleCell.self, forCellReuseIdentifier: SimpleCell.reuseID)
setAccessibility()
let alertViewController = AlertViewController<Any>()
alertViewController.modalPresentationStyle = .overCurrentContext
let contentModel = RegularContentsModel(title: "controllerTitle", message: "message")
let authorizeButtonModel = SimpleButtonModel(title: "yes message", action: {
//action goes here
})
let doNothingButtonModel = SimpleButtonModel(title: "noMsg", action: {
//completion?()
})
alertViewController.styleRegular(regularContentsModel: contentModel,
models: [authorizeButtonModel, doNothingButtonModel])
self.present(alertViewController, animated: false, completion: nil)
}
这是我的自定义警报的实现。
class AlertViewController<Payload>: AkinVC {
typealias FlagsAction = ([ReportFlag], Payload) -> Void
enum AlertStyle<Payload> {
case flag(FlagsAction)
}
let innerWholeAlertContainer = UIView()
let outerWholeAlertContainer = UIView()
let buttonStack = AlertButtonsStack()
var payload: Payload?
let transitionDuration: TimeInterval = 0.11
let containerWidth: CGFloat = 300
private var contentsView: UIView! {
didSet {
innerWholeAlertContainer.addSubview(contentsView)
contentsView.constraints(firstHorizontal: .distanceToLeading(innerWholeAlertContainer.leadingAnchor, 0),
secondHorizontal: .distanceToTrailing(innerWholeAlertContainer.trailingAnchor, 0),
vertical: .distanceToTop(innerWholeAlertContainer.topAnchor, 0),
secondVertical: .distanceToBottom(buttonStack.topAnchor, 0))
}
}
func styleNoButtons(regularContentsModel: RegularContentsModel) {
initialSetup()
let alertContentView = RegularContentsView()
alertContentView.model = regularContentsModel.forContainer(width: containerWidth)
contentsView = alertContentView
setButtonConstraints()
}
func styleAsFlagView(flagsAction: @escaping FlagsAction) {
initialSetup()
let stackView = FlagsStackView()
stackView.flagItemViews = [FlagItemView](ReportFlag.allCases)
contentsView = stackView
buttonStack.buttonModels(
ButtonModel(tekt: "Report", color: .romanceRed, tektColor: .white, action: { [weak stackView] in
guard let selectedFlags = stackView?.flagItemViews?.selectedFlags,
let payload = self.payload else { return }
flagsAction(selectedFlags, payload)
self.dismissAlert()
}),
ButtonModel(tekt: "Cancel", color: .white, tektColor: .black,
borders: BorderModel(color: UIColor.black.withAlphaComponent(0.16), width: 1, edges: [.top]),
action: { [weak self] in
self?.dismissAlert()
})
)
setButtonConstraints()
}
func styleAsOkayAlert(regularContentsModel: RegularContentsModel, action: Action? = nil) {
initialSetup()
let alertContentView = RegularContentsView()
alertContentView.model = regularContentsModel.forContainer(width: containerWidth)
contentsView = alertContentView
let okayModel = standardizeButtonsWithDismissAction(models: [SimpleButtonModel(title: "Okay, I got it.", action: action)])
buttonStack.buttonModels(okayModel)
setButtonConstraints()
}
func styleCancelAlert(regularContentsModel: RegularContentsModel, models: SimpleButtonModel...) {
initialSetup()
let alertContentView = RegularContentsView()
alertContentView.model = regularContentsModel.forContainer(width: containerWidth)
contentsView = alertContentView
var models = models
models.append(SimpleButtonModel(title: "Cancel"))
let newButtonModels = standardizeButtonsWithDismissAction(models: models)
buttonStack.buttonModels(newButtonModels)
setButtonConstraints()
}
func styleRegular(regularContentsModel: RegularContentsModel, models: SimpleButtonModel...) {
self.styleRegular(regularContentsModel: regularContentsModel, models: models)
}
func styleRegular(regularContentsModel: RegularContentsModel, models: [SimpleButtonModel]) {
initialSetup()
let alertContentView = RegularContentsView()
alertContentView.model = regularContentsModel.forContainer(width: containerWidth)
contentsView = alertContentView
let newButtonModels = standardizeButtonsWithDismissAction(models: models)
buttonStack.buttonModels(newButtonModels)
setButtonConstraints()
}
private func standardizeButtonsWithDismissAction(models: [SimpleButtonModel]) -> [ButtonModel] {
var buttonModelsToAdd: [ButtonModel] = []
let count = models.count
for (inde, model) in models.enumerated() {
var borders: [BorderModel] = []
if count > 2 || count == 1 {
borders.append(BorderModel(color: .lightGray, width: 1, edges: [.top]))
} else if count == 2 {
if inde == 0 {
borders.append(BorderModel(color: .lightGray, width: 1, edges: [.top]))
} else if inde == 1 {
borders.append(BorderModel(color: .lightGray, width: 1, edges: [.left, .top]))
}
}
buttonModelsToAdd.append(ButtonModel(tekt: model.title, color: .white, tektColor: .darkGray, borders: borders, action: {
model.action?()
self.dismissAlert()
}))
}
return buttonModelsToAdd
}
func dismissAlert() {
UIView.animate(withDuration: transitionDuration, animations: {
self.view.alpha = 0
}) { (completed) in
self.safelyDissmiss(animated: false)
}
}
fileprivate func initialSetup() {
self.view.alpha = 0
modalPresentationStyle = .currentContext
view.backgroundColor = UIColor.black.withAlphaComponent(0.3)
view.addSubview(outerWholeAlertContainer)
outerWholeAlertContainer.addSubview(innerWholeAlertContainer)
outerWholeAlertContainer.pinToEdges(innerWholeAlertContainer)
innerWholeAlertContainer.backgroundColor = .white
innerWholeAlertContainer.addSubview(buttonStack)
outerWholeAlertContainer.constraints(.horizontal(.centeredHorizontallyWith(view)),
.vertical(.centeredVerticallyTo(view)),
.horizontal(.width(containerWidth)) )
}
func setButtonConstraints() {
buttonStack.constraints(.horizontal(.distanceToLeading(innerWholeAlertContainer.leadingAnchor, 0)),
.horizontal(.distanceToTrailing(innerWholeAlertContainer.trailingAnchor, 0)),
.vertical(.distanceToBottom(innerWholeAlertContainer.bottomAnchor, 0)))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
outerWholeAlertContainer.layer.applySketchShadow()
innerWholeAlertContainer.roundCorners(constant: 15)
UIView.animate(withDuration: transitionDuration, animations: {
self.view.alpha = 1
})
}
}
以下是可视化调试器显示的内容:
解决方案
视图控制器:
- 创建警报控制器;
- 设置
modalPresentationStyle
为.overCurrentContext
; 和 - 并调用
styleRegular
。
但是styleRegular
:
- 来电
initialSetup
- 重置
modalPresentationStyle
为.currentContext
最后一步就是放弃你之前的.overCurrentContext
设置。
推荐阅读
- microsoft-graph-api - 访问 API 响应中的所有数据
- python - Python 列表理解中的条件
- c# - 如何正确地将名称分配给列表中的命名元组
- java - Java 中的成绩报告
- visual-studio - 为 Visual Studio 指定不同的命令提示符
- typescript - 解决 VS 2017 中的“节点定义冲突”TS4090 错误
- flutter - 卡片小部件内的 Listview 未使用列布局显示在屏幕上
- sql - 如何在不使用临时表或视图的情况下在多个列上使用 PIVOT
- jquery - 如何禁用 titlediv_1274837 div 中的所有输入、选择、文本区域
- mariadb - 如何防止 MariaDB 自动完成中间查询?