Как использовать оповещение и счетчик в одном классе? - PullRequest
0 голосов
/ 04 апреля 2019

Я использую общий класс для счетчика и оповещения.Это работает, но у меня иногда возникают проблемы с авариями.

Мой код в SharedClass

import UIKit

class SharedClass: NSObject {

static let sharedInstance = SharedClass()

var transparentView:UIView!
var spinner = UIActivityIndicatorView()

//Show activity indicator
func activityIndicator(view:UIView) {

    DispatchQueue.main.async {
    //            if let window = UIApplication.shared.keyWindow {//Conditionally unwrap it instead of force unwrap

            //let window = UIApplication.shared.keyWindow! //Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
            self.transparentView = UIView()
            self.transparentView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
            self.transparentView.backgroundColor = UIColor.black.withAlphaComponent(0.4)
            view.addSubview(self.transparentView)

            if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
                self.spinner = UIActivityIndicatorView(style: .whiteLarge)
                self.spinner.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
            } else {
                self.spinner = UIActivityIndicatorView(style: .white)
                self.spinner.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
            }
            self.spinner.center = view.center
            self.transparentView.addSubview(self.spinner)
            self.spinner.startAnimating()

            DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {//Stop spinner after 10 Sec's
                self.stopActivityIndicator()
            }
        }
//        }
}

//Stop activity indicator
func stopActivityIndicator() {
    DispatchQueue.main.async {
        self.spinner.stopAnimating()
        self.spinner.removeFromSuperview()
        self.transparentView.removeFromSuperview()//Some times getting error here
    }
}

//Present alert on top of all windows
func alertWindow(title: String, message: String) {
    //Calling
    //SharedClass.sharedInstance.alertWindow(title:"", message:"")
    DispatchQueue.main.async(execute: {
        let window = UIWindow(frame: UIScreen.main.bounds)
        window.rootViewController = UIViewController()
        window.windowLevel = UIWindow.Level.alert + 1

        let alert2 = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let defaultAction2 = UIAlertAction(title: "OK", style: .default, handler: { action in
        })
        alert2.addAction(defaultAction2)

        window.makeKeyAndVisible()

        window.rootViewController?.present(alert2, animated: true, completion: nil)
    })
}

private override init() {

}

}

Иногда я получаю сообщение об ошибке в этой строке

let window = UIApplication.shared.keyWindow!//Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

self.transparentView.removeFromSuperview()//Some times getting error here

Как правильно использовать эти дваоповещение и спиннер в одном классе.

Какой из них хорошо использовать

Пишите код в общем классе или пишите код в отдельном классе.

Здесь я пишу окно для отображения предупрежденияи вертушка в верхней части всех окон, включая панель навигации.

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Если вы позвоните stopActivityIndicator до activityIndicator, то transparentView будет равно нулю.Так что не используйте неявно развернутый необязательный.

Измените

var transparentView:UIView!

на

var transparentView:UIView?

и используйте необязательную цепочку при использовании этой переменной

self.transparentView?.removeFromSuperview()

И использовать guard let, чтобы получить окно ключа

guard let window = UIApplication.shared.keyWindow else {
    return
}

Расширение UIViewController для оповещения

extension UIViewController {
    func showAlert(title: String, msg: String) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }
}

Вы можете вызвать этот метод из любого контроллера представления, подобного этому,Он будет отображаться поверх всех видов и навигационной панели.

self.showAlert("Alert", msg: "Alert message")
1 голос
/ 04 апреля 2019

Не принудительно распаковывать, используйте if-let или guard, вот так:

guard let window = UIApplication.shared.keyWindow else { return }

Чтобы исправить 2-ю ошибку, используйте опциональную цепочку

self.transparentView?.removeFromSuperview()

Я использую следующий подход в одном из моих проектов, который похож на ваш, поскольку я использую его во время сетевых вызовов, он также включает индикатор NetworkActivity:

func showActivityIndicator(inView view: UIView? = nil, isNetworkActivityIndicatorVisible: Bool = true) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = isNetworkActivityIndicatorVisible

    guard let target = view ?? UIApplication.shared.keyWindow else { return }

    ...
    let transparentView = UIView()
    // Avoid using self.transparentView here, just use transparentView
    target.addSubview(transparentView)
    self.transparentView = transparentView
}
...