2010-04-07 13 views
6

Próbuję nauczyć się pisać wtyczki za pomocą SIMBL. Mam wtyczkę do załadowania aplikacji docelowej, a także znam metodę, którą chcę nadpisać. Jednak nie jestem w stanie poprawnie używać class_getInstanceMethod na podstawie fragmentów w Internecie. Czy zmieniło się coś w OSX 10.6 i/lub ObjC2?Jak dynamicznie zastąpić implementację metody w ObjC2?

Poniższy kod z culater.net daje „dereferencji wskaźnik do niepełnej typu” na drugim ostatnim stwierdzeniem:

BOOL DTRenameSelector(Class _class, SEL _oldSelector, SEL _newSelector) 
{ 
    Method method = nil; 

    // First, look for the methods 
    method = class_getInstanceMethod(_class, _oldSelector); 
    if (method == nil) 
     return NO; 

    method->method_name = _newSelector; 
    return YES; 
} 

istnieje kompletny przykład jak przesłonić metodę z wykorzystaniem SIMBL wtyczek? Dzięki!

Odpowiedz

5

Jeśli szukasz swizzle a method, możesz zamiast tego użyć opcji the method_exchangeImplementations function.

+0

To działało. Dzięki! – Abhi

+0

Peter - Czy można również wykonać "funkcję swizzling", tj. Zastępując implementację funkcji, która nie jest metodą klasy? – Abhi

+2

Nie. Metoda swizzowania działa, ponieważ implementacja selektora jest dynamicznie sprawdzana w momencie wysłania komunikatu - tj. W czasie wykonywania. Istnieje nazwa, która jest selektorem, i wartość, która jest implementacją, a swizzling zamienia jedną wartość na inną, podobnie jak zmieniające się wartości w słowniku. Funkcje nie są wyszukiwane dynamicznie; adres zostanie przywiązany, gdy plik wykonywalny zostanie załadowany i pozostanie na nim ustalony, a połączenie przychodzi bezpośrednio pod ten adres, więc nie ma nic do zmiany. –

7

Środowisko wykonawcze Obj-C zmieniło się w Objective-C 2, kod, który cytowałeś, używa starszego.

(Cóż, w aplikacjach 32-bitowych lepiej powiedzieć, że istnieją dwa interfejsy do tego samego środowiska wykonawczego, w zależności od sposobu kompilacji pliku binarnego, oba działają na końcu, ale łatwiej jest myśleć, że wszystko zmieniło się Objective-C 2. I powinieneś używać nowszych API, ponieważ jest łatwiejszy w obsłudze i działa zarówno w wersji 32-bitowej, jak i 64-bitowej.)

Nowe referencje to the Guide i the Reference. Podstawową zmianą jest to, że wewnętrzny struct nie jest już publiczny, jest nieprzejrzysty. Więc nie możesz uzyskać bezpośredniego dostępu do swojego członka. Zamiast tego musisz użyć interfejsu API.

Zazwyczaj rzeczy są łatwiejsze w nowym środowisku wykonawczym. Aby zastąpić IMP, jeden tylko wykorzystuje

IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types); 

aby uzyskać kodowanie typu, należy

const char * method_getTypeEncoding(Method method); 

na oryginalnej metodzie ty wymieniasz. W praktyce, to byłoby

method_getTypeEncoding(class_getInstanceMethod([SomeClass class], @selector(someSelector:you:want:to:replace:))); 

Aby dowiedzieć się więcej na temat wykonywania, ja serdecznie polecam wspaniałą serię blogach Friday Q&A Mike Ash.

Życzymy dobrej zabawy i powodzenia!

Powiązane problemy