객관적인 C 범주에서 Super를 사용하십니까?
-
05-07-2019 - |
문제
소스가없는 목표 C 클래스의 메소드를 무시하고 싶습니다.
나는 그것을 살펴 보았고, 카테고리를 사용하면이 작업을 수행 할 수 있어야하지만, 새 메소드에서 기존 메소드의 결과를 사용하여 Super를 사용하여 이전 메소드 결과를 얻을 수 있습니다.
그래도 시도 할 때마다 내 방법이 호출되지만 "Super"는 Nil입니다 ... 그 이유는 무엇입니까? Xcode 2.2 SDK로 iPhone 개발을하고 있습니다. 나는 수업 인스턴스로 확실히 작업하고 있으며, 수업의 방법은 인스턴스 방법입니다.
@implementation SampleClass (filePathResolver)
-(NSString*) fullPathFromRelativePath:(NSString*) relPath
{
NSString *result = [super fullPathFromRelativePath: relPath];
... do some stuff with the old result
return result;
}
참고 및 설명 : Apple 문서에서 볼 수있는 내용에서 이것이 허용되어야하는 것처럼 보입니까?
Developer.apple.com의 카테고리 문서 :카테고리가 상속 메소드를 무시하면 범주의 메소드는 평소와 같이 메시지를 통해 상속 된 구현을 수퍼에게 호출 할 수 있습니다. 그러나 카테고리가 카테고리 클래스에 이미 존재했던 메소드를 무시하면 원래 구현을 호출 할 방법이 없습니다.
해결책
카테고리는 원래 클래스를 확장하지만 서브 클래스는 아니므로 super
방법을 찾지 못합니다.
당신이 원하는 것을 불립니다 방법 스위 즈 링. 그러나 코드가 무언가를 깨뜨릴 수 있다는 점에 유의하십시오. 에 관한 기사가 있습니다 Scot Stevenson이 작성한 Theocacao 오래된 Objective-C 런타임에서 스위글링하는 방법에 대해 Matt Gallagher의 사랑과 코코아 새로운 Objective-C 2.0 런타임에서 Swizzling 방법과 간단한 교체에 관한 기사가 있습니다.
또는 클래스를 서브 클래스 한 다음 서브 클래스를 사용하거나 사용 할 수 있습니다. + (void)poseAsClass:(Class)aClass
슈퍼 클래스를 교체합니다. Apple은 다음과 같이 씁니다.
포즈 클래스에 의해 정의 된 메소드는 메시지를 통해
super
, 상체하는 슈퍼 클래스 메소드를 통합하십시오.
애플이 더 이상 사용되지 않았다 poseAsClass:
Mac OS X 10.5에서.
다른 팁
이 클래스에 대해 코딩 할 경우, 선택기의 이름을 코드로 사용할 수있는 것으로 바꾸고 Original Selector에게 전화하십시오. self
:
@implementation SampleClass (filePathResolver)
-(NSString*) myFullPathFromRelativePath:(NSString*) relPath
{
NSString *result = [self fullPathFromRelativePath: relPath];
... do some stuff with the old result
return result;
}
해당 클래스 의이 선택기의 기본 구현을 무시하려면 방법 스위 즈 링 접근하다.
카테고리는 정확히 아니지만 런타임에 동적으로 메소드를 추가하여 해결 방법이 있습니다. 그의 기사에서 Samuel Défago는 Super를 호출하는 블록 임프 구현을 만드는 깔끔한 방법을 설명합니다. 그의 원래 기사를 찾을 수 있습니다. 여기
관련 코드는 다음과 같습니다.
#import <objc/runtime.h>
#import <objc/message.h>
const char *types = method_getTypeEncoding(class_getInstanceMethod(clazz, selector));
class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) {
struct objc_super super = {
.receiver = self,
.super_class = class_getSuperclass(clazz)
};
id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
return objc_msgSendSuper_typed(&super, selector, argp);
}), types);