39

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

WORKS:调用 Obj-C 方法的 Obj-C 方法:

[self objCMethod];

WORKS:调用 C 方法的 Obj-C 方法:

cMethod();

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

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

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

错误:“自我”未声明(在此函数中首次使用)

两个问题。为什么 C 函数看不到“self”变量,即使它位于“self”对象内部,如何调用它而不导致错误?非常感谢您的帮助!:)

4

5 回答 5

50

为了让它工作,你应该像这样定义 C 方法:

void cMethod(id param);

当你调用它时,像这样调用它:

cMethod(self);

然后,您将能够编写:

[param objcMethod];

在你的cMethod.

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

在编程指南的方法实现部分中查看更多信息。

于 2009-08-14T20:44:27.610 回答
27

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

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

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

id thisClass;

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

thisClass = self;

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

void cMethod([some parameters]) {
    [thisClass thisIsAnObjCMethod];
}
于 2009-10-06T14:45:53.963 回答
10

C函数不是“self对象内部”。事实上,什么都不是。

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

于 2009-08-14T20:37:50.807 回答
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;
}

这是该程序的 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 中,您可以使用某种类似的方法,但它们实际上只是包含指向结构的指针的函数。

我不认为这回答了您最初的问题,但它确实解决了您似乎一直遇到的一些术语问题。

于 2009-08-26T00:42:49.787 回答
2

到目前为止给出的答案的另一个选择是使用objc_msgSend()Objective-C 运行时提供的函数。

于 2009-10-06T14:50:38.823 回答