Условно переопределяя системный метод через категории в Objective C?

Существует ли способ обеспечить реализацию метода (который носит то же самое имя метода, определенного платформой), только, когда метод уже не определяется в системе? Например, метод [NSSomeClass someMethod:] существует только в Mac OS X 10.6 и если мое выполнение приложения в 10,5, я обеспечу что определение метода в категории. Но когда выполнение приложения в 10,6, я хочу, чтобы обеспеченный ОС метод работал.

Фон: я создаю приложение, предназначенное и для 10,5 и для 10.6. Проблема состоит в том, что я недавно понял тот метод +[NSSortDescriptor sortDescriptorWithKey:ascending:] только существует в 10,6, и мой код уже замусорен тем вызовом метода. Я мог обеспечить реализацию по умолчанию для него (так как это время, не слишком трудно реализовать его сам), но я хочу, чтобы "собственное" было названо каждый раз, когда мое выполнение приложения на 10,6. Кроме того, если я встречаюсь с подобными проблемами в будущем (с большим количеством difficult-to-implement-myself методов), я не смог сходить с рук обеспечение замены остроты.

Этот вопрос, неопределенно подобный, чтобы Переопределить метод через Категорию ObjC и назвать реализацию по умолчанию? но различие - то, что я хочу обеспечить реализации только, когда система уже не имеет того.

Спасибо.

7
задан Community 23 May 2017 в 12:18
поделиться

4 ответа

Да, это возможно. Поскольку вы нацелены на 10.5+, я предполагаю, что вы используете среду выполнения ObjC2, что делает ее довольно простой.

В Справочнике по времени выполнения Objective-C есть все методы, которые вам понадобятся. В частности, вы можете использовать class_getClassMethod или class_getInstanceMethod, чтобы узнать, существует ли метод уже, а затем class_addMethod, чтобы привязать вашу реализацию к этому селектору, если у класса его еще нет.

4
ответ дан 6 December 2019 в 21:12
поделиться

В качестве альтернативы вы можете просто выполнить поиск и выполнить подпрограмму - [NSSortDescriptor initWithKey: ascending:] , а затем добавить соответствующий оператор выпуска.

Это более громоздко в реализации, но гораздо менее уязвимо и подвержено ошибкам, чем изменение самого класса. Это особенно верно, если вы никогда не делали этого раньше. Вы, вероятно, потратите больше времени на то, чтобы разобраться с переопределением, чем просто на поиск.

1
ответ дан 6 December 2019 в 21:12
поделиться

Я бы скомпилировал + [NSSortDescriptor sortDescriptorWithKey: ascending:] в категории в отдельный пакет. Затем в самом начале вашего основного файла проверьте, есть ли в классе NSSortDescriptor метод sortDescriptorWithKey: ascending: с RespondsToSelector: . Если это не реализовано (т.е. вы работаете на <10.6), загрузите пакет с помощью - [NSBundle loadAndReturnError:] .

Таким образом, вы запустите предоставленный ОС метод на 10.6 и вашу реализацию на 10.5.

7
ответ дан 6 December 2019 в 21:12
поделиться

подумайте о компромиссе между изменением initWithKey: ascending: method и и добавлением нового метода во время выполнения - просто создайте подкласс NSSortDescriptor и замените все вызовы NSSortDescriptor на NSMySortDescriptor;

//NSMySortDescriptor.h
@interface NSMySortDescriptor : NSSortDescriptor {
}
- (id)initWithKey:(NSString *)keyPath ascending:(BOOL)ascending
@end

//NSMySortDescriptor.m

@implementation NSMySortDescriptor
- (id)initWithKey:(NSString *)keyPath ascending:(BOOL)ascending{
   // check if super i.e. has initWithKey:ascending: method
   if( [NSSortDescriptor instancesRespondToSelector:@selector(initWithKey:ascending:)] ) {
      [NSSortDescriptor initWithKey:ascending:];
   }
   else{
     // your custom realization for Mac OS X 10.5
     //...
   }
}
@end
0
ответ дан 6 December 2019 в 21:12
поделиться