Failed to disable UserInteraction on UIView added on UIWindow

144 views Asked by At

So here is the problem. I have created a custom loader which shows a basic "loading" text in the middle with dimmed background. The HUD shows just fine but despite of setting isUserInteractionEnabled to false I still can click on the UI where I have added the HUD. Here is the code:

public class Loader {
    public static let shared = Loader()
    
    private(set) var containerView = UIView()
    private(set) var lblText = UILabel()
    
    private init() {
        self.containerView.frame = UIScreen.main.bounds
        self.containerView.backgroundColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.5)
        self.containerView.isUserInteractionEnabled = false
        
        lblText.font = UIFont.boldSystemFont(ofSize: 30)
        lblText.textAlignment = .center
        lblText.textColor = .white
        lblText.text = "Loading..."
        containerView.addSubview(lblText)
        
        lblText.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: lblText, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: containerView, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: lblText, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: containerView, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
        
        NSLayoutConstraint(item: lblText, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 275).isActive = true
        lblText.heightAnchor.constraint(equalTo: lblText.widthAnchor, multiplier: 181/375).isActive = true
    }
    
   
    public func show() {
        DispatchQueue.main.async( execute: {
            if let found = UIApplication.key?.subviews.contains(where: {$0 == self.containerView}), found {
                self.containerView.superview?.bringSubviewToFront(self.containerView)
            }
            else {
                UIApplication.key?.addSubview(self.containerView)
            }
        })
    }
    
    @objc public func hide() {
        DispatchQueue.main.async( execute: {
            self.containerView.removeFromSuperview()
        })
    }
}

extension UIApplication {
    static var key: UIWindow? {
        if #available(iOS 13, *) {
            return UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
        } else {
            // do lower version specific window setup
            return UIApplication.shared.keyWindow
        }
    }
}

Usage: Loader.shared.show() and Loader.shared.hide()

Whats wrong with the code?

1

There are 1 answers

0
Bar Kozlovski On
   Maybe when you show the loader you can change the main view isUserInteractionEnabled to false and after you will finish the loading process change it again to true?
    
             DispatchQueue.main.async {
               Loader.shared.show()
               self.isUserInteractionEnabled = false
            }