Frage

Ich mag eine Methode in einer Objective-C-Klasse außer Kraft zu setzen, die ich habe nicht die Quelle.

Ich habe in es sieht, und es scheint, dass Kategorien erlauben sollen mir, dies zu tun, aber ich mag das Ergebnis der alten Methode in meiner neuen Methode verwenden, super mit führen die alten Methoden zu erhalten.

Jedes Mal, wenn ich dies aber versuche, wird meine Methode genannt, aber „super“ ist gleich Null ... Jede Idee, warum? Ich mache iPhone Entwicklung mit dem XCode 2.2 SDK. Ich bin auf jeden Fall mit einer Instanz einer Klasse zu arbeiten, und die Methode der Klasse ist eine Instanz-Methode.

@implementation SampleClass (filePathResolver)
-(NSString*) fullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [super fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

Hinweis und Klarstellung: Von dem, was ich in der Apple-Docs sehen können, erscheint es mir, dass dies erlaubt sein sollte,

?
  

Kategorien docs bei developer.apple.com:   Wenn eine Kategorie überschreibt eine geerbte Methode, wobei das Verfahren in der   Kategorie kann, wie üblich, rufen Sie die   geerbte Implementierung über eine Nachricht   super. Wenn jedoch eine Kategorie   überschreibt, ein Verfahren, das bereits   in der Kategorie der Klasse existiert, gibt   ist kein Weg, um das Original zu berufen   Umsetzung.

War es hilfreich?

Lösung

Kategorien erweitern die ursprüngliche Klasse, aber sie tun es nicht Unterklasse, also ein Aufruf an super nicht die Methode nicht finden.

Was Sie wollen, heißt Methode Swizzling . Aber beachten Sie, dass Ihr Code etwas brechen könnte. Es gibt einen Artikel über Theocacao geschrieben von Scot Stevenson über Methode Swizzling im alten Objective-C-Laufzeit, Cocoa with Love von Matt Gallagher hat einen Artikel über Methode Swizzling im neuen Ziel C 2.0 Runtime und ein einfacher Ersatz für sie.

Alternativ können Sie die Klasse Unterklasse und dann entweder die Unterklasse verwenden oder ein href verwenden <= "http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/DeprecationAppendix /AppendixADeprecatedAPI.html#//apple_ref/occ/clm/NSObject/poseAsClass:“rel = "nofollow noreferrer"> + (void)poseAsClass:(Class)aClass die übergeordnete Klasse zu ersetzen. Apple schreibt:

  

Ein Verfahren durch eine Aufstellung Klasse definiert   kann durch eine Nachricht an super,   Verfahren der Superklasse binden sie   Überschreibungen.

Seien Sie sich bewusst, dass Apple poseAsClass: in Mac OS X 10.5 ist veraltet.

Andere Tipps

Wenn Sie gegen diese Klasse werden Codierung wird, einfach benennen Sie den Wähler auf etwas Ihrem Code verwenden können, und rufen Sie die Original-Selektor auf self:

@implementation SampleClass (filePathResolver)
-(NSString*) myFullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [self fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

Wenn Sie die Standardimplementierung dieser Wähler für diese Klasse außer Kraft setzen möchten, müssen Sie die

Nicht gerade in der Kategorie, aber es gibt eine Abhilfe, indem die Methode zur Laufzeit dynamisch hinzufügen. Samuel Défago in seinem Artikel beschreibt eine saubere Art und Weise Block IMP Implementierung Aufruf super, seine Original-Artikel erstellen hier

Der entsprechende Code ist:

#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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top