Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to release the private property in iOS 7 using ARC

I am developing a project on iOS 7 using ARC, I want to release a private property when the viewController is released
Here is the TestViewController that is presented as a modal view controller, setting a value to the private property testAVPlayer in viewDidLoad:

//TestViewController.m
#import "TestAVPlayer.h"
@interface TestViewController () {
    TestAVPlayer *testAVPlayer;
}

@end

- (void)viewDidLoad
{
    [self setupPlayer];
}

- (void)setupPlayer {
    AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"music" withExtension:@"mp3"]];
    testAVPlayer = [TestAVPlayer playerWithPlayerItem:item];

    [testAVPlayer setActionAtItemEnd:AVPlayerActionAtItemEndNone];
    [testAVPlayer play];
}

- (void)dealloc {
    NSLog(@"dealloc TestViewController: %@", self);
}

TestAVPlayer is a subclass of AVPlayer, I put a NSLog into the dealloc

// TestAVPlayer.h
#import <AVFoundation/AVFoundation.h>

@interface TestAVPlayer : AVPlayer

@end

//  TestAVPlayer.m
#import "TestAVPlayer.h"

@implementation TestAVPlayer

- (void)dealloc {
    NSLog(@"dealloc testAVPlayer: %@", self);
}
@end

When TestViewController is dismissed, the testAVPlayer seems never be released, I see the "dealloc TestViewController", but there is no "dealloc testAVPlayer" in console log

like image 809
bandw Avatar asked Aug 29 '14 04:08

bandw


3 Answers

I tried your code, the problem is that even if you call [TestAVPlayer playerWithPlayerItem:item] the TestAVPlayer class doesn't have such method, so it will call playerWithPlayerItem: function from the AVPlayer base class, which will return an instance of the AVPlayer class instead of the TestAVPlayer class. The compiler won't give you any warning because the playerWithPlayerItem: method returns a type of id. If you check this with the debugger you'll see that the private variable's type is not TestAVPlayer:

enter image description here

The dealloc of the TestAVPlayer will never be called as no such object was created. The AVPlayer instance gets deallocated when the TestViewController is deallocated. You can check this by using Instruments or simply adding a Symbolic Breakpoint to [AVPlayer dealloc].

Select the Breakpoint Navigator and click on the + button and add a Symbolic Breakpoint.

Write [AVPLayer dealloc] to the Symbol field and press Enter. When you run the application and the TestViewController gets deallocated then you will see that the breakpoint will be hit, hence the AVPlayer really gets deallocated.

like image 108
Bedford Avatar answered Nov 12 '22 06:11

Bedford


You are using a class factory method to initialize your object, which means that you do not own the testAVPlayer object and thus are not responsible for releasing it.

See Class Factory Methods from the Concepts in Objective-C Programming guide for more details.

If you indeed want to own and control the lifetime of this object, use the following initializer:

testAVPlayer = [[TestAVPlayer alloc] initWithPlayerItem:item];

and your dealloc method will be called.

like image 5
mgcm Avatar answered Nov 12 '22 05:11

mgcm


testAVPlayer = [AVPlayer playerWithPlayerItem:playerItem];

You are using AVPlayer, not your TestAVPlayer.

like image 2
Gary Lyn Avatar answered Nov 12 '22 06:11

Gary Lyn