0
extension UIApplication {

    override open var next: UIResponder? {
        print("next")
        return super.next
    }
}

The above code was executed before iOS 13.4, and "next" is printed before the application(_:, didFinishLaunchingWithOptions:) method

On iOS 13.4 and the latest iOS 13.4.1, the console does not output next. If I break the breakpoint on the print() line, the breakpoint will not be executed

This caused some of my previous code to fail, for example:

import UIKit

public extension UIApplication {

    private static let runOnce: Void = {
        NothingToSeeHere.harmlessFunction()
    }()

    override var next: UIResponder? {

        // Called before applicationDidFinishLaunching
        UIApplication.runOnce

        return super.next
    }
}

public protocol SelfAware: class {
    static func awake()
}

public class NothingToSeeHere {

    public static func harmlessFunction() {

        let typeCount = Int(objc_getClassList(nil, 0))
        let types = UnsafeMutablePointer<AnyClass>.allocate(capacity: typeCount)
        let autoreleasingTypes = AutoreleasingUnsafeMutablePointer<AnyClass>(types)

        objc_getClassList(autoreleasingTypes, Int32(typeCount))

        for index in 0 ..< typeCount {
            (types[index] as? SelfAware.Type)?.awake()
        }

        types.deallocate()
    }
}

Why does this happen? Is this a bug in iOS 13.4? Still a feature? I didn't find anything related in the release notes for iOS 13.4 ...


Let me list the situation I tested:

  • 13.2 iPhone, next method execution, and before application(_:, didFinishLaunchingWithOptions:).
  • 13.3 Simulator,next method execution, and before application(_:, didFinishLaunchingWithOptions:).
  • 13.4 Simulator, next method is not executed.
  • 13.4 iPhone, next method is not executed.
  • 13.4.1 iPhone, next method is not executed.
Rakuyo
  • 390
  • 3
  • 15
  • Relying on this method to be called during launch was silly. It’s not a documented event. Stick to those. – matt Apr 08 '20 at 02:59
  • @matt I am very sorry, I did not clarify my question before. Now I have modified it. What I want to know is whether this change is a change on the system, if it is, then on iOS 13.4 and newer systems, is there a way to make the next method run as before – Rakuyo Apr 08 '20 at 03:02
  • But it was never supposed to “run”. – matt Apr 08 '20 at 03:06
  • @matt Thanks, I did n’t know the next method before. I know from http://jordansmith.io/handling-the-deprecation-of-initialize/ that I can do something with the next method, but I can’t do it now. That's why I wanted to know why this happened, and is it possible to "fix" it. Maybe it ’s not a bug, or we should n’t use it to do something – Rakuyo Apr 08 '20 at 03:11
  • I think this question should stay here, because as far as I know, many people use this method. When they upgrade to iOS 13.4, they may also have the same question-why does it not take effect? – Rakuyo Apr 08 '20 at 03:25
  • 1
    Is there somewhere in the documentation that it says "next() is called during didFinishLaunchingWithOptions?" This sounds like you relied on some internal implementation detail, and that detail changed. You can't (and shouldn't) fix that. There are several well-documented ways to run things before `applicationDidFinishLaunching`, most notably `applicationWillFinishLaunching` (and there are things earlier than that, like `main`). I don't know why Jordan Smith suggesting hooking the `next` method. Overriding in an extension has *always* been undefined behavior (going back to ObjC). – Rob Napier Apr 16 '20 at 05:19
  • I would strongly suggest getting rid of this `SelfAware` thing anyway. It's begging to cause problems. Just call the methods you need to call during startup. There's no reason to go digging around in the ObjC runtime like this. Fetching the class list at this point isn't even promised to have all the classes yet (there can be late loading that injects new classes into the hierarchy). It probably "works" if you don't push it too hard, but there's no reason to add so much fragility. – Rob Napier Apr 16 '20 at 05:21
  • 1
    @RobNapier Thank you very much for your reply, your tone makes me feel very cordial and friendly! I have given up this method. But I have to say, "Don't call any method in didFinishLaunchingWithOptions" is really tempting. – Rakuyo Apr 17 '20 at 01:23

2 Answers2

1

Xcode 11.4 and iOS 13.4 don't allow var override in extensions anymore, could it be possible you are using debugging with older Xcode. If you run it but don't debug it that method will be called.

Guille.com
  • 11
  • 1
1

I have meet this issue too, but I open project scheme and uncheck the Debug executable option. the override method can run.

Hu Gforce
  • 371
  • 1
  • 2
  • 9