swift - 自定义警报显示在空窗口而不是以前的 viewController

标签 swift

如您所见,我将演示文稿样式设置为 .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()
  }
}

结果如下:

enter image description here

我不认为这是因为它在后台线程上造成的,因为如果我将它移动到 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
    })
  }
}

这是可视化调试器显示的内容:

enter image description here

enter image description here

最佳答案

View Controller :

  • 创建警报 Controller ;
  • modalPresentationStyle设置为.overCurrentContext;和
  • 并调用 styleRegular

但是styleRegular:

  • 调用initialSetup
  • modalPresentationStyle 重置为 .currentContext

这是丢弃您之前的 .overCurrentContext 设置的最后一步。

关于swift - 自定义警报显示在空窗口而不是以前的 viewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57136277/

相关文章:

ios - UITableView - 主标题和节标题之间的间隙

swift - CFArray takeRetainedValue() 删除导致崩溃

ios - 如何更新CNContact?获取 CNErrorDomain 代码=2

ios - 隐藏 UIView 并调整其他小部件以占用空间?

Swift:带参数的 NSURL 无效

ios - 如何通过 UICollectionViewController (Swift) 中的 didSelectItemAtIndexPath() 方法访问所有单元格

ios - 动态文本字段创建和访问 Swift 4 中的那些字段

ios - 群聊复制上的消息圈

ios - 实例方法表单扩展的覆盖取决于 '@objc' 的弃用推理

ios - 带有 rxswift 的多个 map