web-dev-qa-db-fra.com

Transmettre des arguments par valeur ou par référence dans l'objectif c

Je suis un peu nouveau avec l'objectif C et j'essaie de transmettre un argument par référence mais vous comporte comme une valeur. Savez-vous pourquoi cela ne fonctionne pas?

C'est la fonction:

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

}

Et c'est l'appel:

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

Merci pour ton aide

23
Rafael

Objective-c seulement prend en charge les paramètres de passage par valeur. Le problème ici a probablement été déjà corrigé (puisque cette question est âgée de plus d'un an), mais je dois clarifier certaines choses en ce qui concerne les arguments et l'objectif-c.

Objectif-c est un superset strict ​​de C, ce qui signifie que tout c fait, obj-c le fait aussi.

En regardant rapidement Wikipedia, vous pouvez voir que Function parameters are always passed by value

L'objectif-c n'est pas différent. Ce qui se passe ici, c'est que chaque fois que nous passons un objet à une fonction (dans ce cas, un uilabel *), nous passons la valeur contenue à l'adresse du pointeur.

Quoi que vous fassiez, ce sera toujours la valeur de ce que vous passez. Si vous souhaitez transmettre la valeur du Référence, vous devrez transmettre un objet ** (comme souvent vu lors du passage de Nserror).

C'est la même chose avec des scalaires, ils sont passés par la valeur, vous pouvez donc modifier la valeur de la variable que vous avez reçue dans votre méthode et qui ne modifiera pas la valeur de la variable d'origine que vous avez transmise à la fonction.

Voici un exemple pour faciliter la compréhension:

- (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.
}

Si vous vouliez pouvoir modifier i, vous devriez adopter la valeur de la Référence en procédant comme suit:

- (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

Objective-C, comme Java, n'a qu'une valeur de passage. Comme Java, des objets sont toujours accessibles via des pointeurs. Les "objets" ne sont jamais des valeurs directement, d'où vous n'abandonnez jamais ni n'abandonnez un objet. Vous passez un pointeur d'objet par valeur. Mais cela ne semble pas être le problème - vous essayez de modifier l'objet pointé par le pointeur, ce qui est parfaitement autorisé et n'a rien à voir avec la valeur transvenant par rapport à la référence. Je ne vois aucun problème avec votre code.

11
newacct

Dans l'objectif-C, il n'ya aucun moyen de transmettre des objets par valeur (sauf si vous le copiez explicitement, mais c'est une autre histoire). Poke autour de votre code - êtes-vous sûr que ChreveDColortextext: est appelé? Qu'en est-il de [StartDate Comparer: Enddate], n'est-ce pas jamais égal à NsordedDescendant? LabeltoChange Nil est-il?

0
Jared Pochtar

Avez-vous modifié le code entre cette ligne

UILabel *startHourLabel;

et cette ligne?

[self checkRedColorText:startHourLabel];

Sinon, le problème est que vous réaffirmez votre variable startHourLabel, vous perdez donc une sorte d'initialisation qui y était auparavant. Vous devriez recevoir une erreur de compilateur ici.

0
kubi

Voici les possibilités pour la raison pour laquelle cela ne fonctionne pas:

  1. l'étiquette que vous transmettez à CheckredColortext n'est pas celle que vous pensez.
  2. le résultat de comparaison sort toujours de la même manière.
  3. ... En fait, il n'y a pas 3.

Vous prétendez que vous avez initialisé Starthourlabel ailleurs, mais s'il s'agit d'une étiquette d'un fichier NIB, vous ne devez pas l'initialiser du tout. Il devrait être déclaré comme iboutlet et connecté à l'étiquette dans la nib avec Builder d'interface.

Si ce n'est pas une étiquette dans la nib, vous le créez délibérément par programme, vous devez vérifier l'adresse de l'étiquette que vous initialisez et vérifiez l'adresse de l'étiquette transmise à CheckredColortext. Soit Nslog son adresse à l'initialisation et à ChreeDColortext ou à l'inspecter avec le débogueur.

0
JeremyP