UIView-subklasse wordt niet vrijgegeven

Ik heb een subklasse UIView die niet wordt gealloceerd. Ik weet dat slechts één klas een voorbeeld van mijn mening creëert. Ik heb volgens mij een NSTimer-variant. Als ik die timer uitschakel en als ik op een annuleerknop tik die op deze view-controller staat, wordt dealloc in deze view aangeroepen. Als ik de timer niet becommentarieer, wordt de dealloc nooit gebeld.

//CustomUIView
- (id) initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }
}

Ik wil een verwijzing naar deze timer behouden, omdat er momenten zijn waarop ik de timer wil pauzeren. Nu zou ik een eigenschap naar mijn mening kunnen hebben voor de timer en bij de dealloc-methode van de klasse die een verwijzing naar mijn aangepaste uiview heeft, kon ik deze ongeldig maken voordat ik de weergave losliet. Ik vind deze aanpak niet echt leuk omdat ik deze timer niet wil blootstellen aan externe entiteiten.

Heeft iemand ideeën?

2
NSTimer behoudt zijn doel ...
toegevoegd de auteur fbernardo, de bron

3 antwoord

NSTimer always retains its target. This has two implications:

  1. Het is niet de bedoeling dat de weergave (het doel van de timer) de timer behoudt, omdat hierdoor een cyclus wordt gecreëerd.

  2. Uw weergave zal nooit worden verwijderd zolang de timer actief blijft.

In plaats daarvan moet u invalideren op de timer als u hiermee klaar bent. Zodra dit is gebeurd, wordt de weergave dealloc weergegeven wanneer het referentietelling op nul wordt gezet.

Meestal gebeurt dit wanneer een weergave wordt verwijderd uit zijn superview; als je wilt dat het zijn timer blijft gebruiken totdat dat gebeurt en dan wordt vrijgegeven, kun je removeFromSuperview overschrijven om de timer te ontkrachten en vervolgens super aan te roepen.

6
toegevoegd
Hoe kan dit antwoord slechts een upvote bevatten? (Nou ja, nu twee ...) Opheffen removeFromSuperview was de sleutel voor mij, bedankt Rickster.
toegevoegd de auteur BP., de bron

You should not retain the timer. Schedule the timer like this : _pollTimer = [NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES]; and whenever you want to invalidate it: [_pollTimer invalidate]

1
toegevoegd

Bewerk:

Probeer in de methode -dealloc dit:

- (void) dealloc
{
    [_pollTimer invalidate];

    /*
        If not using ARC:
        [_pollTimer release], _pollTimer = nil;
        [super dealloc];
    */
}

U bent vergeten super 's implementatie van -initWithFrame: aan te roepen! Whoops!

- (id) initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame]))
    {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }

    return self;
}

Dit zou veel beter moeten werken.

0
toegevoegd
Als NSTimer het doelwit behoudt, raakt het aantal keren behouden niet nul en daarom wordt het object dealloc ed. U moet die code uit dealloc halen en het elders noemen als u klaar bent met deze weergave.
toegevoegd de auteur Rob, de bron
eigenlijk doe ik dat. sorry is vergeten maar dat in mijn codefragment.
toegevoegd de auteur developerdoug, de bron