Отладка запуска приложения в инструкции по удалению пула - PullRequest
0 голосов
/ 13 декабря 2011

Я создаю приложение для iPhone, которое пытается выполнить вход через веб-службу Rest (WCF).Часть, которая вызывает сервис, работает правильно.Я получаю данные из вызываемой службы без каких-либо проблем.Но я должен разобрать сообщение, используя NSXMLParser.Когда я представляю его в своем приложении (это первый раз, когда я его использую), приложение правильно анализирует сообщение, но в конце выполнения приложения оно запускает gdb и приостанавливает работу приложения при запуске инструкции [pool dump].

@interface MessageParser : NSObject  <NSXMLParserDelegate> {
    NSMutableString* currentProperty;
    Message* message;

}

@property (nonatomic, retain) NSMutableString* currentProperty;
@property (nonatomic, retain) Message* message;

- (void)parseMessageData:(NSData *)data parseError:(NSError **)err;


@end


@implementation MessageParser

@synthesize message, currentProperty;

- (void)parseMessageData:(NSData *)data parseError:(NSError **)err {
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

    [parser setDelegate:self]; 
    [parser setShouldProcessNamespaces:NO]; 
    [parser setShouldReportNamespacePrefixes:NO]; 
    [parser setShouldResolveExternalEntities:NO]; 

    [parser parse];

    if (err && [parser parserError]) {
        *err = [parser parserError];
    }

    [parser release];
}

-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    if(qName){
        elementName = qName;
    }

    if([elementName isEqualToString:@"Message"]){
        self.message = [[Message alloc] init];
    }
    else if( [elementName isEqualToString:@"body"] || [elementName isEqualToString:@"code"] || [elementName isEqualToString:@"error"]){
        currentProperty = [NSMutableString string];
    }
}

-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    if(qName){
        elementName = qName;
    }
    if(message){
        if([elementName isEqualToString:@"body"]){
            self.message.messageBody = currentProperty;
        }
        else if([elementName isEqualToString:@"error"]){
            self.message.error = currentProperty;
        }
        else if([elementName isEqualToString:@"code"]){

            NSNumberFormatter * f = [[NSNumberFormatter alloc] init];            
            [f setNumberStyle:NSNumberFormatterDecimalStyle];

            self.message.messageCode = [f numberFromString:currentProperty];
            [f release];

        }
    }

    self.currentProperty = nil;

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)foundedCharacters
{
    if (self.currentProperty) {
        [currentProperty appendFormat:@"%@", foundedCharacters];
    }
}

Когда-то отладчик выдает мне следующее сообщение: Попытка создать переменную USE_BLOCK_IN_FRAME с блоком, которого нет в кадре.

У вас есть идеи?

Спасибовы.

1 Ответ

1 голос
/ 13 декабря 2011

Это можно сделать с помощью метода swizzling:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface NSAutoreleasePool(customDrain)

-(void) myDrain;

@end

@implementation NSAutoreleasePool(customDrain)

-(void) myDrain
{
    if ([self respondsToSelector:@selector(myDrain)])
    {
        NSLog(@"Draining...");

        // note that @selector(myDrain) was remapped 
        // to @selector(drain) during the process of 
        // the swizzling, so now, myDrain calls drain,
        // and drain calls myDrain.
        [self myDrain];
    }
    else 
    {
        NSLog(@"Remapping Failed!");
    }
}

@end

void SwizzleMethod(Class c, SEL orig, SEL new);
void SwizzleMethod(Class c, SEL orig, SEL new) {

    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);

    if (origMethod && newMethod)
        method_exchangeImplementations(origMethod, newMethod);

}

int main (int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    SwizzleMethod([NSAutoreleasePool class], @selector(drain), @selector(myDrain));

    [pool drain];
    return 0;
}

Вы просто помещаете свой собственный код в метод myDrain категории, а затем запускаете свой собственный код при опустошении пула.

Надеюсь, это помогло.

...