如何从C方法调用Objective-C方法?

Dav*_*her 38 objective-c self

我有一个Obj-C对象,里面有一堆方法.有时一个方法需要在同一个对象中调用另一个方法.我似乎无法弄清楚如何使用C方法调用Obj-C方法...

工作:调用Obj-C方法的Obj-C方法:

[self objCMethod];
Run Code Online (Sandbox Code Playgroud)

工作:调用C方法的Obj-C方法:

cMethod();
Run Code Online (Sandbox Code Playgroud)

不工作:调用Obj-C方法的C方法:

[self objCMethod];     // <--- this does not work
Run Code Online (Sandbox Code Playgroud)

最后一个示例导致编译器吐出此错误:

错误:'self'未声明(首次使用此功能)

两个问题.为什么C函数看不到"自"变量,即使它在"自"对象内部,如何在不引起错误的情况下调用它?非常感谢任何帮助!:)

Avi*_*Dov 50

为了使其工作,您应该像这样定义C方法:

void cMethod(id param);
Run Code Online (Sandbox Code Playgroud)

当你打电话给它时,请这样称呼它:

cMethod(self);
Run Code Online (Sandbox Code Playgroud)

那么,你可以写:

[param objcMethod];
Run Code Online (Sandbox Code Playgroud)

在你的cMethod.

这是因为self变量是一个自动传递给Objective-C方法的特殊参数.由于C方法不享有此权限,如果您想使用self,则必须自己发送.

请参阅编程指南的" 方法实现"部分中的更多内容.


For*_*orm 25

我知道你的问题已经由Aviad回答,但只是为了添加信息,因为这不是无关的:

在我的情况下,我需要从C函数调用Objective-C方法,我没有调用自己(通过注册全局热键事件触发的Carbon Event函数),因此将self作为参数传递是不可能的.在这种特殊情况下,您可以这样做:

在您的实现中定义一个类变量:

id thisClass;
Run Code Online (Sandbox Code Playgroud)

然后在init方法中,将其设置为self:

thisClass = self;
Run Code Online (Sandbox Code Playgroud)

然后,您可以从类中的任何C函数调用Objective-C方法,而无需将self参数作为参数传递给函数:

void cMethod([some parameters]) {
    [thisClass thisIsAnObjCMethod];
}
Run Code Online (Sandbox Code Playgroud)


Pav*_*aev 10

C函数不是" self对象内部".事实上,什么都没有.

Objective-C方法有效地得到self一个隐含的参数,魔术在幕后完成.对于普通的C函数,它们不与任何类或对象相关联,并且没有调用魔法,所以没有self.如果需要,您需要将其作为参数显式传递给C函数.


Jon*_*ing 5

要完全真实,没有C方法这样的东西.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;
}
Run Code Online (Sandbox Code Playgroud)

这是该程序的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;
}
Run Code Online (Sandbox Code Playgroud)

纯C程序的输出是:

age: 17, name: Jon Sterling
age: 34, name: Jon Sterling
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

唯一的区别是NSLog在文本之前放置的所有垃圾.功能完全相同.因此,在C中,您可以使用某种类似的方法,但它们实际上只是包含指向结构的指针的函数.

我不认为这回答了你原来的问题,但它确实澄清了你似乎遇到的一些术语问题.