Changed + load method order in Xcode 7

Ich habe herausgefunden, dass Xcode 7 (Version 7.0 (7A220)) die Reihenfolge geändert hat, in der+load Methoden für Klassen und Kategorien werden bei Unit-Tests aufgerufen.

Wenn eine zum Testziel gehörende Kategorie ein @ implementie+load -Methode, wird jetzt am Ende aufgerufen, wenn Instanzen der Klasse möglicherweise bereits erstellt und verwendet wurden.

Ich habe einAppDelegate, das @ implementie+load Methode. DasAppDelegate.m Datei enthält auchAppDelegate (MainModule) Kategorie. Zusätzlich gibt es eine Unit-Test-DateiLoadMethodTestTests.m, das eine andere Kategorie enthält -AppDelegate (UnitTest).

Beide Kategorien implementieren auch+load Methode. Die erste Kategorie gehört zum Hauptziel, die zweite - zum Testziel.

Cod

Ich habe ein kleines @ gemactest project, um das Problem zu demonstrieren. Es ist ein leeres Xcode One View-Standardprojekt, bei dem nur zwei Dateien geändert wurden.

AppDelegate.m:

#import "AppDelegate.h"

@implementation AppDelegate

+(void)load {
    NSLog(@"Class load");
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"didFinishLaunchingWithOptions");

    return YES;
}

@end

@interface AppDelegate (MainModule)
@end

@implementation AppDelegate (MainModule)

+(void)load {
    NSLog(@"Main Module +load");
}

@end

Und eine Unit-Test-Datei (LoadMethodTestTests.m):

#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "AppDelegate.h"

@interface LoadMethodTestTests : XCTestCase

@end

@interface AppDelegate (UnitTest)
@end

@implementation AppDelegate (UnitTest)

+(void)load {
    NSLog(@"Unit Test +load");
}

@end

@implementation LoadMethodTestTests

-(void)testEmptyTest {
    XCTAssert(YES);
}

@end
Teste

Ich habe dieses Projekt auf Xcode 6/7 Unit-Tests unterzogen (der Code und der Github-Link befinden sich unten) und Folgendes erhalten:+load ruft Reihenfolge auf:

Xcode 6 (iOS 8.4 simulator):
    Unit Test +load
    Class load
    Main Module +load
    didFinishLaunchingWithOptions

Xcode 7 (iOS 9 simulator):
    Class load
    Main Module +load
    didFinishLaunchingWithOptions
    Unit Test +load

Xcode 7 (iOS 8.4 simulator):
    Class load
    Main Module +load
    didFinishLaunchingWithOptions
    Unit Test +load
Frag

Xcode 7 führt die Testzielkategorie aus+load Methode Unit Test +load) am Ende nach demAppDelegate wurde bereits erstellt.Ist es ein korrektes Verhalten oder ist es ein Fehler, der an Apple gesendet werden sollte?

Kann es sein, dass es nicht spezifiziert ist, so dass der Compiler / die Laufzeit frei ist, um Aufrufe neu anzuordnen? Ich habe mir @ angesehdiese SO Frage sowie auf dem + Beschreibung in der NSObject-Dokumentation laden aber ich habe nicht ganz verstanden, wie die+load -Methode soll funktionieren, wenn die Kategorie zu einem anderen Ziel gehört.

Oder vielleichtAppDelegate ist eine Art Sonderfall aus irgendeinem Grund?

Warum frage ich dasBildungs GründeIch habe Methoden-Swizzling in einer Kategorie innerhalb des Unit-Test-Ziels durchgeführt. Wenn sich die Anrufreihenfolge geändert hat,applicationDidFinishLaunchingWithOptions wird vor dem Swizzeln ausgeführt. Ich glaube, es gibt andere Möglichkeiten, dies zu tun, aber es scheint mir nur kontraintuitiv zu sein, wie es in Xcode 7 funktioniert. Ich dachte, wenn eine Klasse in den Speicher geladen wird,+load dieser Klasse und+loads wird angenommen, dass @ -Methoden aller Kategorien aufgerufen werden, bevor wir mit dieser Klasse etwas anfangen können (z. B. eine Instanz erstellen und @ aufrufendidFinishLaunching...).

Antworten auf die Frage(4)

Ihre Antwort auf die Frage