Версия SudzC ARC - вызов objc_msgSend вызывает EXC_BAD_ACCESS с использованием 64-битной архитектуры

Изменить - я отслеживал приведенную ниже проблему для проблемы 64-битной и 32-битной архитектуры ... см. Мой опубликованный ответ, как я решил

Я использовалSudzC генерировать SOAP-код для веб-службы. Они предоставляют вам пример приложения, которое я смог успешно использовать как на устройстве, так и на симуляторе.

Затем я начал создавать свое приложение. Я импортировал сгенерированные файлы SudzC в новый проект XCode, используя пустой шаблон приложения (с включенными CoreData и ARC).

Я получил первый SOAP-запрос - все работает в симуляторе, - а затем я отправился на первый тест на устройство (iPhone 5S под управлением iOS 7.02). Устройство выбрасываетEXC_BAD_ACCESS ошибка каждый раз, когда выполняется запрос SOAP.

Я отследил это доSoapRequest.m файл, а именноconnectionDidFinishLoading метод. Этот метод используетobjc_msgSend вызов для отправки данных ответа SOAP обратно в метод-обработчик в другом классе (в данном случае, мой контроллер представления). Вот код:

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

Итак, линияobjc_msgSend(self.handler, self.action, output); кажется, где моя проблема.self.handler указывает на мой View Controller, иself.action указывает на этот метод:

TasksViewController.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);
}

Повторный вход в этот метод - то, где я терплю крах. Похоже,(id)value не делает это из класса SoapRequest. Я предполагаю, что ARC освобождает его. Я проверил звонок, заменив(id)value сint:

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

а также

- (void)findItemHandler:(int)value

Это работает. Предполагая, что проблема заключается в преждевременном уничтожении переменной-значения, я попытался сделать несколько вещей, чтобы сохранить ее. Я добавил свойство в SoapRequest.m:

@property (nonatomic, strong) id value;

Потом прошло что:

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

Та же проблема. Я также попробовал то же самое с экземпляром SoapRequest ... Теперь я смог обойти эту проблему, создав свойство в контроллере представления и установив для этого свойства значение, но мне действительно любопытно, как это исправить, используя оригинальный код. Я вернулся к примеру приложения, которое я скачал с SudzC, чтобы посмотреть, как это работает, и оказалось, что ARC не включен для этого проекта (!).

Может кто-нибудь сказать мне:

1) Если я прав в своем предположении, чтоoutput освобождается, в результате чего метод обработчика ссылается на неверный адрес памяти?

2) Почему это работает на симуляторе? Я предполагаю, что это потому, что у сима гораздо больше доступной памяти, поэтому он не так агрессивен с освобождением ARC ...

3) Как я мог это исправить, предполагая, что я хочу сохранитьobjc_msgSend вызов? Я хочу узнать, как / почему это происходит

4) Если SudzC правильно в их использовании здесьobjc_msgSendНасколько я понимаю, это плохая практика называть это напрямую, кроме как в редких случаях?

Спасибо!

Ответы на вопрос(1)

Ваш ответ на вопрос