Как я могу выпустить этот NSXMLParser без сбоя моего приложения? - PullRequest
2 голосов
/ 21 апреля 2010

Ниже приведен @interface для объекта MREntitiesConverter, который я использую для удаления всех тегов html из строки с использованием NSXMLParser.

@interface MREntitiesConverter : NSObject {
    NSMutableString* resultString;
    NSString* xmlStr;
    NSData *data;
    NSXMLParser* xmlParser;
}
@property (nonatomic, retain) NSMutableString* resultString;
- (NSString*)convertEntitiesInString:(NSString*)s;
@end

И это реализация:

@implementation MREntitiesConverter
@synthesize resultString;
- (id)init
{
    if([super init]) {
        self.resultString = [NSMutableString string];
    }
    return self;
}

- (NSString*)convertEntitiesInString:(NSString*)s {
    xmlStr = [NSString stringWithFormat:@"<data>%@</data>", s];
    data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    xmlParser = [[NSXMLParser alloc] initWithData:data];

    [xmlParser setDelegate:self];
    [xmlParser parse];

    return [resultString autorelease];
}

- (void)dealloc {
    [data release];
    //I want to release xmlParser here but it crashes the app
    [super dealloc];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
    [self.resultString appendString:s];
}
@end

Если я освобождаю xmlParser в методе dealloc, я ломаю свое приложение, но, не отпуская, я совершенно очевидно теряю память.

Я новичок в инструментах и ​​пытаюсь научиться оптимизировать это приложение. Любая помощь, которую вы можете предложить по этой конкретной проблеме, вероятно, поможет мне решить другие проблемы с памятью в моем приложении.

Ваш в расстроенном ожидании :) Oisin

Ответы [ 6 ]

3 голосов
/ 21 апреля 2010

И ваш класс, и NSXMLParser выпускают данные, что вызывает ваш текущий сбой. Единственный член должен быть resultString. Вы должны инициализировать resultString в convertEntitiesInString: не init, поэтому один и тот же экземпляр можно использовать более одного раза. Вы должны вернуть либо self.resultString, либо [[resultString retain] autorelease] из convert, потому что то, что вы в данный момент делаете, приведет к двойному освобождению позже, если вы выпустите resultString в dealloc, как вы должны. Вы должны использовать resultString непосредственно в parser: foundCharacters: вместо self.resultString, который является вызовом метода.

2 голосов
/ 21 апреля 2010

Вы уверены, что [выпуск xmlParser] приводит к сбою приложения в dealloc? Я вижу, у вас есть [data release] в dealloc, и я не вижу оператора, в котором вы использовали alloc для выделения памяти.

2 голосов
/ 21 апреля 2010

Я не вижу, чтобы xmlParser использовалось за пределами convertEntitiesInString:. Вы можете сделать xmlParser локальным для этого метода (не переменной экземпляра) и освободить его, когда закончите с этим методом, перед строкой return [resultString autorelease].

0 голосов
/ 21 апреля 2010

Основываясь на некоторых действительно полезных предложениях, это последняя версия моего кода, которая, похоже, не дает утечки памяти:

@interface MREntitiesConverter : NSObject {
    NSMutableString* resultString;
}
@property (nonatomic, retain) NSMutableString* resultString;
- (NSString*)convertEntitiesInString:(NSString*)s;
@end


@implementation MREntitiesConverter
@synthesize resultString;

- (NSString*)convertEntitiesInString:(NSString*)s {
    self.resultString = [NSMutableString string];

    NSString* xmlStr = [NSString stringWithFormat:@"<d>%@</d>", s];
    NSData *data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    NSXMLParser* xmlParse = [[NSXMLParser alloc] initWithData:data];

    [xmlParse setDelegate:self];
    [xmlParse parse];
    [xmlParse release];

    return [self.resultString autorelease];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
    [resultString appendString:s];
}
@end

Единственная странность в том, что если я прослежу retainCount из resultString непосредственно перед его возвратом, я получу счет 2, где я ожидал бы, что он будет 1. Есть идеи почему?

0 голосов
/ 21 апреля 2010

Я считаю, что это resultString, которая вызывает сбой. Это NSMutableString, и вы не выделили для этого памяти. Также освободите xmlParser в convertEntitiesInString перед возвратом [autoStlease] resultString;

0 голосов
/ 21 апреля 2010

Хотя два других комментария верны (вы забываете release синтаксический анализатор в методе, который вы alloc it, что является утечкой памяти), я уверен, что он вылетает именно потому, что вы установили класс MREntitiesConverter как delegate для парсера.

...