在iPad上泄漏,我不明白

时间:2011-01-04 13:28:25

标签: objective-c xcode memory-leaks ipad

我的应用程序漏洞了,我不知道为什么。也许我的所有记忆管理都是错误的。在我的代码中,我有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不是NSString,则验证器ivar成为TelephoneValidator实例。

在我的dealloc中:

- (void)dealloc {

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

我已经检查了几次dealloc是否有效,而且确实如此。在调用dealloc之后,验证器被释放(在[validator release]之后调用验证器上的任何方法使我异常)。

然而在仪器中,它告诉我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 个答案:

答案 0 :(得分:2)

你需要在dealloc方法的末尾调用[super dealloc]。

答案 1 :(得分:1)

可能是仪器指向validatorOptions作为泄漏的来源吗?是否是在dealloc发布的保留财产?我不能肯定地说,你发布的代码还不足以得出结论。

另外,正如willcodejavaforfood所说,你必须在你的dealloc方法结束时调用[super dealloc];。没有代码必须在它之后。

编辑:

我回来了。但是Bruno Domingues已经把它弄好了,你要分配两次,在这种情况下,第一次泄漏。您应该将-initWithOptions:代码更改为:

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

    return self;
}

答案 2 :(得分:1)

参见这两行

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

和initWithOptions内部

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

您正在分配两次验证器,因此存在泄漏。