EXC_BAD_ACCESS снова - PullRequest
       16

EXC_BAD_ACCESS снова

0 голосов
/ 16 декабря 2011

Я создаю (пытаюсь ...) приложение для iPhone. Моя первая пользовательская история - это вид входа в систему, который отправляет учетные данные пользователя в веб-службу (WCF). Процесс связи с веб-сервисом работает без проблем. Но я должен десериализовать сообщение, приходящее от него. Для этого я использовал NSXMLParser для создания Объекта сообщения, который содержит ответ службы. Это когда проблема начинается:

Это анализатор сообщений:

.h

@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

.m

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

это действие входа в систему:

- (IBAction)didLogin:(id)sender 
{
    NSData* receivedData;
    NSError* parserError;
    NSError* error;

    receivedData = [[ServiceClient PerformLogin:txtLogin.text withPassword:txtPassword.text error:error] retain];    
    MessageParser* messageParser = [[MessageParser alloc] init];

    Message* msg;    
    [messageParser parseMessageData:receivedData parseError:&parserError];

    msg = [messageParser.message retain];

    if(msg && !msg.error){        

        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Login Service Response" message:msg.messageBody delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    else if(msg.error){
        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg.error delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    else if(!msg){
        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Enable to contact the Athentication service." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

Объект сообщения:

@interface Message : NSObject{
    NSString* messageBody;
    NSNumber* messageCode;
    NSString* error;   
}

@property (retain, nonatomic) NSString* messageBody;
@property (retain, nonatomic) NSNumber* messageCode;
@property (retain, nonatomic) NSString* error;

@end

@implementation Message
@synthesize error, messageBody, messageCode;

@end

Так что случилось? Некоторое время, когда происходит вход в систему, он показывает мне предупреждение, а затем xcode выдает ошибку EXC_BAD_ACCESS в main.m в этом коде:

@autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}

И когда я нажимаю на кнопку «Войти», она выдает мне ту же ошибку напрямую.

Что не так с моим кодом? У меня есть проблемы с управлением памятью? где?

Спасибо.

Ответы [ 2 ]

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

Вы используете удобный метод без сохранения результата ....

currentProperty = [NSMutableString string];

либо делай ...

currentProperty = [[NSMutableString string] retain];

или когда вы объявляете свойство с атрибутом сохранения, используйте ...

self.currentProperty = [NSMutableString string];

Также обратите внимание, что в следующей строке происходит утечка памяти ....

self.message = [[Message alloc] init];

, поскольку свойство также имеет атрибут retain, который вам необходим для выпуска созданной вами версии ...

Message *aMessage = [[Message alloc] init];
self.message = aMessage;
[aMessage release];

... или ...

message = [[Message alloc] init];
1 голос
/ 16 декабря 2011

положить NSZombieEnabled : YES в разделе «Редактировать активный исполняемый файл» вашего проекта. Я надеюсь, что это может помочь найти след по этому вопросу.

...