Если вы расширяете вопрос от простого изменения к реальной модификации библиотеки, то я могу вспомнить полезные примеры.
Начиная с iOS 5, NSURLConnection
предоставляет sendAsynchronousRequest:queue:completionHandler:
,который является блочным (/ closure) управляемым способом выполнения асинхронной загрузки из любого ресурса, идентифицируемого с помощью URL (локального или удаленного).Это очень полезный способ продолжить работу, так как он делает ваш код чище и меньше, чем классическая альтернатива делегата, и с гораздо большей вероятностью сохраняет связанные части кода рядом друг с другом.
Этот метод нене поставляется в iOS 4. Итак, что я сделал в своем проекте, так это то, что, когда приложение запускается (через подходящий + (void)load
), я проверяю, определен ли метод.Если нет, я исправляю реализацию этого класса.Отныне каждая другая часть программы может быть записана в спецификации iOS 5 без выполнения какой-либо проверки версии или проверки доступности точно так же, как если бы я предназначался только для iOS 5, за исключением того, что она также будет работать на iOS 4.
В Java или C ++, я думаю, того же можно добиться, создав собственный класс для выдачи соединений URL-адресов, который выполняет проверку во время выполнения при каждом вызове.Это худшее решение, потому что от него труднее отступить.Таким образом, если однажды я решу поддерживать только iOS 5, я просто удаляю исходный файл, в котором добавлена моя реализация sendAsynchronousRequest:...
.Больше ничего не меняется.
Что касается метода swizzling, то единственное, что я вижу в нем, это когда кто-то хочет изменить функциональность существующего класса и не имеет доступа к коду, в котором этот класс создан.Таким образом, вы обычно говорите о попытке изменить логически непрозрачный код извне, делая предположения о его реализации.Я бы не стал поддерживать это как идею на любом языке.Я полагаю, что в Objective-C его рекомендуют больше, потому что Apple более склонна к непрозрачности (см., Например, каждое приложение, которое хотело показывать настраиваемый вид камеры до iOS 3.1, каждое приложение, которое хотело выполнить пользовательскую обработку на входе камеры до этого).на iOS 4.0 и т. д.), а не потому, что это хорошая идея в Objective-C.Это не так.
РЕДАКТИРОВАТЬ: так, в дальнейшем изложении - я не могу опубликовать полный код, потому что я написал его как часть моей работы, но у меня есть класс с именем NSURLConnectionAsyncForiOS4
с реализацией sendAsynchronousRequest:queue:completionHandler:
.Эта реализация на самом деле довольно тривиальна, просто отправляя операцию в назначенную очередь, которая выполняет синхронную загрузку через старый интерфейс sendSynchronousRequest:...
, а затем отправляет результаты этого в обработчик.
Этот класс имеет + (void)load
, который является методом класса, который вы добавляете в класс, который будет выпущен сразу после загрузки этого класса в память, фактически как глобальный конструктор для метакласса и со всеми обычными предостережениями.
В моем+load
Я использую среду выполнения Objective C напрямую через интерфейс C, чтобы проверить, определено ли sendAsynchronousRequest:...
в NSURLConnection
.Если это не так, я добавляю свою реализацию к NSURLConnection
, поэтому отныне она определена.Это явно не так уж и быстро - я не корректирую существующую реализацию чего-либо, я просто добавляю пользовательскую реализацию чего-либо, если Apple не доступна.Соответствующие вызовы времени выполнения: objc_getClass
, class_getClassMethod
и class_addMethod
.
В остальной части кода, когда я хочу выполнить асинхронное соединение URL, я просто пишу, например,
[NSURLConnection sendAsynchronousRequest:request
queue:[self anyBackgroundOperationQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *blockError)
{
if(blockError)
{
// oh dear; was it fatal?
}
if(data)
{
// hooray! You know, unless this was an HTTP request, in
// which case I should check the response code, etc.
}
/* etc */
}
Таким образом, остальная часть моего кода просто написана для API iOS 5 и не знает и не заботится о том, что у меня есть прокладка где-то еще, чтобы обеспечить изменение одной микроскопической части iOS 5 на iOS 4. И, как я уже сказал, когда япрекрати поддерживать iOS 4, я просто удалю прокладку из проекта, а весь остальной мой код по-прежнему не будет знать или беспокоиться.
У меня был похожий код для предоставления альтернативной частичной реализации NSJSONSerialization
(которая динамически создавала новый класс во время выполнения и копировала в него методы);единственное изменение, которое вам нужно сделать, это то, что ссылки на NSJSONSerialization
в другом месте будут разрешаться компоновщиком один раз во время загрузки, что вам на самом деле не нужно.Поэтому я добавил быстрый #define
из NSJSONSerialization
к NSClassFromString(@"NSJSONSerialization")
в моем предварительно скомпилированном заголовке.Что является менее функционально аккуратным, но схожим направлением действия с точки зрения поиска способа сохранить поддержку iOS 4 в то время, пока просто записываю остальную часть проекта в стандарты iOS 5.