2008-11-23 5 views
5

J'ai une méthode d'initialisation qui prend un (id) Argument:Pourquoi ai-je besoin de me transformer en ID?


    -(id) initWithObject:(id) obj; 

Je suis en train de l'appeler comme ceci:


    [[MyClass alloc] initWithObject:self]; 

Mais XCode se plaint de l'argument étant une « distincte Objective-C type "(qui indique généralement une incompatibilité de type ou un niveau d'erreur d'indirection).

Si je mets explicitement le moi à (id) l'avertissement disparaît. Dans les deux cas, le code s'exécute comme prévu. Il est intéressant de noter que sur la ligne suivante, je suis en train de passer à une autre méthode qui prend aussi un identifiant, et cela fonctionne bien.

Je me demande s'il me manque quelque chose de subtil - ou est-ce une particularité du compilateur?

Je ne suis pas entièrement à l'aise de le lancer jusqu'à ce que je sois sûr des raisons pour lesquelles c'est nécessaire.

[Modifier]

On me demande de fournir plus de code. Je ne suis pas sûr qu'il y ait beaucoup d'autres choses pertinentes. Voici mon code réel qui fait l'appel. Notez qu'il est lui-même dans une méthode init. Il est l'appel à initWithSource qui est de donner l'avertissement:


-(id) initWithFrame:(CGRect) frame 
{ 
    self = [super initWithFrame: frame]; 
    if(self) 
    { 
     delegate = nil; 
     touchDelegate = [[TBCTouchDelegate alloc] initWithSource:self]; 
     [touchDelegate.viewWasTappedEvent addTarget: self action:@selector(viewWasTapped:)]; 
    } 
    return self; 
} 

Et voici la méthode d'initialisation appelé:


-(id) initWithSource:(id) sourceObject 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     // Uninteresting initialisation snipped 
    } 
    return self; 
} 
+0

Vous voudrez peut-être afficher plus de code ici; rien ne saute, mais avec seulement deux lignes de travail, c'est difficile à dire. –

+0

D'accord avec Ben, mais une chose à considérer, est la méthode initWithObject déclaré? –

+0

Merci de votre attention, les gars. J'ai ajouté un peu plus de code ci-dessus, pour ce que ça vaut. @Jason: Oui, initWithSource (mon nom de méthode actuel) est déclaré dans l'en-tête, et il correspond certainement. – philsquared

Répondre

7

Typiquement, cela signifie qu'il ya plusieurs noms de méthode initWithSource: sur différentes classes avec types d'arguments contradictoires. Rappelez-vous, si une variable est tapée comme id, le compilateur ne sait pas de quelle classe il s'agit. Ainsi, si vous appelez initWithSource: sur un objet de type id et que plusieurs classes ont une méthode initWithSource:, le compilateur choisit essentiellement l'un des deux. Si elle choisit la «mauvaise», eh bien, vous obtenez une erreur «type Objective-C».

Alors, pourquoi cela vous arrive-t-il? Je ne suis pas sûr à 100%, mais rappelez-vous que +[TBCTouchDelegate alloc] renvoie un id. Ainsi enchaînant les appels alloc/init est équivalent à ceci:

id o = [TBCTouchDelegate alloc]; 
touchDelegate = [o initWithSource:self]; 

Par conséquent, vous appelez initWithSource: sur une id variables -typed. S'il existe une méthode initWithSource: en conflit, vous pouvez obtenir cette erreur de compilation.

Existe-t-il une méthode contradictoire? J'ai vérifié le système, et le seul conflit a été en NSAppleScript:

- (id)initWithSource:(NSString *)source; 

maintenant NSAppleScriptest partie de la Fondation, mais j'ai remarqué ce code est iPhone. Alors peut-être que vous obtenez cette erreur lors de la compilation pour le simulateur, et non l'appareil?

Dans tous les cas, si cela est votre problème, vous pourriez la contourner par alloc/init division sur deux lignes différentes:

touchDelegate = [TBCTouchDelegate alloc]; 
touchDelegate = [touchDelegate initWithSource:self]; 

Maintenant, vous appelez initWithSource: sur une variable entièrement typé (au lieu de id -typed), donc le compilateur n'a plus à deviner lequel choisir. Ou vous pourriez lancer le retour de +alloc:

touchDelegate = [(TBCTouchDelegate *)[TBCTouchDelegate alloc] initWithSource:self]; 

Une autre solution consiste à renommer initWithSource: pour éviter le conflit et peut-être le rendre plus descriptif. Vous ne dites pas ce que la classe est actuellement nommée ni à quoi sert la "source", donc je ne peux pas jeter toutes les possibilités.

+0

J'ai essayé de copier votre code dans mon propre projet et de double-cliquer sur initWithSource. Bien qu'il s'agisse d'un projet iPhone, il essaie en effet de faire référence à NSApplescript, selon la suggestion de Dave. –

+0

Merci Dave - c'était sur - et clairement expliqué aussi! Heureusement, le mot «source» était assez arbitraire, j'ai donc pu le changer assez facilement. Le TouchDelegate est un proxy pour les événements tactiles, et la "source" est l'objet pour lequel elle est mandatée. Je l'ai appelé TouchSource maintenant. – philsquared

+0

Merci pour la confirmation supplémentaire aussi, Ben, et pour avoir pris le temps d'aider. – philsquared

Questions connexes