Timer and pointers to it...

Discussion in 'iOS Programming' started by grandM, Mar 10, 2018.

  1. grandM macrumors 6502a

    grandM

    Joined:
    Oct 14, 2013
    #1
    Hi guys

    I have a question about Timer objects. In the code beneath I've created a Timer object which is deleted upon the disappearance of the view. As I call for invalidate on this object the Timer object should be removed. To do so I made a timer property in my ViewController so I can refer to the Timer object to which the main run loop refers. Checking it with Instruments I came to the same conclusion though that the property isn't pointing to the same memory address as the main run loop? Can anyone explain me why this is the case? I would have expected it to be the same memory address?

    Instruments delivers following output on Allocations/Statistics/Allocation summary/CFRunLoopTimer:
    CFRunLoopTimer
    0x60000017c080 CFRunLoopTimer Foundation -[NSCFTimer initWithFireDate:interval:target:selector:userinfo:repeats:]
    0x60000017c740 CFRunLoopTimer QuartzCore CA::update_timer()

    Under Allocations/Statistics/Allocation summary I also found
    CFRunLoopTimer (contents described above)
    awd::profile:TimerSpec
    NSCFTimer

    Clicking on awd::profile:TimerSpec I found the contents
    0x60000026d00 awd::profile:TimerSpec WirelessDiagnostics awd::profile::protobuf_AddDesc_AwdProfile_2eproto()

    Clicking on NSCFTimer I found the contents
    0x60000012530 NSCFTimer Foundation _27+[NSFCTimer allocWithZone:]_block_invoke

    Code:
    
    class ViewController: UIViewController {
    
       
    
        @IBOutlet weak var timeLabel: UILabel!
    
        let clock = Clock()
    
        var timer: Timer?
    
       
    
        override func viewDidLoad() {
    
            super.viewDidLoad()
    
        }
    
    
    
        override func viewWillAppear(_ animated: Bool) {
    
            super.viewWillAppear(animated)
    
            updateTimeLabel()
    
            timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.updateTimeLabel), userInfo: nil, repeats: true)
    
        }
    
       
    
        override func viewWillDisappear(_ animated: Bool) {
    
            super.viewWillDisappear(animated)
    
            timer?.invalidate()
    
        }
    
       
    
        func updateTimeLabel() {
    
            let formatter = DateFormatter()
    
            formatter.timeStyle = .medium
    
            timeLabel.text = formatter.string(from: clock.currentTime as Date)
    
        }
    
       
    
        override func didReceiveMemoryWarning() {
    
            super.didReceiveMemoryWarning()
    
            // Dispose of any resources that can be recreated.
    
        }
    
    }
    
     
  2. PhoneyDeveloper macrumors 68040

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    According to the Apple docs Timer, NSTimer are toll free bridged to CFRunLoopTimer so I assume the addresses of one in swift reported by Instruments would match the other. Your first two lines represent two different timers. One, presumably the one from your code, created by -[NSCFTimer initWithFireDate:interval:target:selector:userinfo:repeats:] and the other created by QuartzCore. I can't say why the various objects you show don't have the same address except that maybe more Timers were created than you expect.

    Is there a bug or is this just a fascination?

    BTW, I always set a Timer variable to nil after invalidating it.
     
  3. grandM, Mar 17, 2018
    Last edited: Mar 17, 2018

    grandM thread starter macrumors 6502a

    grandM

    Joined:
    Oct 14, 2013
    #3
    I am trying to understand timers a bit better. When you talk about the timer created by QuartzCore do you refer to the Timer object on the main run loop? Or is this Timer object found on another line?

    In the former case I'm a bit puzzled as I don't expect a second timer to be produced. I would think a second pointer is made to the same Timer object. This Timer object is created by the -[NSCFTimer initWithFireDate:interval:target:selector:userinfo:repeats:] initialisation method. In that process a extra pointer would be made to that Timer object. This second pointer would be directed from the main run loop. In that case two pointers would be pointing at the same memory address. As those memory addresses don't match I stand puzzled.

    I posted the full code. In the latter case the explanation could be that by not setting the pointer to nil in the swift file the Timer objects created by the -[NSCFTimer initWithFireDate:interval:target:selector:userinfo:repeats:] initialisation method keep filling up the memory. The invalidation method does remove the pointer from the main run loop. The pointer from the VC is still there though keeping it in memory.

    In both cases there however should be at least one repeating memory address. To be entirely clear which of those memory addresses comes from the main run loop?
     
  4. PhoneyDeveloper macrumors 68040

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #4
    The Timer I refer to from QuartzCore is this one that you showed. I can't tell which runloop it's on.

    0x60000017c740 CFRunLoopTimer QuartzCore CA::update_timer()

    I assume that the other one you show is the one from your code. You could try commenting out the one from your code and running instruments. Any timers that show up are of course not yours.

    Like you, I expect that because timers are toll-free bridged the various classes displayed in Instruments would have the same addresses. However, I don't think Instruments will tell you which runloop a timer is on.
     

Share This Page