Search code examples
ioscrashautolayout

How can I make my iOS app crash when a view is laid out ambiguously?


I want to notify developers on my team, and prevent them from going further, when they have created a view that has ambiguous constraints. To do this, I want to make the phone crash (in debug). I could poll periodically to see if any views in the hierarchy have hasAmbiguousLayout set to true, but this is not great. However, it looks like iOS reports ambiguous layouts in its Runtime Issues area. So, there must be some equivalent of UIViewAlertForUnsatisfiableConstraints for ambiguous layouts. How can I make it crash?


Solution

  • Swizzle UIViewController.viewDidLayoutSubviews and UIView.layoutSubviews and assert !hasAmbiguousLayout == false

    Here is a playground example:

    import UIKit
    import PlaygroundSupport
    
    extension UIViewController {
      @objc private func swizzledViewDidLayoutSubviews() {
        assert(!view.hasAmbiguousLayout)
        print("inside the swizzledViewDidLayoutSubviews method for \(Self.self) ")
        swizzledViewDidLayoutSubviews()
      }
    
      private static let swizzleImplementation: Void = {
        guard let original = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.viewDidLayoutSubviews as (UIViewController) -> () -> Void)),
          let swizzled = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.swizzledViewDidLayoutSubviews)) else {
            return
        }
        method_exchangeImplementations(swizzled, original)
      }()
    
      static func swizzle() {
        _ = swizzleImplementation
      }
    }
    
    class V: UIViewController {}
    UIViewController.swizzle()
    let v = V()
    PlaygroundPage.current.liveView = v