Утечка на iPad, которую я не понимаю - PullRequest
1 голос
/ 04 января 2011

В моем приложении есть утечка, и я не знаю почему.Может быть, у меня все неправильно с управлением памятью.В моем коде у меня есть объект UIViewController, который имеет ivar TelephoneValidator * validator

TelephoneValidator это TelephoneValidator: NSObject

Так что в моей функции инициализации объекта UIViewController (initWithFieldData) я получил:

-(id) initWithFieldData: (NSMutableDictionary*) fieldData
{
...
     validatorOptions     = [fieldData objectForKey:@"fieldValidator"];
...
}

Теперь в моем viewDidLoad у меня есть:

- (void)viewDidLoad {
...
if (![validatorOptions respondsToSelector:@selector(isEqualToString:)]) {

          validator = [[TelephoneValidator alloc] initWithOptions: validatorOptions];
     }
     else {
          validator = nil;
     }
...
}

В основном, если мой validatorOptions не равен NSS, строка ivar validator становится экземпляром TelephoneValidator.

В моем dealloc:

- (void)dealloc {

     if(validator != nil)
     {
          [validator release];
          validator = nil;
     }
...
[super dealloc];
    }

Я пару раз проверял, работает ли dealloc, и это так.После вызова dealloc валидатор освобождается (вызывая любой метод для валидатора после того, как [релиз валидатора] получает мое исключение).

И все же в Instruments сообщается, что TelephoneValidator утечка.И после двойного щелчка в Инструментах выделяется строка кода:

validator = [[TelephoneValidator alloc] initWithOptions: validatorOptions];

Что я делаю не так?

ОБНОВЛЕНИЕ:

Вот моя информация заголовка оUIViewController:

@interface GenericViewController : UIViewController  <UITextFieldDelegate>{

UIImage *backgroundImage;
NSString *step; // na ktorym kroku jestesmy
id <GenericControllerDelegate> delegate; //delegata z ktorej bedziemy pobierali dane 
UITextField *textField;
NSString *fieldName; //nazwa pola (potrzebujemy zeby zapisac do modelu odpowiedni tekst
UILabel  *textLabel;
UILabel *stepsLabel;
UILabel *prefixTextLabel;

NSString *fieldPlaceholder;
NSString *textLabelText;
NSString *textLabelTextPl; //w jezyku polskim 
NSString *prefixTextLabelText; //w jezyku eng
NSString *prefixTextLabelTextPl; //w jezyku polskim prefix

NSString *fieldRequired;
NSString *keyboardType;
NSString *capitalizeType;

UIButton *button; //forward button
UIButton *button2;  //backward button

//to bedzie do przerobienia bo bedziemy mieli tablicje walidatorow a nie jeden walidator
NSString *validatorType;

//maksymalna dlugosc pola
int maxLengthOfTextField;

NSArray* validatorOptions;

TelephoneValidator *validator; 

//patientModel
PatientData *patientModel;

}

Заголовок TelephoneValidator:

#import <Foundation/Foundation.h>
#import "MAOTranslate.h"

@interface TelephoneValidator : NSObject {


    //opcje walidacyjne
    NSString *phonePrefix;
    NSString *phonePostfix;
    int       phoneLength;
    NSString *message;
    NSString *messagePl;

    UIAlertView *alertView;
}

-(id) initWithOptions:(NSArray *) optionsArray;

-(void) displayMessage;
-(BOOL) validate: (NSString *) phoneNumber;


@end

Класс TelephoneValidator:

#import "TelephoneValidator.h"


@implementation TelephoneValidator
//@synthesize phoneNumber;

-(id) initWithOptions:(NSArray *) optionsArray;
{
    if(self = [[TelephoneValidator alloc] init])
    {
        phonePrefix = [optionsArray objectAtIndex:0];
        phonePostfix = [optionsArray objectAtIndex:1];
        phoneLength = [[optionsArray objectAtIndex:2] intValue];
        message = [optionsArray objectAtIndex:3];
        messagePl = [optionsArray objectAtIndex:4];
    }
    else {
        self = nil;
    }

    return self;


}

//wyswietlamy wiadomosc
-(void) displayMessage
{
    NSString *displayMsg;
    if ([[MAOTranslate getLanguage] isEqualToString:@"pl"]) {
        displayMsg = messagePl;
    }
    else {
        displayMsg = message;
    }

    alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:displayMsg delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil];
    [alertView show];

}

-(BOOL) validate: (NSString *) phoneNumber
{


    //dlugosc
    if ([phoneNumber length] != phoneLength) {
        NSLog(@"zla dlugosc");
        return NO;
    }


    NSLog(@"tutaj");
    //sprawdzamy prefix     
    if ([phonePrefix length]!= 0) {     
        NSLog(@"w srodku ifa");
        if ([phoneNumber compare:phonePrefix options:NSLiteralSearch range:NSMakeRange(0, [phonePrefix length])] != 0) {
            NSLog(@"zly prefix");
            [self displayMessage];
            return NO;
        }
    }

    //sprawdzamy postfix
    if([phonePostfix length] != 0)
    {
        if ([phoneNumber compare:phonePostfix options:NSLiteralSearch range:NSMakeRange([phoneNumber length]-[phonePostfix length], [phonePostfix length])] != 0) {
            NSLog(@"zly postfix");
            [self displayMessage];
            return NO;
        }
    }


    //sprawdzamy czy string jest numeryczny

    NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];  
    NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:phoneNumber];  

    if (![alphaNums isSupersetOfSet:inStringSet]) 
    {
        NSLog(@"zly format ");
        [self displayMessage];
        return NO;
    }

    return YES; //zwalidowany poprawnie
}

-(void) dealloc
{   

    [alertView release];
    alertView = nil;
    [super dealloc];
}

Ответы [ 3 ]

2 голосов
/ 04 января 2011

Вам нужно вызвать [super dealloc] в конце метода dealloc.

1 голос
/ 04 января 2011

см. Эти обе строки

validator = [[TelephoneValidator alloc] initWithOptions: validatorOptions];

и внутри initWithOptions

if(self = [[TelephoneValidator alloc] init])

Вы дважды выделяете валидатор, поэтому есть утечка.

1 голос
/ 04 января 2011

Может ли прибор указывать на validatorOptions как источник утечки?Это удерживаемое имущество, освобождаемое на деаллок или нет?Я не могу точно сказать, что код, который вы разместили, недостаточен, чтобы прийти к выводу.

Также, как говорит willcodejavaforfood, вы всегда должны вызывать [super dealloc]; в конце вашего метода dealloc.После него не должно быть кода.

Редактировать:

Я вернулся.Но Бруно Домингес уже понял это правильно, вы выделяете дважды, и в этом случае первая утечка.Вы должны изменить свой -initWithOptions: код на:

-(id) initWithOptions:(NSArray *) optionsArray;
{
    if((self = [super init])){
    // ... rest of code is fine
    }

    return self;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...