1

I encountered a weird behavior. The best way I can put it is … Not overridden protocol methods in a class extension are not called while the superclass already conforms to the protocol (via extension). However this happens only while it's build with the release build configuration.

class A: UIViewController {}

extension A: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("scrollViewDidScroll in superclass")
    }
}

class B: A {
    // A tableView (and its data source and delegate) is set here…
}

extension B: UITableViewDelegate {
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        super.scrollViewDidScroll(scrollView)
        print("scrollViewDidScroll in subclass")
    }

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        print("scrollViewDidEndDragging")
    }
}

The output:

scrollViewDidScroll in superclass

scrollViewDidScroll in subclass

scrollViewDidEndDragging

however if I build it with the release build configuration, the output is

scrollViewDidScroll in superclass

scrollViewDidScroll in subclass

I can solve the problem if I don't use the extension for protocol conformance approach in the class B and just use the regular way instead (put the methods that implement a protocol into the class).

The question is … how come?

Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84
  • Seems like it could be related to [delegate methods in child class sometimes not called with swift 5 compiler](https://stackoverflow.com/questions/55393027/delegate-methods-in-child-class-sometimes-not-called-with-swift-5-compiler) and [SR-2919](https://bugs.swift.org/browse/SR-2919). So it is allegedly resolved in Swift 5.1, but the problem is still a bit different. – Jakub Truhlář Jun 18 '19 at 12:56

1 Answers1

0

I too encountered the same behaviour.

Xcode version - 12.4 Swift version - 4.2

I also encounter that this behaviour is shown only when applicationDidBecomeActive method is called in the application.(Mostly when you have navigation to some other Screen like authentication etc)

Fix: You need to assign the ViewController as delegate again.

func applicationDidBecomeActive(_ application: UIApplication) {

    fixesForCallBackInExt()
}

func fixesForCallBackInExt() {
    guard  let navController = window?.rootViewController as? UINavigationController else { return }
    if let tabVC = navController.topViewController as? UITabBarController, let topVC = tabVC.selectedViewController, topVC.isKind(of: UIViewController.self) {
        // Set Your Delegate = topVC
    } else if let topVC = navController.topViewController, topVC.isKind(of: UIViewController.self) {
        // Set Your Delegate = topVC
    }
}