Как CategoryA переопределить метод categoryB

В AFNetworking 2.0, в UIImageView+AFNetworking есть метод:

+ (id <AFImageCache>)sharedImageCache

Я хочу переопределить его и вернуть сюда свой пользовательский объект. Я также хотел бы переопределить все методы в AFImageCache, поэтому в основном я бы сделал здесь новый протокол. Я думал о методе swizzling, однако из-за отсутствия опыта я не уверен, что он работает нормально с 2 категориями. Что, если моя категория загрузится до категории AFNetworking, будет ли она работать?

И вообще, хорош ли этот подход? Хочу добавить дисковое кеширование в память и интересно какой способ самый чистый с точки зрения качества кода.


person Nat    schedule 28.05.2014    source источник


Ответы (1)


Не используйте категории для переопределения метода. Согласно документации

"If the name of a method declared in a category is the same as a
 method in the original class, or a method in another category on 
 the same class (or even a superclass), the behavior is undefined 
 as to which method implementation is used at runtime. "

обратитесь к документации в разделе «Избегайте конфликтов имен методов категорий» --> https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf

Подкласс и вместо этого переопределить метод и использовать подкласс?

Анализируя ваш сценарий, имеет смысл сделать метод swizzling. Примечание. Убедитесь, что yourCache будет вести себя так же, как и sharedImageCache, иначе это приведет к сбою.

@implementation UIImageView (Swizzling)

      + (void)load {

                static dispatch_once_t token;
                dispatch_once(&token, ^{

                    Class myClass = [self class];

                    Method originalMethod = class_getInstanceMethod(myClass, @selector(sharedImageCache));
                    Method newMethod = class_getInstanceMethod(myClass, @selector(NewSharedImageCache:));
                    method_exchangeImplementations(originalMethod, newMethod);
                });
            }

            //This is just for sample. you can create your buffer in your own way
            static id <yourCache> yourBuffer;
            + (id <yourCache>)NewSharedImageCache
            {
                return yourBuffer;
            }

@end
person Naveen Prasad R    schedule 28.05.2014
comment
Как мне подклассировать категорию из AFNetworking? Или вы хотите переписать AFNetworking? - person Nat; 28.05.2014
comment
Если у вас есть исходный код, измените код, чтобы он возвращал ваш собственный объект. В качестве альтернативы вы можете написать новую категорию с другой подписью, например + (id <YourDelegate>)YourMethod, и внутри нее, если вам нужно sharedImageCache, вы можете вызвать [self sharedImageCache], чтобы получить общий кеш, манипулировать кешем/объектом в кеше и вернуть свой собственный объект. - person Naveen Prasad R; 28.05.2014
comment
Я не хочу менять исходный код для него, так как это можно сделать и без него. С этой категорией я не думаю, что вы правы - вы не знаете, какая из них будет называться, поэтому это не сработает. - person Nat; 28.05.2014
comment
Очевидно, что имя метода отличается, поэтому будет вызван ваш метод. Чего вы пытаетесь достичь, переопределяя метод? - person Naveen Prasad R; 28.05.2014
comment
В этом случае в каждом месте AFNetworking я все равно получаю экземпляр sharedImageCache. Проблема в том, что я хочу заменить sharedImageCache на myImageCache, поэтому каждый метод в этой категории в AFNetworking будет работать с myImageCache, а не с sharedImageCache. Решение, которое вы мне дали, работает противоположным образом. - person Nat; 28.05.2014
comment
Обновленный ответ, попробуйте метод swizzling? - person Naveen Prasad R; 29.05.2014
comment
Давайте продолжим это обсуждение в чате. - person Naveen Prasad R; 29.05.2014
comment
Спасибо за исходник, но я умею качать методы. Пожалуйста, перечитайте мой вопрос, я спрашивал, как это работает с 2 методами из категорий - никогда не знаешь, какой из них загружается быстрее. К сожалению, ваш ответ все еще не отвечает на мой вопрос. - person Nat; 29.05.2014