39

たくさんのメソッドを含むObj-Cオブジェクトがあります。メソッドが同じオブジェクト内で別のメソッドを呼び出す必要がある場合があります。CメソッドでObj-Cメソッドを呼び出す方法がわからないようです...

動作: Obj-Cメソッドを呼び出すObj-Cメソッド:

[self objCMethod];

WORKS: Cメソッドを呼び出すObj-Cメソッド:

cMethod();

動作しません: Obj-Cメソッドを呼び出すCメソッド:

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

最後の例では、コンパイラがこのエラーを吐き出します。

エラー:'self'が宣言されていません(この関数での最初の使用)

2つの質問。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 イベント関数) から Objective-C メソッドを呼び出す必要があったため、self をパラメーターとして渡すことは不可能でした。この特定のケースでは、これを行うことができます:

実装でクラス変数を定義します。

id thisClass;

次に、init メソッドでそれを self に設定します。

thisClass = self;

selfその後、関数にパラメーターとして渡す必要なく、クラス内の任意の C 関数から Objective-C メソッドを呼び出すことができます。

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には関数があります。違いを説明するために、次の例を見てください。

これは、型とそれに付随する 2 つの関数を定義する実用的な 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

これまでの回答に対するもう 1 つのオプションはobjc_msgSend()、Objective-C ランタイムによって提供される関数を使用することです。

于 2009-10-06T14:50:38.823 に答える