objective-c casting initialization

objective c - ¿Por qué tengo que lanzarme a Identificación?



objective-c casting (1)

Normalmente esto significa que hay múltiples initWithSource: nombres de métodos en diferentes clases con tipos de argumentos en conflicto. Recuerde, si una variable se escribe como id el compilador no sabe qué clase es. Por lo tanto, si llama a initWithSource: en un objeto de tipo id y múltiples clases tienen un método initWithSource: el compilador solo elige uno de los dos. Si escoge el que está "equivocado", bueno, se obtiene un error de "tipo Objective-C distinto".

Entonces, ¿por qué te está pasando esto? No estoy 100% seguro, pero recuerde que +[TBCTouchDelegate alloc] devuelve una id . Por lo tanto, encadenar las llamadas alloc / init es equivalente a esto:

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

Por lo tanto, llama a initWithSource: en una variable de tipo id . Si hay un método initWithSource: conflicto, puede obtener este error de compilación.

¿Hay un método conflictivo? Revisé el sistema y el único conflictivo fue en NSAppleScript :

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

Ahora NSAppleScript es parte de Foundation, pero noté que este es el código de iPhone. Entonces, ¿tal vez solo obtiene este error al compilar para el simulador, y no el dispositivo?

En cualquier caso, si este es su problema, puede evitarlo dividiendo alloc / init en dos líneas diferentes:

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

Ahora, llama a initWithSource: en una variable completamente initWithSource: (en lugar de id tipo), por lo que el compilador ya no tiene que adivinar cuál elegir. O puede lanzar el retorno desde +alloc :

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

Otra solución es renombrar initWithSource: para evitar el conflicto y tal vez hacerlo más descriptivo. No dices para qué se llama actualmente la clase ni para qué sirve la "fuente", así que no puedo descartar ninguna posibilidad.

Tengo un método init que toma un argumento (id):

-(id) initWithObject:(id) obj;

Intento llamarlo así:

[[MyClass alloc] initWithObject:self];

Pero XCode se queja de que el argumento es un "tipo distinto de Objective-C" (que generalmente indica una falta de coincidencia de tipo o un nivel de error de indirección).

Si me lanzo explícitamente a (id) la advertencia desaparece. En cualquier caso, el código se ejecuta como se esperaba. Curiosamente, en la siguiente línea me estoy pasando a otro método que también toma una identificación, y eso funciona bien.

Me pregunto si me estoy perdiendo algo sutil, ¿o es una peculiaridad del compilador?

No estoy del todo cómodo simplemente lanzándolo hasta que esté seguro de las razones por las que es necesario.

[Editar]

Me han pedido que proporcione más código. No estoy seguro de que haya mucho más relevante. Aquí está mi código real que hace la llamada. Tenga en cuenta que es, en sí mismo, dentro de un método init. Es la llamada a initWithSource que está dando la advertencia:

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

Y aquí está el método init que se llama:

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