Я просто хочу получить имя селектора, аргументы, отправитель или экземпляр NSInvocation каждый раз при отправке сообщения объекту. Возможное? Что-то вроде forwardInvocation :, но в случае evey (каждый вызов метода).Есть ли способ наблюдать за каждым вызовом сообщений, вызываемым на объекте (iOS)?
ответ
Существует способ получить имя и цель селектора, используя скрытые параметры в сообщениях цели-c. От Apple's documentation:
Когда objc_msgSend находит процедуру, которая реализует метод, он вызывает процедуру и передает ей все аргументы в сообщении. Он также проходит процедуру, два скрытых аргумента:
принимающий объект Селектор для метода
Таким образом, в методе вы можете получить следующее:
id target = getTheReceiver();
SEL method = getTheMethod();
Если это еще не достаточно для ваших нужд, вы можете сделать следующее:
- Создайте класс под названием
Helper
. - Добавить ссылку на класс, где вы будете вызывать методы, в следующем формате:
id <HelperDelegate> myClassReference;
- Когда вам нужно сделать
[self method]
вместо этого создать экземпляр этогоHelper
класса и вызвать метод на него, как[helper method];
и добавить это[helper setMyClassReference:self];
. - Приложение должно потерпеть крах, но затем просто добавьте
forwardInvocation:
на классHelper
. Оттуда вы сможете получить объектNSInvocation
. Сделайте то, что вам нужно сделать, а затем:[anInvocation invokeWithTarget:myClassReference];
, чтобы вы могли передать сообщение первому абоненту.
P.S: Даже если это не отвечает на вопрос, +1 за вопрос .. На самом деле меня думать об этом.
Итак, я сделал этот класс, работает как шарм.
.h
@protocol PGMessageObserverDelegate
-(void)observedInvocation:(NSInvocation*) invocation willSendToObject:(id) object;
-(void)observedInvocation:(NSInvocation*) invocation didSendToObject:(id) object;
@end
@interface PGMessageObserver : NSObject
@property (nonatomic, readonly) id observable;
@property (nonatomic, readonly) id <PGMessageObserverDelegate> delegate;
+(id)messageObserverObserving:(id) observable delegate:(id) delegate;
@end
.m
#import "PGMessageObserver.h"
@interface PGMessageObserver()
-(id)initWithObservable:(id) observable delegate:(id) delegate;
@end
@implementation PGMessageObserver
@synthesize observable = _observable;
@synthesize delegate = _delegate;
#pragma mark - Creation
+(id)messageObserverObserving:(id) observable delegate:(id) delegate
{
return [[[PGMessageObserver alloc] initWithObservable:observable delegate:delegate] autorelease];
}
-(id)initWithObservable:(id) observable delegate:(id) delegate
{
if (self = [super init])
{
_observable = observable;
_delegate = delegate;
}
return self;
}
#pragma mark - Message forwarding
-(void)forwardInvocation:(NSInvocation*) invocation
{
//Notify.
[_delegate observedInvocation:invocation willSendToObject:_observable];
//Forward.
if (_observable != nil)
{
[invocation invokeWithTarget:_observable];
//Notify.
[_delegate observedInvocation:invocation didSendToObject:_observable];
}
}
-(NSMethodSignature*)methodSignatureForSelector:(SEL) selector
{
return [_observable methodSignatureForSelector:selector];
}
@end
Это не так строго, как это может быть, но он уведомляет меня о каждом действии отправить этот наблюдатель, и сообщение затем перенаправляется к исходному объекту (наблюдаемый).
Клиентский код только сохранил собственность ...
@property (nonatomic, retain) PGMessageObserver *messageObserver;
#define self_OBSERVED _messageObserver
... и установка где-то.
self.messageObserver = [PGMessageObserver messageObserverObserving:self delegate:self];
Наблюдаемые сообщения затем должны отправляться в SELF_OBSERVED insted of self.
Эй, я обожаю обходной путь с «промежуточным» объектом! – Geri
Это действительно здорово! – Geri
Я займусь этим прямо сейчас. – Geri