web-dev-qa-db-ja.com

値または目的Cの参照によって引数を渡す

私はObjective Cの初心者であり、参照によって引数を渡そうとしていますが、値のように振る舞っています。これが機能しない理由を知っていますか?

これは関数です:

- (void) checkRedColorText:(UILabel *)labelToChange {
    NSComparisonResult startLaterThanEnd = [startDate compare:endDate];
    if (startLaterThanEnd == NSOrderedDescending){
        labelToChange.textColor = [UIColor redColor];
    }
    else{
        labelToChange.textColor = [UIColor blackColor];
    }

}

そして、これは呼び出しです:

UILabel *startHourLabel; // This is properly initialized in other part of the code
[self checkRedColorText:startHourLabel];

ご協力いただきありがとうございます

23
Rafael

Objective-Conlyは、値によるパラメーターの受け渡しをサポートします。ここでの問題はおそらくすでに修正されています(この質問は1年以上前のものであるため)が、引数とObjective-Cについていくつか明確にする必要があります。

Objective-C はCのstrict supersetです。つまり、Cが行うすべてのこと、Obj-Cも行うことを意味します。

ウィキペディアをざっと見てみると、 see that Function parameters are always passed by value

Objective-Cも同じです。ここで起こっていることは、オブジェクトを関数(この場合はUILabel *)に渡すときは常に、ポインターのアドレスに値containedを渡すことです。

あなたが何をするにせよ、それは常にあなたが渡すものの価値になります。 referenceの値を渡したい場合は、**オブジェクトを渡す必要があります(NSErrorを渡すときによく見られるように)。

これはスカラーの場合と同じです。スカラーは値で渡されるため、メソッドで受け取った変数の値を変更でき、関数に渡した元の変数の値は変更されません。

理解を容易にするための例を次に示します。

- (void)parentFunction {
    int i = 0;
    [self modifyValueOfPassedArgument:i];
    //i == 0 still!
}

- (void)modifyValueOfPassedArgument:(NSInteger)j {
    //j == 0! but j is a copied variable. It is _NOT_ i
    j = 23;
    //j now == 23, but this hasn't changed the value of i.
}

Iを変更できるようにするには、次のようにしてreferenceの値を渡す必要があります。

- (void)parentFunction {
    int i = 0; //Stack allocated. Kept it that way for sake of simplicity
    [self modifyValueOfPassedReference:&i];
    //i == 23!
}

- (void)modifyValueOfPassedReference:(NSInteger *)j {
    //j == 0, and this points to i! We can modify i from here.
    *j = 23;
    //j now == 23, and i also == 23!
}
72

Javaと同様に、Objective-Cには値渡しのみがあります。 Javaと同様に、オブジェクトは常にポインターを通じてアクセスされます。 「オブジェクト」は決して直接の値ではないため、オブジェクトを割り当てたり、渡したりすることはありません。オブジェクトポインターを値渡ししています。しかし、それは問題ではないようです-ポインターによってポイントされたオブジェクトを変更しようとしていますが、これは完全に許可されており、値渡しと参照渡しとは関係ありません。コードに問題はありません。

11
newacct

Objective-Cでは、オブジェクトを値で渡す方法はありません(明示的にコピーしない限り、これは別の話です)。コードの周りを突く-checkRedColorText:が呼び出されますか? [startDate compare:endDate]はどうですか?NSOrderedDescendingと等しくないのですか? labelToChangeはnilですか?

0
Jared Pochtar

この行の間のコードを編集しましたか

UILabel *startHourLabel;

そしてこの線?

[self checkRedColorText:startHourLabel];

そうでない場合、問題はstartHourLabel変数を再宣言しているため、以前にあった初期化が失われていることです。ここでコンパイラエラーが発生するはずです。

0
kubi

これが機能しない理由は次のとおりです。

  1. checkRedColorTextに渡すラベルは、あなたが思っているものではありません。
  2. 比較結果は常に同じように出てきます。
  3. ...実際には3はありません。

StartHourLabelを他の場所で初期化したと主張していますが、それがnibファイルのラベルである場合は、まったく初期化しないでください。これはIBOutletとして宣言し、インターフェースビルダーでnibのラベルに接続する必要があります。

ペン先のラベルではない場合、つまりプログラムで意図的に作成している場合は、初期化するラベルのアドレスを確認し、checkRedColorTextに渡されたラベルのアドレスを確認する必要があります。初期化時とcheckRedColorTextでアドレスをNSLogするか、デバッガーで検査します。

0
JeremyP