Подтвердить что ты не робот

Аспектно-ориентированная библиотека Objective-C?

Есть ли какая-либо аспект-ориентированная библиотека Objective-C, которую я мог бы использовать для разработки iPhone?

4b9b3361

Ответ 1

Существует старый проект AspectCocoa, это может быть то, что вы ищете.

В противном случае Í предложит вам перевернуть. Либо на основе AOP на основе прокси, путем подклассификации NSProxy для изменения. Или вы можете сделать какой-то метод swizzling с довольно крутой функцией времени выполнения Obj-C method_exchangeImplementations().

Но если вы не ищете забавное упражнение, спросите себя, чего вы хотите достичь, и если есть существующий отлично работающий способ Objective-C.

Ответ 2

Ознакомьтесь с моей статьей о возможном решении: http://codeshaker.blogspot.com/2012/01/aop-delivered.html

Основная идея состоит в том, чтобы сделать крючок в механизм отправки сообщений и принудительно перенаправить его на маршрут пересылки сообщений:

Итак, краткое объяснение того, как это работает:

  • При регистрации вызова метода определенного класса он создает объект-оболочку метода (AOPMethod) и сохраняет каждую информацию в нем об этом конкретном методе наряду с блоком, который будет использоваться при перехват.

  • Изменяет реализацию метода на _objc_msgForward или _objc_msgForward_stret, используя метод_создание. Это тот момент, когда мы направляем отправку сообщений на пересылку механизм. В следующий раз, когда сообщение вызывается в базовом классе, оно вернет реализацию _objc_msgForward, как если бы она не обнаружила реализация. Поэтому он начинает разрешать это, пройдя через отправке сообщений. Ницца.

  • Мы добавляем метод forwardingTargetForSelector: в базовый класс, используя class_addMethod, чтобы указать на нашу реализацию в AOPAspect класс. Также мы добавляем оригинальную реализацию метода и селектор (с расширенным именем для предотвращения конфликтов между классами) AOPAspect.

  • В методе forwardingTargetForSelector: мы возвращаем экземпляр AOPAspect. При этом мы отправляем сообщение с базовый объект для нашего объекта AOPAspect.

  • Этот метод forwardingTargetForSelector: будет снова вызван на AOPAspect, поскольку у нас нет этого селектора. В этом случае мы return nil, поэтому дальнейшие шаги пересылки сообщений и methodSignatureForSelector: и forwardInvocation: методы на AOPAspect.

  • В методеSignatureForSelector: мы вернули правильную сигнатуру сообщения, которая уже хранится в словаре в оболочке метода объект.

  • В то время, когда он приходит к нашей реализации forwardInvocation: в AOPAspect у нас есть полностью настроенный экземпляр NSInvocation и Единственное, что нам нужно сделать, это изменить селектор на расширенный версию мы добавили в класс AOPAspect. Здесь мы можем запускать блоки зарегистрированный для данного метода до/после или даже вместо вызов метода. И, конечно, мы можем запустить оригинальный метод, позвонив [anInvocation invoke].

  • Для простоты мы просто передаем объект NSInvocation в блоки, зарегистрированные для метода, поэтому они могут обращаться ко всем аргументам и возвращаемое значение также через getArgument: atIndex: и getReturnValue: методы.

И что это. Он работает со всеми типами возвращаемых типов, типами аргументов и любые варианты аргументов.

Вы можете найти конкретный пример по приведенной выше ссылке. Пожалуйста, не стесняйтесь использовать его.

Ответ 3

Вопрос старый, но сегодня я открыл этот проект, и он может быть полезен кому-то в будущем.

https://github.com/steipete/Aspects

Ответ 4

Также вы можете проверить библиотеку на https://github.com/moszi/AOP-in-Objective-C, который является очень простым подклассом NSProxy, позволяющим перехватить начало и конец вызова метода.

С этим вы даже можете создать прокси-класс для объектов, чтобы сообщения, отправленные на ваш объект, были сериализованы по одному потоку независимо от вызывающего потока.

Ответ 5

Все заинтересованные люди должны взглянуть на https://github.com/mgebele/MGAOP

Кажется, это новый проект с будущим потенциалом.

Ответ 6

Проверьте этот https://github.com/pvantrepote/FlexOC Это альфа-версия и использует (на данный момент) реализацию Proxy. Это также инъекции зависимостей.

Ответ 7

Я работаю над реальным (это больше, чем метод-swizzling) AOP-Framework для Objective-C. Скоро появится альфа. Вы можете послушать мою немецкую презентацию на конференции Macoun'09: http://www.macoun.de/video2009ts6.php

Если вы все еще интересуетесь АОП для Objective-C, вы можете отправить мне письмо на [email protected] или просто посетить этот сайт: aspective-c.com/index.html За несколько недель. В течение нескольких недель появится англоязычная версия (yup, не переведенная мной;-)) на сайт и руководство.

Ответ 9

С Objective-C я бы предложил пойти с здесь много используемым шаблоном Category- и Delegate-Pattern. Они могут быть более полезными, чем АОП. Не пытайтесь решить свои проблемы с решениями, которые вы изучили для других языков.

Ответ 10

Я сделал некоторые рудиментарные функции pre и post process в категории NSObject

@implementation NSObject (AOP)

- (void)preprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
    Method m1 = class_getInstanceMethod(self.class, sel);
    IMP imp1 = method_getImplementation(m1);

    SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"pre"] cStringUsingEncoding:NSUTF8StringEncoding]);
    class_addMethod(self.class,replacement, imp1, nil);

    method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
        implementingBlock(x,param);
        [x performSelector:replacement withObject:param];
    }));
}

- (void)postprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
    Method m1 = class_getInstanceMethod(self.class, sel);
    IMP imp1 = method_getImplementation(m1);

    SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"post"] cStringUsingEncoding:NSUTF8StringEncoding]);
    class_addMethod(self.class,replacement, imp1, nil);

    method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
        [x performSelector:replacement withObject:param];
        implementingBlock(x,param);
    }));
}
@end