DEV Community

Khoa Pham
Khoa Pham

Posted on

2 2

How to avoid UIVisualEffectView crash in iOS

We all know that there's a potential crash with UIVisualEffectView on iOS 11. The fix is to not add sub views directly to UIVisualEffectView, but to its contentView. So we should change

effectView.addSubview(button)

to

effectView.contentView.addubView(button)

Here we don't need to perform iOS version check, because effectView.contentView works for any iOS versions.

Potential cases for crashes

Here are some cases you can potentially cause the crashes

Strange namings

Normally we name our UIVisualEffectView as blurView, effectView. But there's times we name it differently like navigationView, containerView, boxView, ... This way we may completely forget that it's a UIVisualEffectView 🙀

containerView.addSubview(button)
boxView.insertSubview(label, at: 0)

Custom loadView

Sometimes it's convenient to have our UIViewController 's view as a whole blur view, so that all things inside have a nice blur effect background

class OverlayController: UIViewController {
  let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
  override func loadView() {
    super.loadView()
    self.view = blurView
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(button)
  }
}

By setting our blurView as view in loadView, we have no idea afterwards that view is actually a UIVisualEffectView 🙀

Inheritance

What happen if we have another UIViewController that inherits from our OverlayController, all it knows about view is UIView, it does not know that it is a disguising UIVisualEffectView 🙀

class ClocksController: OverlayController {
  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(timeLabel)
  }
}

Superclass type

Sometimes declare our things but with protocol or superclass types. Consumers of our API have no clue to know that it is UIVisualEffectView 🙀

let view: UIView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))

Here it appears to us that view is of type UIView

Legacy codebase

Now imagine you 've handled a legacy codebase to deal with. Perform finding and replacing all those things related to UIVisualEffectView is very hard task. Especially since we tend to write less tests for UI

Making it impossible to crash

I like concept like Phantom type to limit interface. Here we're not using type but a wrapper

final class BlurView: UIView {
  private let effectView: UIVisualEffectView

  init(style: UIBlurEffectStyle, backgroundColor: UIColor? = nil) {
    self.effectView = UIVisualEffectView(effect: UIBlurEffect(style: style))
    self.effectView.backgroundColor = backgroundColor
    super.init(frame: .zero)
    insertSubview(effectView, at: 0)
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError()
  }

  override func addSubview(_ view: UIView) {
    effectView.contentView.addSubview(view)
  }

  override func layoutSubviews() {
    super.layoutSubviews()

    effectView.frame = bounds
  }
}

Here we override addSubview to always add views to effectView.contentView. In the init method, we need to call insertSubview instead because of our overriden addSubview

Now BlurView has a blur effect thanks to is underlying UIVisualEffectView, but expose only addSubview because of its UIView interface. This way it is impossible to cause crashes 😎

let blurView = BlurView(style: .dark)
blurView.addSubview(button(

Original post https://github.com/onmyway133/blog/issues/124

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay