2014-08-29 7 views
5

sto sviluppando un progetto su iOS 7 utilizzando ARC, voglio rilasciare una proprietà privata quando il viewController viene rilasciato
Ecco l'TestViewController che si presenta come una vista modale controllo, l'impostazione di un valore alla proprietà privata in testAVPlayer viewDidLoad:Come per rilasciare la proprietà privata in iOS 7 utilizzando ARC

//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 è una sottoclasse di AVPlayer, ho messo un NSLog nella 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 

Quando TestViewController è respinto, il testAVPlayer sembra mai essere rilasciato, vedo il "dealloc TestViewController", ma non v'è alcuna "dealloc testAVPlayer" nel registro della console

+0

non è necessario dealloc questo è il punto intero di ARC ... – meda

+3

@meda yes, ma 'dealloc' dovrebbe ancora essere chiamato quando rilasciato da ARC. Qualcosa deve mantenere l'oggetto, ma temo che non ci sia abbastanza per andare avanti qui. –

+0

È possibile conservarlo da qualche parte nel blocco o utilizzare il timer ripetuto senza invalidarlo. Non sono abbastanza informazioni ora. –

risposta

10

ho provato il codice, il problema è che anche se si chiama [TestAVPlayer playerWithPlayerItem:item] classe TestAVPlayer non ha tale metodo, in modo che chiamerà playerWithPlayerItem: funzione dal la classe base AVPlayer, che restituirà un'istanza della classe AVPlayer anziché la classe TestAVPlayer. Il compilatore non ti avviserà perché il metodo playerWithPlayerItem: restituisce un tipo di id. Se si seleziona questo con il debugger vedrete che il tipo di variabile privata non è TestAVPlayer:

enter image description here

La dealloc del TestAVPlayer non verrà mai chiamato come tale oggetto è stato creato. L'istanza AVPlayer viene deallocata quando lo TestViewController viene deallocato. Puoi verificarlo utilizzando gli strumenti o semplicemente aggiungendo un punto di rottura simbolico a [AVPlayer dealloc].

Selezionare il Breakpoint Navigator e fare clic sul pulsante + e aggiungere un punto di interruzione simbolico.

Write [AVPLayer dealloc] al simbolo campo e premere Invio.Quando si esegue l'applicazione e lo TestViewController viene deallocato, si vedrà che il punto di interruzione verrà colpito, quindi lo AVPlayer verrà effettivamente deallocato.

2

testAVPlayer = [AVPlayer playerWithPlayerItem:playerItem];

Si utilizza AVPlayer, non il vostro TestAVPlayer.

+0

BTW dovrebbe essere la risposta corretta. :) Non ho notato che AVPlayer è usato al posto della sottoclasse. –

+0

Ho modificato il mio codice, sostituendo AVPlayer con TestAVPlayer, ma non è ancora possibile rilasciare – bandw

+0

@bandw Hai accesso a 'testAVPlayer' da qualche altra parte? –

5

Si sta utilizzando un metodo di classe factory per inizializzare l'oggetto, il che significa che non si possiede l'oggetto testAVPlayer e quindi non si è responsabili del rilascio.

Vedere Class Factory Methods dai Concetti nella guida alla programmazione in Objective-C per ulteriori dettagli.

Se davvero vuole possedere e controllare la durata di questo oggetto, utilizzare la seguente inizializzazione:

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

e il metodo di dealloc sarà chiamato.

1

Prova attuazione - viewDidUnload quindi nullo il testAVPlayer:

- (void) viewDidUnload 
{ 
    [super viewDidUnload]; 
    testAVPlayer = nil; 
} 
1

Anche se si sta chiamando come [TestAVPlayer playerWithPlayerItem:item], siete veramente tornare un'istanza di AVPlayer, non TestAVPlayer. In effetti, l'istanza di AVPlayer che hai creato si sta davvero deallocando. Non sarai in grado di vedere il tuo log in dealloc perché non viene mai creata un'istanza di quella classe.

Come suggerito da un altro, sostituire [TestAVPlayer playerWithPlayerItem:item] con [[TestAVPlayer alloc] initWithPlayerItem:item]; e si dovrebbe iniziare a vedere i registri.