В каком порядке вызываются методы + initialize и + load? - PullRequest
0 голосов
/ 30 декабря 2018

Давайте представим, что у нас есть два класса:

@interface First : NSObject

@end

@interface Second : NSObject

@end

@implementation First
+(void)load
{
    NSLog(@"This must be called first");
}
@end

@implementation Second
+(void)load
{
    NSLog(@"And this must be called second");
}
@end

У нас есть +load методы в каждом классе.Если мы запустим этот код, This must be called first будет первым, а And this must be called second будет вторым.

От чего зависит порядок вызова +load методов этого класса?В моем эксперименте, если я перемещу @implementation второго класса до @implementation первого класса - And this must be called second печатается первым, а This must be called first печатается вторым.Значит ли это, что порядок +load зависит только от порядка в исходном коде?

В моем реальном случае у меня есть предварительно скомпилированный фреймворк с пользовательским +load (некоторый код вызывается до main(), и я вижу логи из него), и мне нужно выполнить свой код перед этим кодом (и, как японимаю - я могу поместить его в +load, но я не знаю, как изменить порядок).Или, может быть, я могу вызвать свой код до кода фреймворка с помощью другой техники?

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018
Методы

+load вызываются средой выполнения objc как часть процесса загрузки изображения (вы можете увидеть это, взломав метод load и напечатав трассировку стека).

Порядок, в котором +load вызываемые методы, кажется, зависят от порядка списков классов objc, сгенерированных clang.

Если вы посмотрите на исходный код среды выполнения objc, вы увидите, что load_images (функция, вызываемая dyld), вызывает prepare_load_methods, чтобы получить список всех классов объектов в изображении.prepare_load_methods вызывает _getObjc2NonlazyClassList, который выбирает список классов objc из секции __objc_nlclslist изображения.

load_images, затем вызывает call_load_methods,который проходит через все загруженные классы и вызывает их +load методы.

0 голосов
/ 30 декабря 2018

Вы действительно не можете полагаться на заказ и не можете эффективно контролировать порядок.По дизайну.+load должно произойти до +initialize этого класса , но их порядок, по-видимому, неопределенен для нескольких классов (что я нахожу немного удивительным, но вполне в рамках правил).

Это большая часть того, почему вы не должны выполнять тяжелую работу в +load или +initialize.Они действительно должны использоваться только экономно и только для инициализации небольшого количества сильно локализованного состояния.Прикосновение к другим важным подсистемам опасно, потому что вы будете изменять порядок и поведение инициализации способами, которые могут нарушить работу системы.Не должно, но может, может, и имеет в прошлом.

Вместо этого вам действительно следует попытаться указать точку «начала здесь» в коде вашей платформы, в которую клиент явно обращается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...