0

I just wonder what is the best implementation of memory optimized versatile multi Timers in swift. The timers which are concurrent and have weak reference with Dispatch? I've tried to implement two timers in one view controller and I got an error.

one of my timer was like this:

func startOnPlayingTimer() {

 let queue = DispatchQueue(label: "com.app.timer")
 onPlayTimer = DispatchSource.makeTimerSource(queue: queue)
 onPlayTimer!.scheduleRepeating(deadline: .now(), interval: .seconds(4))
 onPlayTimer!.setEventHandler { [weak self] in
   print("onPlayTimer has triggered")
 }
 onPlayTimer!.resume()   
}

another one was:

 carouselTimer = Timer.scheduledTimer(timeInterval: 3, target: self,selector: #selector(scrollCarousel), userInfo: nil, repeats: true)
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Emran
  • 79
  • 1
  • 11
  • 1
    I would just create multiple `Timer` instances. What error are you getting? – Paulw11 May 26 '17 at 12:14
  • @Paulw11 Actually, I could implement this with `Timer` today. but I'm in doubt wich is this function thread safe? and has a "weak reference"? I'm looking for to implement this with Dispatch and make it thread safe and memory optimized. – Emran May 26 '17 at 18:15
  • Thread safety and cicrcular strong references are separate issues to the timer. No timer approach will give you inherent thread safety. Thread safety depends on what you are doing in the closure that is dispatched by the timer. Timers can have an impact on energy use and in fact Apple specifically advises not to use timers as a synchronisation technique; https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/MinimizeTimerUse.html. You still haven't explained what the "error" was when you tried to use two timers – Paulw11 May 26 '17 at 21:17
  • The error was very long but I'll send the first statement here: `This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.` I got this error after a while when I tried to use these two implementations together. Does `Timer()` function have strong reference or weak? – Emran May 27 '17 at 06:45
  • If you search for that message you will find many hits; You must dispatch any UI updates onto the main queue. You would hold a strong reference to your timer. The timer will hold a weak reference to the invocation target. – Paulw11 May 27 '17 at 06:48
  • Thank you, I got what the problem is but I couldn't know why I should hold strong reference to my timer? If I ran out of memory timer and view controller should be realsed.Don't they? – Emran May 27 '17 at 07:06
  • If you don't hold a strong reference to your timer then it will be released immediately; something has to hold a strong reference to every object or it will be released; You should read up on how ARC works. – Paulw11 May 27 '17 at 07:54

1 Answers1

0

I dont think there is need for multiple timer for any application. If from before hand you know which methods you are going to fire, Keep boolean for each method you need to fire and also an Int to save the occurrence of the method. You can invoke the timer once, with a method that checks for the required boolean and its respective method.

A pseudo code referencing the above logic is below :

  class ViewController: UIViewController {


var myTimer : Timer!

var methodOneBool : Bool!
var methodTwoBool : Bool!
var mainTimerOn : Bool!


var mainTimerLoop : Int!
var methodOneInvocation : Int!
var methodTwoInvocation : Int!

override func viewDidLoad() {
    super.viewDidLoad()
   configure()
}

func configure(){
    methodOneBool = false
    methodTwoBool = false

    methodOneInvocation = 5 // every 5 seconds
    methodTwoInvocation = 3 //every 3 seconds

    mainTimerOn = true // for disable and enable timer
    mainTimerLoop = 0 // count for timer main
}

func invokeTimer(){
    myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(checkTimerMethod), userInfo: nil, repeats: true)
}


func checkTimerMethod(){

    if(mainTimerOn){

        if(mainTimerLoop % methodOneInvocation == 0 && methodOneBool){
            // perform first method
            // will only get inside this when
            // methodOneBool = true and every methodOneInvocation seconds
        }

        if(mainTimerLoop % methodTwoInvocation == 0 && methodTwoBool){
            // perform second method
            // will only get inside this when
            // methodTwoBool = true and every methodTwoInvocation seconds
        }

        mainTimerLoop = mainTimerLoop + 1

    }
 }

}

I hope this clears up the problem, also if I didnt understand your requirement please comment below, so that I can edit the answer accordingly

Saheb Roy
  • 5,899
  • 3
  • 23
  • 35
  • 1
    IMO it is much simpler just to have two timers – Paulw11 May 26 '17 at 12:15
  • 1
    Timer are very heavy objects and takes a lot of memory to invoke AFAIK, So its good to maintain as less as possible – Saheb Roy May 26 '17 at 12:40
  • . Always go for the simplest solution and optimise if necessary once you determine that there is an issue. Your solution has many more "moving parts" and therefore potential for bugs – Paulw11 May 26 '17 at 13:09
  • Thanks, but IMO this solution is not so efficient. Your timer every second invoke a function. You decreased the number of timers but increase complexity. – Emran May 26 '17 at 18:59