Swift - Background Fetch and Delay - ios

I implemented Background Fetch feature in my App.
The function called by background fetch includes a delayed function.
However this function doesn't seem to trigger :
let when = DispatchTime.now() + 2
DispatchQueue.main.asyncAfter(deadline: when) {
MyFunction()
}
It seems to trigger however as soon as I wake up the app.
Why this doesn't trigger on background fetch ?

Try this code:
DispatchQueue.global().async {
let timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.MyFunction), userInfo: nil, repeats: false)
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
RunLoop.current.run()
}

I don't think you can run in the background on the main queue. Try this (changed main to global()):
let when = DispatchTime.now() + 2
DispatchQueue.global().asyncAfter(deadline: when) {
MyFunction()
}

Related

How to call function on time? Also How to Call only once time in swift 3?

How to call function on time? Also How to Call only once time in swift 3?
i need to call one function one time only, so how can possible to call function only one time like after 3 seconds?
You can do something like,
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
yourFunction() // call your functin here
}
You can also use DispatchQueue.global().asyncAfter if you don't want to perform your task on main thread!
And refer this post to manage it one time only!
private let _onceToken = NSUUID().uuidString
DispatchQueue.once(token: _onceToken) {
print( "Do This Once!" )
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
yourFunction() // call your functin here
}
}
It will execute your method only once and delay your method for 3 seconds.
For start timer:
var timerUpdateArray:Timer!
func callTimer(){
self.timerUpdateArray = Timer.scheduledTimer(timeInterval: 1,
target: self, selector: #selector(yourFunc),
userInfo: nil, repeats: true)
}
For stop timer:
self.timerUpdateArray.invalidate()

Adding Tme Countdown to App Using a Thread

I'm trying to add a countdown timer to an existing app. Naturally, I don't want this timer to stall the rest of the application so I wanted to use an asynchronous thread dedicated to the timer. This is my current code and it doesn't even get to the update function (I used print statements to test this), but does print "Got". Also, I'm trying to update a label with the correct time and you can't do that within the thread. The time variable is a class variable. Not sure if this is even the correct approach, any suggestions?
Edit: Running the timer on main queue doesn't work as it interferes with a pan gesture I already have on the app. Also, any proposed solutions to the timing inaccuracies of the Timer Class would also be great.
func startTimer() {
time = 30
let queue = DispatchQueue(label: "timer")
queue.async {
print("Got")
_ = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
}
func update() {
DispatchQueue.main.sync {
if(time >= 0) {
time -= 1
timer.text = String(time)
} else {
timer.text = "0"
}
}
}

How to wait a given time to run an action-SWIFT

I would like to know how to run an action after making the console count a given time. For example printing 'hello' after 3 seconds.
Thank you!!
You need to use the NSTimer class.
Example usage:
var timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
Somewhere else in your class...
func sayHello() {
println("Hello")
}
You can create delays with following ways!!
You can create a delay using asynAfter
DispatchQueue.main.asyncAfter(deadline: .now() + <secondsToDelay>) {
// Put your code here that you want to execute after delay
}
Another way is calling a function itself after a delay using objc's perform selector
perform(#selector(delayedMethod), with: nil, afterDelay: <secondsToDelay>)
#objc func delayedMethod() {
print("My delayed method call")
}
Of course you can also use Timer like in Woodstock's answer.

NSTimer - how to delay in Swift

I have a problem with delaying computer's move in a game.
I've found some solutions but they don't work in my case, e.g.
var delay = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: nil, userInfo: nil, repeats: false)
I tried to use this with function fire but also to no effects.
What other possibilities there are?
Swift 3
With GCD:
let delayInSeconds = 4.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayInSeconds) {
// here code perfomed with delay
}
or with a timer:
func myPerformeCode() {
// here code to perform
}
let myTimer : Timer = Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(self.myPerformeCode), userInfo: nil, repeats: false)
Swift 2
With GCD:
let seconds = 4.0
let delay = seconds * Double(NSEC_PER_SEC) // nanoseconds per seconds
let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
// here code perfomed with delay
})
or with a timer:
func myPerformeCode(timer : NSTimer) {
// here code to perform
}
let myTimer : NSTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: Selector("myPerformeCode:"), userInfo: nil, repeats: false)
With Swift 4.2
With Timer You can avoid using a selector, using a closure instead:
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (nil) in
// Your code here
}
Keep in mind that Timer is toll-free bridged with CFRunLoopTimer, and that run loops and GCD are two completely different approaches.... e
In swift we can delay by using Dispatch_after.
SWift 3.0 :-
DispatchQueue.main.asyncAfter(deadline: .now()+4.0) {
alert.dismiss(animated: true, completion: nil)
}
How about using Grand Central Dispatch?
https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html
Valfer has shown you how

Swift performSelector:withObject:afterDelay: is unavailable [duplicate]

This question already has answers here:
dispatch_after - GCD in Swift?
(26 answers)
Closed 8 years ago.
I have an app in Objective C that I'm transitioning to Swift. In Objective C, I have this method:
[self.view performSelector:#selector(someSelector) withObject:self afterDelay:0.1f];
I'm working with Swift and I can't figure out how to do this. I've tried:
self.view.performSelector(Selector("someSelector"), withObject: self, afterDelay: 0.1)
Here's the error that I get: 'performSelector' is unavailable: 'performSelector' methods are unavailable
What call would I use to call a method afterDelay?
UPDATE
Here's what I ended up with:
extension NSObject {
func callSelectorAsync(selector: Selector, object: AnyObject?, delay: NSTimeInterval) -> NSTimer {
let timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: selector, userInfo: object, repeats: false)
return timer
}
func callSelector(selector: Selector, object: AnyObject?, delay: NSTimeInterval) {
let delay = delay * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
NSThread.detachNewThreadSelector(selector, toTarget:self, withObject: object)
})
}
}
Swift 4
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your function here
}
Swift 3
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(0.1)) {
// your function here
}
Swift 2
let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
// your function here
})
You could do this:
var timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("someSelector"), userInfo: nil, repeats: false)
func someSelector() {
// Something after a delay
}
SWIFT 3
let timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(someSelector), userInfo: nil, repeats: false)
func someSelector() {
// Something after a delay
}
Swift is statically typed so the performSelector: methods are to fall by the wayside.
Instead, use GCD to dispatch a suitable block to the relevant queue — in this case it'll presumably be the main queue since it looks like you're doing UIKit work.
EDIT: the relevant performSelector: is also notably missing from the Swift version of the NSRunLoop documentation ("1 Objective-C symbol hidden") so you can't jump straight in with that. With that and its absence from the Swiftified NSObject I'd argue it's pretty clear what Apple is thinking here.

Resources