Versión de SudzC ARC: objc_msgEnviar llamada EXC_BAD_ACCESS utilizando una arquitectura de 64 bits

Editar: he rastreado el problema de abajo a un problema de arquitectura de 64 bits frente a 32 bits ... vea mi respuesta publicada para saber cómo resolví

he usadoSudzC para generar código SOAP para un servicio web. Le suministran una aplicación de muestra, que pude usar con éxito, tanto en el dispositivo como en el simulador.

Entonces empecé a construir mi aplicación. Importé los archivos generados de SudzC en un nuevo proyecto XCode usando la plantilla de aplicación en blanco (con CoreData y ARC habilitados).

Tengo la primera solicitud de SOAP en funcionamiento, todo funciona en el simulador, y luego hice mi primera prueba en un dispositivo (iPhone 5S con iOS 7.02). El dispositivo lanza unEXC_BAD_ACCESS error cada vez que se ejecuta la solicitud SOAP.

He rastreado esto hasta elSoapRequest.m archivo, específicamente elconnectionDidFinishLoading método. Este método utiliza unobjc_msgSend llamar para enviar los datos de respuesta SOAP a un método de controlador en otra clase (en este caso, mi controlador de vista). Aquí está el código:

SoapRequest.m:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSError* error;
    if(self.logging == YES) {
        NSString* response = [[NSString alloc] initWithData: self.receivedData encoding: NSUTF8StringEncoding];
        NSLog(@"%@", response);
    }

    CXMLDocument* doc = [[CXMLDocument alloc] initWithData: self.receivedData options: 0 error: &error];
    if(doc == nil) {
        [self handleError:error];
        return;
    }

    id output = nil;
    SoapFault* fault = [SoapFault faultWithXMLDocument: doc];

    if([fault hasFault]) {
        if(self.action == nil) {
            [self handleFault: fault];
        } else {
            if(self.handler != nil && [self.handler respondsToSelector: self.action]) {
                objc_msgSend(self.handler, self.action, fault);
            } else {
                NSLog(@"SOAP Fault: %@", fault);
            }
        }
    } else {
        CXMLNode* element = [[Soap getNode: [doc rootElement] withName: @"Body"] childAtIndex:0];
        if(deserializeTo == nil) {
            output = [Soap deserialize:element];
        } else {
            if([deserializeTo respondsToSelector: @selector(initWithNode:)]) {
                element = [element childAtIndex:0];
                output = [deserializeTo initWithNode: element];
            } else {
                NSString* value = [[[element childAtIndex:0] childAtIndex:0] stringValue];
                output = [Soap convert: value toType: deserializeTo];
            }
        }
        if(self.action == nil) { self.action = @selector(onload:); }
        if(self.handler != nil && [self.handler respondsToSelector: self.action]) {
            objc_msgSend(self.handler, self.action, output);
        } else if(self.defaultHandler != nil && [self.defaultHandler respondsToSelector:@selector(onload:)]) {
            [self.defaultHandler onload:output];
        }

    }
    conn = nil;
}

Así que la líneaobjc_msgSend(self.handler, self.action, output); Parece ser donde está mi problema.self.handler está apuntando a mi controlador de vista, yself.action apunta a este método:

TareasViewController.m:

- (void) findItemHandler: (id) value {

    // Handle errors
    if([value isKindOfClass:[NSError class]]) {
        NSLog(@"%@", value);
        return;
    }

    // Handle faults
    if([value isKindOfClass:[SoapFault class]]) {
        NSLog(@"%@", value);
        return;
    }

    // Do something with the id result
    NSLog(@"FindItem returned the value: %@", value);
}

El reingreso a este método es donde me caigo. Se parece a la(id)value no está pasando de la clase SoapRequest. Supongo que está siendo desasignado por ARC. He probado la llamada reemplazando(id)value con unint:

objc_msgSend(self.handler, self.action, 1);

y

- (void)findItemHandler:(int)value

Esto funciona. Suponiendo que el problema es que la variable de valor se destruye prematuramente, intenté algunas cosas para intentar mantenerla retenida. Agregué una propiedad a SoapRequest.m:

@property (nonatomic, strong) id value;

Luego pasó eso:

self.value = output;
objc_msgSend(self.handler, self.action, self.value);

El mismo problema. También intenté lo mismo con la instancia de SoapRequest ... Ahora, pude solucionar el problema creando una propiedad en el controlador de vista y configurando esa propiedad al valor, pero tengo mucha curiosidad sobre cómo solucionar este problema usando El código original. Regresé a la aplicación de ejemplo que descargué de SudzC para ver cómo funcionaba, y resulta que ARC no está habilitado para ese proyecto (!).

Alguien me puede decir:

1) Si tengo razón en mi suposición de queoutput ¿Se está desasignando, lo que hace que el método del controlador haga referencia a una dirección de memoria incorrecta?

2) ¿Por qué funciona esto en el simulador? Supongo que es porque el simulador tiene mucha más memoria disponible, por lo que no es tan agresivo con las desasignaciones ARC ...

3) ¿Cómo podría solucionar esto, asumiendo que quiero mantener elobjc_msgSend ¿llamada? Quiero saber cómo / por qué sucede esto.

4) Si SudzC es correcto en su uso aquí deobjc_msgSend, como entiendo, es una mala práctica llamar a esto directamente, excepto en circunstancias excepcionales.

¡Gracias!

Respuestas a la pregunta(1)

Su respuesta a la pregunta