Fehler beim Kompilieren mit ARC beim Programmieren der dynamischen Methode zur Laufzeit

Ich versuche, eine Laufzeitprogrammierung auf Objective-C durchzuführen. Um dies zu tun, überschreibe ich dieresolveClassMethod Methode.

Leider habe ich einen Kompilierungsfehler mit clang, wenn ARC aktiv ist:

Fehler: Keine bekannte Klassenmethode für den Selektor 'dynamic'

Alles funktioniert gut, wenn ich gcc oder clang ohne ARC benutze (-fno-objc-arc Option übergeben), außer einer Warnung anstelle des Fehlers.

Mir ist bekannt, dass ARC den Namen der aufgerufenen Methode kennen muss, um herauszufinden, wie der Speicher mit dem zurückgegebenen Wert verwaltet wird (gemäß der Methodennamenskonvention). Aber wie geht das ohne ein hässliches ThemaperformSelector Aufruf anstelle eines direkten Methodenaufrufs?

Hier ist mein Code:

Test.m

#import "Test.h"
#import <objc/runtime.h>

NSString* dynamicImp(id slef, SEL _cmd)
{
    NSLog(@"Dynamic method called");
    return @"dynamicImp";
}

@implementation Test

- (NSString*)name
{
    return @"John";
}

+ (BOOL)resolveClassMethod:(SEL)name
{
    if (name == @selector(dynamic))
    {
        Class metaClass = objc_getMetaClass([NSStringFromClass([self class]) UTF8String]);
        class_addMethod(metaClass, name, (IMP) dynamicImp, "@@:");
        return YES;
    }
    return NO;
}

+ (IMP)methodForSelector:(SEL)aSelector
{
    if (aSelector == @selector(dynamic))
    {
        return (IMP) dynamicImp;
    }
    else
    {
        return [super methodForSelector:aSelector];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(dynamic))
    {
        return YES;
    }
    else
    {
        return [NSObject respondsToSelector:aSelector];
    }
}

@end

Test.h

#import <Cocoa/Cocoa.h>

@interface Test : NSObject <NSObject> {
    NSString *_name;
}

- (NSString*)name;

@end

main.m

#import <Cocoa/Cocoa.h>
#import <stdio.h>
#import "Test.h"

int main(int argc, char* argv[])
{
    @autoreleasepool {
        Test *test = [[Test alloc] init];
        NSLog(@"Hello, %@", [test name]);
        NSLog(@"How are you , %@", [Test dynamic]);
    }
    return 0;
}

Gcc oder clang ohne ARC

Kompilierungsergebnis

main.m: 13: 36: Warnung: Klassenmethode '+ dynamic' nicht gefunden (Rückgabetyp ist standardmäßig 'id')

    NSLog(@"How are you , %@", [Test dynamic]);

Ausgabe

2012-10-22 10: 33: 15.563 test-clang [957: 707] Hallo, John 2012-10-22

2012-10-22 10: 33: 15.565 test-clang [957: 707] Dynamische Methode mit dem Namen 2012-10-22

2012-10-22 10: 33: 15.565 test-clang [957: 707] Wie geht es dir, dynamicImp

Clang mit ARC

Kompilierungsergebnis

main.m: 13: 36: Fehler: Keine bekannte Klassenmethode für den Selektor 'dynamic'

    NSLog(@"How are you , %@", [Test dynamic]);

PS: Ich habe mich im Moment nicht um die Speicherverwaltung gekümmert, da mein Ziel darin besteht, diesen Code mit aktiviertem ARC zu kompilieren.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage