Dhanesh Dhanesh - 2 months ago 24
iOS Question

getting memory leak in [[NSNumberFormatter alloc] init] in instrument with ARC enable project

Getting wired memory leak on

NSNumberFormatter
in my project.

While i am checking my app in
Instrument
i am getting many framework leaks and one of very surprising leak was
NSNumberFormatter
leak while I am allocing that formatter object.

Here is my function to formatting my Number value:

//Set Number Formatter - Like 1000 = 1,000
+ (NSString *)getNumberWithNumberFormate:(NSString*)dataVal{
NSNumberFormatter *aNumberFormatter = [[NSNumberFormatter alloc] init];
[aNumberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSString *aFormattedNumber = [aNumberFormatter stringFromNumber:[NSNumber numberWithDouble:[dataVal doubleValue]]];
aNumberFormatter = nil;
return aFormattedNumber;
}


while I am checking memory leak it will show

NSNumberFormatter *aNumberFormatter = [[NSNumberFormatter alloc] init];


This line as leak.

I have also
nil
this object after my formatting done.

aNumberFormatter = nil;


still memory leak is there.

any idea to resolve this leak.

Check this instrument screenshot.enter image description here

Answer

So for your case you no need set instance to nil aNumberFormatter = nil The instance of NSNumberFormatter will destroy after getNumberWithNumberFormate class method will out of scope. Try to modify a bit your method to

+ (NSString *)getNumberWithNumberFormate:(NSString*)dataVal{
    NSNumberFormatter *aNumberFormatter = [[NSNumberFormatter alloc] init];
    [aNumberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
    NSString *aFormattedNumber = [aNumberFormatter stringFromNumber:[NSNumber numberWithDouble:[dataVal doubleValue]]];
    return aFormattedNumber;
}

Also the good practice use static instance and dispatch_once for formatter like below

+ (NSString *)getNumberWithNumberFormate:(NSString*)dataVal{
    static NSNumberFormatter *aNumberFormatter = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        aNumberFormatter = [[NSNumberFormatter alloc] init];
        [aNumberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
    });
    NSString *aFormattedNumber = [aNumberFormatter stringFromNumber:[NSNumber numberWithDouble:[dataVal doubleValue]]];
    return aFormattedNumber;
}

In this example you will use only one instance for every time of using this class method and will decrease memory usage

Answer for comment and clear debugging try to check this code

+ (NSString *)getNumberWithNumberFormate:(NSString*)dataVal{
    NSString *copyDataValue = [dataVal copy];
    double dataValueDouble = [copyDataValue doubleValue];
    static NSNumberFormatter *aNumberFormatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        aNumberFormatter = [[NSNumberFormatter alloc] init];
        [aNumberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
    });
    NSString *aFormattedNumber = [aNumberFormatter stringFromNumber:@(dataValueDouble)];
    return aFormattedNumber;
}
Comments