2009-08-14 17 views
34

Mam obiekt Obj-C z wiązką metod wewnątrz niego. Czasami metoda musi wywołać inną metodę wewnątrz tego samego obiektu. I nie wydaje się, aby dowiedzieć się, jak uzyskać Metoda C do wywołania metody Obj-C ...Jak wywołać metodę Objective-C metodą C?

działa: metoda Obj-C Wywołanie metody Obj-C:

[self objCMethod]; 

działa: sposób obj-C wywoływania metoda C:

cMethod(); 

nie działa: C Sposób wywoływania metody obj-c:

[self objCMethod];  // <--- this does not work 

Ostatni przykład powoduje kompilator wypluwa ten błąd:

błędzie: 'ja' nierejestrowanej (najpierw użyć w tej funkcji)

dwa pytania. Dlaczego funkcja C nie może zobaczyć zmiennej "self", nawet jeśli znajduje się wewnątrz obiektu "self" i jak ją wywołać, nie powodując błędu? Bardzo dziękuję za pomoc! :)

Odpowiedz

47

Aby to do pracy, należy określić metodę C tak:

void cMethod(id param); 

a gdy go nie nazywać, nazwać tak:

cMethod(self); 

wtedy, byłbyś w stanie napisać:

[param objcMethod]; 

W swoim cMethod.

Dzieje się tak, ponieważ zmienna self jest specjalnym parametrem przekazywanym automatycznie do metod Objective-C. Ponieważ metody C nie korzystają z tego przywileju, jeśli chcesz korzystać z self, musisz wysłać go samemu.

Zobacz więcej w Method Implementation section of the programming guide.

+0

Idealnie, dziękuję !!! –

+0

Nie powinien "[samo objcMethod];" być "[param objcMethod];" –

+0

@Peter: Oczywiście! Naprawiony! :) –

10

Funkcja C nie jest "wewnątrz obiektu self". W rzeczywistości nic nie jest.

Metody Objective-C skutecznie przyjmują self jako niejawny argument, z magią zrobioną pod maską. W przypadku zwykłych funkcji C nie są one powiązane z żadną klasą ani obiektem i nie ma magii wywoływania, więc nie ma potrzeby stosowania self. Jeśli jej potrzebujesz, musisz przekazać ją do swojej funkcji C jawnie jako argument.

+0

Dzięki za wyjaśnienie. Teraz jest o wiele jaśniej. :) –

4

Aby być całkowicie prawdziwym, nie ma czegoś takiego jak metoda C. C ma funkcje.Aby zilustrować różnicę, spojrzeć na poniższych przykładach:

Jest to program pracy C, która określa rodzaj i dwie funkcje, które go wraz z nim:

#include <stdio.h> 

typedef struct foo_t { 
    int age; 
    char *name; 
} Foo; 

void multiply_age_by_factor(int factor, Foo *f) { 
    f->age = f->age * factor; 
} 

void print_foo_description(Foo f) { 
    printf("age: %i, name: %s\n", f.age, f.name); 
} 

int main() { 
    Foo jon; 
    jon.age = 17; 
    jon.name = "Jon Sterling"; 

    print_foo_description(jon); 
    multiply_age_by_factor(2, &jon); 
    print_foo_description(jon); 

    return 0; 
} 

Oto implementacja Objective-C, które Program:

#import <Foundation/Foundation.h> 

@interface Foo : NSObject { 
    NSUInteger age; 
    NSString *name; 
} 

@property (nonatomic, readwrite) NSUInteger age; 
@property (nonatomic, copy) NSString *name; 

- (void)multiplyAgeByFactor:(NSUInteger)factor; 
- (NSString *)description; 
- (void)logDescription; 

@end 


@implementation Foo 
@synthesize age; 
@synthesize name; 

- (void)multiplyAgeByFactor:(NSUInteger)factor { 
    [self setAge:([self age] * factor)]; 
} 

- (NSString *)description { 
    return [NSString stringWithFormat:@"age: %i, name: %@\n", [self age], [self name]]; 
} 

- (void)logDescription { 
    NSLog(@"%@",[self description]); 
} 

@end 


int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    Foo *jon = [[[Foo alloc] init] autorelease]; 
    [jon setAge:17]; 
    [jon setName:@"Jon Sterling"]; 

    [jon logDescription]; 
    [jon multiplyAgeByFactor:2]; 
    [jon logDescription]; 

    [pool drain]; 

    return 0; 
} 

Wydajność czystego programu C:

age: 17, name: Jon Sterling 
age: 34, name: Jon Sterling 

Wyjście z programu Objective-C:

2009-08-25 17:40:52.818 test[8963:613] age: 17, name: Jon Sterling 
2009-08-25 17:40:52.828 test[8963:613] age: 34, name: Jon Sterling 

Jedyną różnicą jest to, że wszystkie śmieci NSLog stawia przed tekstem. Funkcjonalność jest dokładnie taka sama. Tak więc, w C, możesz użyć czegoś w rodzaju podobnych metod, ale są one po prostu funkcjami, które zawierają wskaźnik do struktury.

Nie sądzę, żeby to odpowiadało na twoje pierwotne pytanie, ale wyjaśniło pewne problemy z terminologią, które wydają się mieć.

+1

Doceniam komentarz. Bardzo pomocne. Dzięki! :) –

+0

Nie ma problemu! Cieszę się, że pomogłem ... –

+0

To nie odpowiada na oryginalne pytanie ... –

24

Znam Twoje pytanie jest już odpowiedź od Aviad ale tylko dodać do informacji, ponieważ to nie ma związku:

W moim przypadku musiałem wywołać metodę Objective-C z C funkcji, że nie zadzwoń do mnie (funkcja zdarzenia węglowego wyzwalana przez rejestrację globalnego zdarzenia hotkey), więc przekazanie siebie jako parametru było niemożliwe. W tym konkretnym przypadku można to zrobić:

Zdefiniuj zmienną klasy w swojej realizacji:

id thisClass; 

Następnie w metodzie init ustawić go do siebie:

thisClass = self; 

Można połączyć Metody Objective-C z dowolnej funkcji C w klasie bez potrzeby przekazania self jako parametru funkcji:

void cMethod([some parameters]) { 
    [thisClass thisIsAnObjCMethod]; 
} 
+1

Dzięki! :) Właściwie to wpadłem na tę samą sytuację i właśnie to zrobiłem. W pliku @interface wstawiam "id aSelf;" przed @ interfejs, a następnie ustaw "aSelf = self;" w init (lub awakeFromNib) dla @implementation. –

+1

Jak zdefiniować identyfikator z funkcji C, ponieważ ma on dostęp tylko do standardowej biblioteki? Czy mogę zaimportować konkretną bibliotekę Apple, która pozwoli mi używać "id" w moim pliku C? – Micrified

+0

To nie działa; zwraca błąd "duplikatu symbolu" w środowisku wykonawczym. –

2

Inną opcją udzielonych do tej pory odpowiedzi jest użycie funkcji objc_msgSend() dostarczanej przez środowisko wykonawcze Objective-C.

+0

Generalnie nie jest to świetny pomysł. Konwencje wzywające są trochę tajemnicze. W środowisku wykonawczym Apple istnieją różne wersje objc_msgSend dla różnych typów zwracanych, na przykład. Bezpieczniej pozwolić kompilatorowi to zrozumieć. –

+3

Czy możesz podać przykład, zalety lub wady? Ponieważ to ty, Dave, założę się, że to jeden z lepszych sposobów na ... –

Powiązane problemy