SwiftKickMobile / SwiftMessages

A very flexible message bar for UIKit and SwiftUI.
MIT License
7.24k stars 741 forks source link

Showing a message from a modal causes losing the keyWindow #455

Closed barisatamer closed 3 years ago

barisatamer commented 3 years ago

Hiding the message shown in a modal is causing keyWindow to be nil.

(UIApplication.shared.keyWindow is deprecated but one of our dependencies is using it. PKHUD.swift#L126 And this is causing a crash on our side.)

Steps to reproduce:

  1. Replace the Demo/Viewcontroller.swift with the sample code
  2. Tap 'Show Modal' cell (it will display a message)
  3. Hide the message by swiping up.
  4. keyWindow becomes nil

Tested with

Removing this line in WindowViewController fixes it, but I have no idea why setting windowScene nil is causing it.

Sample code

Demo/ViewController.swift import UIKit import SwiftMessages class ViewController: UITableViewController { var items: [Item] = [] /* MARK: - UITableViewDataSource */ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let item = items[(indexPath as NSIndexPath).row] return item.dequeueCell(tableView) } /* MARK: - UITableViewDelegate */ override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let item = items[(indexPath as NSIndexPath).row] item.performDemo() } override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { return 50.0 } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } // MARK: - UIViewController override func viewDidLoad() { super.viewDidLoad() self.items = [ .titleBody(title: "SHOW MODAL", body: "Display a modal", function: { self.showModal() }) ] let _ = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: true) } // MARK: - Private Methods @objc private func fireTimer() { checkKeyWindow() } private func checkKeyWindow() { if UIApplication.shared.keyWindow == nil { fatalError("❌ Key Window is nil") } else { print("✅ Key window") } } private func showModal() { let navVC: UINavigationController = .init(rootViewController: ModalVC()) navigationController?.present(navVC, animated: true, completion: nil) } } typealias Function = () -> Void enum Item { case titleBody(title: String, body: String, function: Function) func dequeueCell(_ tableView: UITableView) -> UITableViewCell { switch self { case .titleBody(let title, let body, _): let cell = tableView.dequeueReusableCell(withIdentifier: "TitleBody") as! TitleBodyCell cell.titleLabel.text = title cell.bodyLabel.text = body cell.configureBodyTextStyle() return cell } } func performDemo() { switch self { case .titleBody(_, _, let function): function() } } } class TitleBodyCell: UITableViewCell { @IBOutlet var titleLabel: UILabel! @IBOutlet var bodyLabel: UILabel! func configureBodyTextStyle() { let bodyStyle = NSMutableParagraphStyle() bodyStyle.lineSpacing = 5.0 bodyLabel.configureBodyTextStyle() } } class ModalVC: UIViewController { override func loadView() { let view: UIView = .init() view.backgroundColor = .white self.view = view navigationItem.leftBarButtonItem = .init(title: "Close", style: .plain, target: self, action: #selector(close)) } @objc private func close() { self.dismiss(animated: true, completion: nil) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) showMessage() } func showMessage() { let success = MessageView.viewFromNib(layout: .cardView) success.configureTheme(.success) success.configureDropShadow() success.configureContent(title: "Success", body: "Something good happened!") success.button?.isHidden = true var successConfig = SwiftMessages.defaultConfig successConfig.presentationContext = .window(windowLevel: UIWindow.Level.normal) successConfig.becomeKeyWindow = false SwiftMessages.show(config: successConfig, view: success) } }
timonchev commented 3 years ago

Same issue

wtmoose commented 3 years ago

This should be fixed in 9.0.1