Мне интересно понять обстоятельства, заставляющие разработчика переопределить + инициализировать или + загрузить. Документация дает понять, что эти методы вызываются для вас средой выполнения Objective-C, но это действительно все, что ясно из документации по этим методам. :-)
Мое любопытство возникает, когда я смотрю пример кода Apple - MVCNetworking. У их модельного класса есть +(void) applicationStartup
метод. Он выполняет некоторую уборку в файловой системе, читает NSDefaults и т. Д. И т. Д., И после попытки изучить методы класса NSObject кажется, что эту работу по уборке можно поместить в + load.
Я изменил проект MVCNetworking, удалив вызов в App Delegate на + applicationStartup и поместив служебные биты в + load ... мой компьютер не загорелся, но это не значит, что это правильно! Я надеюсь получить представление обо всех тонкостях, подводных камнях и многом другом, связанных с пользовательским методом настройки, который вы должны вызывать вместо + load или + initialize.
Документация для + загрузки говорит:
Сообщение о загрузке отправляется классам и категориям, которые как динамически загружаются, так и статически связаны, но только в том случае, если вновь загруженный класс или категория реализует метод, который может отвечать.
Это бессвязное предложение, которое сложно разобрать, если вы не знаете точного значения всех слов. Помогите!
Что подразумевается под «динамически загружаемым и статически связанным?» Может ли что-то быть динамически загружено и статически связано, или они являются взаимоисключающими?
«... вновь загруженный класс или категория реализует метод, который может отвечать» Какой метод? Ответьте как?
Что касается + initialize, в документации говорится:
инициализировать, он вызывается только один раз для каждого класса. Если вы хотите выполнить независимую инициализацию для класса и для категорий класса, вы должны реализовать методы загрузки.
Я понимаю, что это означает: «Если вы пытаетесь настроить класс ... не используйте инициализацию». В порядке Хорошо. Когда и зачем тогда переопределить инициализацию?
источник
+load
рассылается отдельно для категорий; то есть каждая категория в классе может содержать свой собственный+load
метод.initialize
будет правильно вызыватьсяload
из-заload
ссылки на неинициализированный объект. Это может (как ни странно, но разумно) привести кinitialize
забегу раньшеload
! Во всяком случае, это то, что я наблюдал. Похоже, что это противоречит «И к тому времени, когда вы получитеinitialize
, каждый класс в вашем процессе должен уже получитьload
(если необходимо)».load
первым. Затем вы можете получить,initialize
покаload
все еще работает.Это означает, что не переопределяйте
+initialize
категорию, вы, вероятно, что-то сломаете.+load
вызывается один раз для каждого класса или категории, которая реализует+load
, как только этот класс или категория загружается. Когда он говорит «статически связанный», это означает, что он скомпилирован в двоичный файл вашего приложения. Эти+load
методы по классам , таким образом , составленных будут выполняться , когда ваше приложение запускает, возможно , прежде чем он войдетmain()
. Когда он говорит «динамически загружается», это означает загружается через пакеты плагинов или вызовdlopen()
. Если вы используете iOS, вы можете проигнорировать этот случай.+initialize
вызывается при первой отправке сообщения классу, непосредственно перед обработкой этого сообщения. Это (очевидно) случается только один раз. Если вы переопределите+initialize
категорию, произойдет одно из трех:Вот почему вы никогда не должны переопределять
+initialize
в категории - на самом деле довольно опасно пытаться заменить любой метод в категории, потому что вы никогда не уверены, что вы заменяете, или ваша собственная замена сама будет заменена другой категорией.Кстати, еще одна проблема, которую следует учитывать,
+initialize
заключается в том, что если кто-то вас подклассифицирует, вы потенциально можете получить вызов один раз для своего класса и один раз для каждого подкласса. Если вы делаете что-то вроде установкиstatic
переменных, вам нужно защититься от этого: либо сdispatch_once()
помощью тестирования, либо путем тестированияself == [MyClass class]
.источник