Как вызвать метод Objective-C из метода C?
У меня есть объект Obj-C с кучей методов внутри него. Иногда метод должен вызывать другой метод внутри одного и того же объекта. Я не могу понять, как получить метод C для вызова метода Obj-C...
РАБОТЫ: Метод Obj-C, вызывающий метод Obj-C:
[self objCMethod];
РАБОТЫ: Метод Obj-C, вызывающий метод C:
cMethod();
НЕ РАБОТАЕТ: Метод C, вызывающий метод Obj-C:
[self objCMethod]; // <--- this does not work
В последнем примере компилятор выплевывает эту ошибку:
ошибка: "self" uneclared (сначала использовать в этой функции)
Два вопроса. Почему функция C не видит переменную "self" , даже если она находится внутри объекта "self" , и как я могу ее вызвать, не вызывая ошибки? Большое спасибо за любую помощь!:)
Ответы
Ответ 1
Чтобы это сработало, вы должны определить метод C следующим образом:
void cMethod(id param);
и когда вы его вызываете, назовите его так:
cMethod(self);
тогда вы сможете написать:
[param objcMethod];
В cMethod
.
Это связано с тем, что переменная self
является специальным параметром, который автоматически передается методам Objective-C. Поскольку методы C не пользуются этой привилегией, если вы хотите использовать self
, вам необходимо отправить его самостоятельно.
Подробнее в разделе "Реализация метода" руководства по программированию.
Ответ 2
Я знаю, что на ваш вопрос уже ответил Aviad, но просто чтобы добавить к информации, так как это не связано:
В моем случае мне нужно было вызвать метод Objective-C из функции C, которую я сам не вызывал (функция события Carbon, вызванная регистрацией глобального события hotkey), поэтому передача self в качестве параметра была невозможна. В этом конкретном случае вы можете сделать это:
Определите переменную класса в вашей реализации:
id thisClass;
Затем в вашем методе init установите его в self:
thisClass = self;
Затем вы можете вызвать методы Objective-C из любой функции C в классе без необходимости передавать self
в качестве параметра функции:
void cMethod([some parameters]) {
[thisClass thisIsAnObjCMethod];
}
Ответ 3
Функция C не является "внутри объекта self
". На самом деле ничего нет.
Objective-C методы эффективно получают self
как неявный аргумент, с магией, выполняемой под капотом. Для простых функций C они не связаны ни с каким классом или объектом, и там нет магии вызова, поэтому нет self
. Если вам это нужно, вам нужно передать его в свою C-функцию явно как аргумент.
Ответ 4
Чтобы быть полностью правдивым, нет такой вещи, как метод С. C имеет функции. Чтобы проиллюстрировать разницу, посмотрите на следующие примеры:
Это рабочая программа на C, которая определяет тип и две функции, которые идут вместе с ним:
#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;
}
Вот реализация этой программы Objective-C:
#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;
}
Вывод чистой программы C:
age: 17, name: Jon Sterling
age: 34, name: Jon Sterling
Вывод программы 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
Единственное отличие - это все нежелательные файлы, которые NSLog помещает перед текстом. Функциональность точно такая же. Итак, в C вы можете использовать что-то вроде подобных методов, но они действительно просто функции, которые включают указатель на структуру.
Я не думаю, что это ответило на ваш первоначальный вопрос, но он прояснил некоторые терминологические проблемы, которые, по-видимому, возникли.
Ответ 5
Еще один вариант ответов, предоставленных до сих пор, заключается в использовании функции objc_msgSend()
, обеспечиваемой средой Objective-C.