Custom view of timeout blocking view within network connection.

class Timeout {
    
    fileprivate var indicatorInterval: TimeInterval {
        return 3
    }
    
    fileprivate var timeoutInterval: TimeInterval {
        return 12
    }
    
    private var blockViewTag: Int {
        return "blockViewTag".hashValue
    }
    
    private func blockView(_ tag: Int) -> UIView? {
        return UIApplication.shared.keyWindow?.subviews.first(where: {$0.tag == tag})
    }
    
    private func indicator(_ value: Bool) {
        if value {UIApplication.shared.beginIgnoringInteractionEvents()}
        else {
            guard UIApplication.shared.isIgnoringInteractionEvents else {return}
            UIApplication.shared.endIgnoringInteractionEvents()
        }
    }
    
    fileprivate func start() {
        DispatchQueue.main.async {
            guard let window = UIApplication.shared.keyWindow, self.blockView(self.blockViewTag) == nil else {return}
            let blockView = UIView(frame: window.bounds)
            blockView.isUserInteractionEnabled = false
            blockView.backgroundColor = .clear
            blockView.tag = self.blockViewTag
            window.addSubview(blockView)
            DispatchQueue.main.asyncAfter(deadline: .now() + self.indicatorInterval, execute: self.indicatorWork)
        }
    }
    
    private lazy var indicatorWork: DispatchWorkItem = DispatchWorkItem {
        DispatchQueue.main.async {
            self.indicator(true)
            UIView.animate(withDuration: 0.3) {
                self.blockView(self.blockViewTag)?.backgroundColor = ColorStore.black.alpha(0.3)
            }
            let lessInterval = self.timeoutInterval - self.indicatorInterval
            DispatchQueue.main.asyncAfter(deadline: .now() + lessInterval, execute: self.endWork)
        }
    }
    
    private lazy var endWork: DispatchWorkItem = DispatchWorkItem {
        DispatchQueue.main.async {
            LockAPI.unlock()
            self.indicator(false)
            self.blockView(self.blockViewTag)?.removeFromSuperview()
        }
    }
    
    fileprivate func stop() {
        DispatchQueue.main.async {
            LockAPI.unlock()
            self.indicatorWork.cancel()
            self.endWork.cancel()
            self.indicator(false)
            self.blockView(self.blockViewTag)?.removeFromSuperview()
        }
    }
    
}