Условно переопределить системный метод через категории в Objective-C? - PullRequest
7 голосов
/ 18 марта 2010

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

Справочная информация: Я создаю приложение, рассчитанное как на 10,5, так и на 10,6. Проблема в том, что я недавно понял, что метод +[NSSortDescriptor sortDescriptorWithKey:ascending:] существует только в 10.6, и мой код уже засорен этим вызовом метода. Я мог бы предоставить для него реализацию по умолчанию (поскольку на этот раз это не так уж сложно реализовать самостоятельно), но я хочу, чтобы «родная» была вызвана всякий раз, когда мое приложение работает на 10.6. Кроме того, если в будущем я столкнусь с подобными проблемами (с более сложными для реализации методами), я не смогу обойтись без замены одной строки.

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

Спасибо.

Ответы [ 4 ]

7 голосов
/ 18 марта 2010

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

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

4 голосов
/ 18 марта 2010

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

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

1 голос
/ 18 марта 2010

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

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

0 голосов
/ 18 марта 2010

подумайте о компромиссе между изменением initWithKey: ascending: метод и добавлением нового метода во время выполнения - просто подкласс 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...