     /// If set to `true`, SimpleButton shows `loadingView` and hides the default `titleLabel` and `imageView`
     open var isLoading: Bool = false {
         didSet {
-            if isLoading {
-                isUserInteractionEnabled = false
-                if loadingView == nil {
-                    let activityIndicator = UIActivityIndicatorView(style: .white)
-                    activityIndicator.startAnimating()
-                    activityIndicator.hidesWhenStopped = false
-                    loadingView = activityIndicator
+            DispatchQueue.main.async {
+                if self.isLoading {
+                    
+                    if self.loadingView == nil {
+                        self.setDefaultLoadingView()
+                    }
+                    self.isUserInteractionEnabled = false
+                    self.showLoadingView(animaded: true)
+                    
+                } else {
+                    
+                    if !self.state.contains(.disabled) {
+                        self.isUserInteractionEnabled = true
+                    }
+                    self.hideLoadingView(animaded: true)
+                    
                 }
                 
-                if loadingView!.superview == nil {
-                    addSubview(loadingView!)
-                    setLoadingViewConstraints()
-                }
-                
-                loadingView?.isHidden = false
-                titleLabel?.layer.opacity = 0
-                imageView?.isHidden = true
-            }
-            else {
-                if !state.contains(.disabled) {
-                    isUserInteractionEnabled = true
-                }
-                loadingView?.isHidden = true
-                titleLabel?.layer.opacity = 1
-                imageView?.isHidden = false
-            }
-            update()
+                self.update()
+            }
         }
     }
     

    }
    
    /// used to lock any animated state transition for initial setup
    fileprivate var lockAnimatedUpdate: Bool = true
    
    /// used to determine the `from` value of any animation
    fileprivate var sourceLayer: CALayer {
        return (layer.presentation() ?? layer)
    }
    
    // MARK: State values with initial values
    
    fileprivate lazy var backgroundColors: [ControlState: SimpleButtonStateChangeValue<CGColor>] = {
        if let color = self.backgroundColor?.cgColor {
            return [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: color, animated: true, animationDuration: self.defaultAnimationDuration)]
        }
        return [:]
    }()
    
    fileprivate lazy var borderColors: [ControlState: SimpleButtonStateChangeValue<CGColor>] = {
        if let color = self.layer.borderColor {
            return [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: color, animated: true, animationDuration: self.defaultAnimationDuration)]
        }
        return [:]
    }()
    
    fileprivate lazy var buttonScales: [ControlState: SimpleButtonStateChangeValue<CGFloat>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: 1.0, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    
    fileprivate lazy var borderWidths: [ControlState: SimpleButtonStateChangeValue<CGFloat>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: self.layer.borderWidth, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    
    fileprivate lazy var cornerRadii: [ControlState: SimpleButtonStateChangeValue<CGFloat>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: self.layer.cornerRadius, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    
    fileprivate lazy var shadowColors: [ControlState: SimpleButtonStateChangeValue<CGColor>] = {
        if let color = self.layer.shadowColor {
            return [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: color, animated: true, animationDuration: self.defaultAnimationDuration)]
        }
        return [:]
    }()
    
    fileprivate lazy var shadowOpacities: [ControlState: SimpleButtonStateChangeValue<Float>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: self.layer.shadowOpacity, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    
    fileprivate lazy var shadowOffsets: [ControlState: SimpleButtonStateChangeValue<CGSize>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: self.layer.shadowOffset, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    
    fileprivate lazy var shadowRadii: [ControlState: SimpleButtonStateChangeValue<CGFloat>] = {
        [UIControl.State.normal.rawValue: SimpleButtonStateChangeValue(value: self.layer.shadowRadius, animated: true, animationDuration: self.defaultAnimationDuration)]
    }()
    

    
    // MARK: Animation helper
    
    private func animate(layer: CALayer, from: AnyObject?, to: AnyObject, forKey key: String, duration: TimeInterval) {
        let animation = CABasicAnimation()
        animation.fromValue = from
        animation.toValue = to
