Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS Memory leak in class method

In your opinion if I have a singleton subclass of NSObject being initialised with parameters like this:

- (MyObject *) initWithSomeParam:(NSString *)param{
    self = [super init];
    if (SharedInstance == nil){
        SharedInstance = [super init];
        SharedInstance.someProperty = param;
    }
    return self;
}

+ (MyObject *) objectWithSomeParam:(NSString *)param{
    return [[self alloc] initWithSomeParam:param];
    // Will the alloc cause a leak?
}

The user doesn't have access to the instance method, just the class. Thanks.

like image 436
John Lane Avatar asked Jun 01 '12 11:06

John Lane


People also ask

How detect memory leak IOS app?

Xcode's Memory Graph Debugger If you haven't used this yet, it's easy to access while developing. Tapping on the icon will pause your application and generate a graph of the objects with their references to other objects. If there's leaked memory detected, you will see purple icons on the left pane of Xcode.

How memory leak happens in IOS?

Memory that was allocated at some point, but was never released and is no longer referenced by your app. Since there are no references to it, there's now no way to release it and the memory can't be used again. So a memory leak occurs when a content remains in memory even after its life cycle has ended.


1 Answers

That's not the normal way of implementing a singleton and you are breaking the convention of init. Better would be to create a sharedInstance class method and leave the initWithParam method to be more conventional:

static MyObject *_sharedInstance = nil;

+ (MyObject *)sharedInstance:(NSString *)param
{
    if (_sharedInstance == nil)
    {
        _sharedInstance = [MyObject alloc] initWithParam:param];
    }
    return _sharedInstance;
}

// This must be called during app termination to avoid memory leak
+ (void)cleanup
{
    [_sharedInstance release];
    _sharedInstance = nil;
}

- (id)initWithParam:(NSString *)param
{
    self = [super init];
    if (self != nil)
    {
        self.someProperty = param;
    }
    return self;
}

However, even that doesn't seem very comfortable; i.e. what happens if the user calls sharedInstance with a different parameter? Perhaps you want to keep a NSMutableDictionary of the initialized objects and create/return them depending on the parameter?

If so, you would do:

static NSMutableDictionary _sharedInstances = [[NSMutableDictionary alloc] init];

+ (MyObject *)sharedInstance:(NSString *)param
{
    MyObject *obj = [_sharedInstances objectForKey:param];
    if (obj == nil)
    {
        obj = [[MyObject alloc] initWithParam:param];
        [_sharedInstances setObject:obj forKey:param];
    }
    return obj;
}

// This must be called during app termination to avoid memory leak
+ (void)cleanup
{
    [_sharedInstances release];
    _sharedInstances = nil;
}
like image 156
trojanfoe Avatar answered Oct 29 '22 01:10

trojanfoe