문제

Objective-C에서 메소드 호출을 차단할 수 있습니까? 어떻게?

편집하다: 마크 파월대답의 대답은 나에게 부분적인 해결책을 주었다. -forwardinvocation 방법. 그러나 문서에 따르면 -forwardInvocation은 객체에 해당 메소드가없는 메시지가 전송 될 때만 호출됩니다. 수신기에 해당 선택기가있는 경우에도 모든 상황에서 방법을 호출하고 싶습니다.

도움이 되었습니까?

해결책

당신은 메소드 호출을 스와이즈글함으로써 그것을합니다. 모든 릴리스를 NstableView로 가져 가고 싶다고 가정합니다.

static IMP gOriginalRelease = nil;
static void newNSTableViewRelease(id self, SEL releaseSelector, ...) {
   NSLog(@"Release called on an NSTableView");
   gOriginalRelease(self, releaseSelector);
}


  //Then somewhere do this:
  gOriginalRelease = class_replaceMethod([NSTableView class], @selector(release), newNSTableViewRelease, "v@:");

목표 C 런타임에서 더 자세한 내용을 얻을 수 있습니다. 선적 서류 비치.

다른 팁

Objective-C에서 메소드 호출을 가로 채기 방법 스위 즈 링.

이를 구현하는 방법에 대한 소개를 찾을 수 있습니다. 여기. 실제 프로젝트에서 메소드 스와이글링이 구현되는 방법을 예로 들어 보려면 체크 아웃 OCMOCK (Objective-C를위한 분리 프레임 워크).

Objective-C에서 메시지 보내는 것은 함수의 호출로 변환됩니다. objc_msgSend(receiver, selector, arguments) 또는 그 변형 중 하나 objc_msgSendSuper, objc_msgSend_stret, objc_msgSendSuper_stret.

이러한 기능의 구현을 변경할 수 있다면 모든 메시지를 가로 채 릴 수 있습니다. 안타깝게도, objc_msgSend 목표 C 런타임의 일부이며 재정의 할 수 없습니다.

인터넷 검색으로 Google 도서에서 논문을 찾았습니다. Charlotte Pii Lunau의 프로세스 제어 응용 프로그램을위한 반사 아키텍처. 이 논문은 객체를 리디렉션하여 해킹을 소개합니다. isa Custom MetaObject 클래스의 인스턴스에 대한 클래스 포인터. 따라서 수정 된 객체를 위해 의도 된 메시지는 MetaObject 인스턴스로 전송됩니다. MetaObject 클래스에는 자체 방법이 없으므로 메시지를 수정 된 객체로 전달하여 전진 호출에 응답 할 수 있습니다.

이 논문에는 소스 코드의 흥미로운 비트가 포함되어 있지 않으며 그러한 접근 방식이 코코아에서 부작용이 있는지 전혀 모른다. 그러나 시도하는 것은 흥미로울 수 있습니다.

응용 프로그램 코드에서 메시지를 보내려면 -forwardingTargetForselector : 팁은 솔루션의 일부입니다.
객체를 감싸십시오 :

@interface Interceptor : NSObject
@property (nonatomic, retain) id interceptedTarget;
@end

@implementation Interceptor
@synthesize interceptedTarget=_interceptedTarget;

- (void)dealloc {
    [_interceptedTarget release];
    [super dealloc];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"Intercepting %@", NSStringFromSelector(aSelector));
    return self.interceptedTarget;
} 

@end

이제 다음과 같은 일을하십시오.

Interceptor *i = [[[Interceptor alloc] init] autorelease];
NSFetchedResultsController *controller = [self setupFetchedResultsController];
i.interceptedTarget = controller;
controller = (NSFetchedResultsController *)i;

그리고 당신은 메시지 보내기 로그가 있습니다. 참고, 인터셉트 된 객체 내에서 전송 된 보내기는 원래 오브젝트 'self'포인터를 사용하여 전송되므로 인터셉트되지 않습니다.

외부에서 호출 된 메시지 만 로그인하려면 (일반적으로 대의원에서 호출하고, 어떤 종류의 메시지,시기 등을 확인하기 위해) responseelector를 다음과 같이 재정의 할 수 있습니다.

- (BOOL)respondsToSelector:(SEL)aSelector {
NSLog(@"respondsToSelector called for '%@'", NSStringFromSelector(aSelector));

// look up, if a method is implemented
if([[self class] instancesRespondToSelector:aSelector]) return YES;

return NO;

}

서브 클래스를 만듭니다 NSProxy 그리고 구현 -forwardInvocation: 그리고 -methodSignatureForSelector: (또는 -forwardingTargetForSelector:, 단순히 메소드를 직접 피하는 대신 두 번째 객체로 지시하는 경우).

NSProxy 구현을 위해 설계된 클래스입니다 -forwardInvocation: 에. 그것은 몇 가지 방법이 있지만 대부분 당신은 그들이 잡히기를 원하지 않습니다. 예를 들어, 기준 계수 방법을 잡으면 쓰레기 수집하에 프록시가 거래되는 것을 방지 할 수 있습니다. 그러나 특정 방법이 있다면 NSProxy 당신이 절대적으로 전달해야한다는 것은 그 방법을 구체적으로 무시하고 -forwardInvocation: 수동으로. 메소드가 아래에 나열되어 있기 때문에 NSProxy 문서화는 그것을 의미하지 않습니다 NSProxy 그것을 구현하면, 단지 모든 프록시 된 객체에 그것을 가지고있을 것으로 예상됩니다.

이것이 효과가 없다면 상황에 대한 추가 세부 정보를 제공하십시오.

아마도 당신은 원할 것입니다 NSObject'에스 -forwardInvocation 방법. 이를 통해 메시지를 캡처하고 다시 타겟팅 한 다음 재판매 할 수 있습니다.

당신은 당신의 자신의 방법 중 하나와 함께 메소드 호출을 스 와일을 할 수 있습니다. "인터 셉션"에서하고 싶은 모든 일을하고 원래 구현으로 전화를 걸었습니다. Swizzling은 class_replacemethod ()로 수행됩니다.

메소드 호출, 아니요. 메시지 보내기, 그렇습니다.하지만 방법에 대한 좋은 답변을 원한다면 훨씬 더 설명 적이어야합니다.

방법이 호출 될 때 무언가를하려면 이벤트 기반 접근법을 시도 할 수 있습니다. 따라서이 방법이 호출되면 모든 청취자가 선택한 이벤트를 방송합니다. 나는 객관적인 C에 좋지 않지만, 나는 단지 비슷한 사용을 알아 냈습니다. nsnotificationCenter 코코아에서.

그러나 "intercept"라면 "정지"를 의미한다면, 그 방법을 전혀 호출 해야하는 더 많은 논리가 필요할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top