¿Cómo llamar a un método Objective-C desde un Método C?


Tengo un objeto Obj-C con un montón de métodos dentro de él. A veces un método necesita llamar a otro método dentro del mismo objeto. Parece que no puedo averiguar cómo obtener un método C para llamar a un método Obj-C...

WORKS: Método Obj-C llamando a un método Obj-C:

[self objCMethod];

WORKS: Método Obj-C que llama a un método C:

cMethod();

NO FUNCIONA: Método C llamando a un método Obj-C:

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

El último ejemplo hace que el compilador escupe esto error:

Error: 'self' no declarado (primer uso en esta función)

Dos preguntas. ¿Por qué la función C no puede ver la variable " self "a pesar de que está dentro del objeto" self", y cómo lo llamo sin causar el error? Muchas gracias por cualquier ayuda! :)

Author: Dave Gallagher, 2009-08-15

5 answers

Para que eso funcione, debe definir el método C de la siguiente manera:

void cMethod(id param);

Y cuando lo llames, llámalo así: {[7]]}

cMethod(self);

Entonces, usted sería capaz de escribir:

[param objcMethod];

En su cMethod.

Esto se debe a que la variable self es un parámetro especial que se pasa automáticamente a los métodos de Objective-C. Dado que los métodos C no disfrutan de este privilegio, si desea usar self debe enviarlo usted mismo.

Ver más en la sección de Implementación del método de la guía de programación .

 47
Author: Aviad Ben Dov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-15 12:08:06

Sé que su pregunta ya ha sido respondida por Aviad, pero solo para agregar a la información ya que esto no está relacionado:

En mi caso, necesitaba llamar a un método Objective-C desde una función C que no llamaba yo mismo (una función de Evento de Carbono activada al registrar un evento de tecla de acceso rápido global), por lo que pasar self como parámetro era imposible. En este caso particular puedes hacer esto:

Defina una variable de clase en su implementación:

id thisClass;

Luego, en su método init, establézcalo en yo:

thisClass = self;

Luego puede llamar a métodos Objective-C desde cualquier función C de la clase sin necesidad de pasar self como parámetro a la función:

void cMethod([some parameters]) {
    [thisClass thisIsAnObjCMethod];
}
 25
Author: Form,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-06 19:53:52

La función C no está "dentro del objeto self". De hecho, nada lo es.

Los métodos Objective-C obtienen efectivamente self como un argumento implícito, con magia hecha bajo el capó. Para las funciones C simples, no están asociadas con ninguna clase u objeto, y no hay magia de llamada, por lo que no hay self. Si lo necesita, debe pasarlo a su función C explícitamente como un argumento.

 10
Author: Pavel Minaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-27 21:14:58

Para ser totalmente veraz, no hay tal cosa como un método C. C tiene funciones. Para ilustrar la diferencia, mira los siguientes ejemplos:

Este es un programa de trabajo en C que define un tipo y dos funciones que lo acompañan:

#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;
}

Aquí está una implementación del Objetivo-C de ese programa:

#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;
}

La salida del programa C puro fue:

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

El resultado del programa Objetivo-C fue:

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

La única diferencia es toda la basura que NSLog pone antes del texto. La funcionalidad es exactamente la misma. Por lo tanto, en C, se puede utilizar algo así como métodos, pero son realmente sólo funciones que incluyen un puntero a una estructura.

No creo que esto respondiera a su pregunta original, pero aclaró algunos problemas terminológicos que parece haber tenido.

 4
Author: Jonathan Sterling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-26 00:42:49

Otra opción a las respuestas dadas hasta ahora es utilizar el objc_msgSend() función proporcionada por el tiempo de ejecución de Objective-C.

 2
Author: Dave DeLong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-06 14:50:38