Is there a way to delay a return-Statement in Swift?
You are looking for a closure, a.k.a. completion handler.
return
executes immediately and there is no way to delay that. Instead, you can use completion handlers, which work by passing in a closure as a parameter. This closure can then be called after a delay.
/// closure here!
func returnLate(completion: @escaping ((String) -> Void)) {
var string = "Wrong"
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
string = "right"
completion(string) /// similar to `return string`
}
}
override func viewDidLoad() {
super.viewDidLoad()
returnLate { string in
print("String is \(string)") /// String is right
}
}
How to create a delay in Swift?
Instead of a sleep, which will lock up your program if called from the UI thread, consider using NSTimer
or a dispatch timer.
But, if you really need a delay in the current thread:
do {
sleep(4)
}
This uses the sleep
function from UNIX.
Delay the return value instead of whole method
Use a block to call back with return value with delay;
- (void)ayncGetValue:(void(^)(id value))returnBlock {
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 10.f * NSEC_PER_SEC); // delay 10 seconds
dispatch_after(popTime, dispatch_get_main_queue(), ^{
returnBlock(@"hello block");
});
}
// Usage
[obj ayncGetValue:^(id value) {
// continue
}];
How to program a delay in Swift 3
After a lot of research, I finally figured this one out.
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.
// Code you want to be delayed
}
This creates the desired "wait" effect in Swift 3 and Swift 4.
Inspired by a part of this answer.
How can I put a time delay within an IF statement in Swift?
Taking aheze's code suggestion and adding it to my program in the proper position has worked, and now the app pauses for a second upon successful login. This doesn't work entirely as I need it to, as the successful login message simply does not appear now, probably due to the time delay, however I'm sure I can work around this as it appears to be simple issue!
aheze's code inserted into my program:
if self.username == storedUsername && self.password == storedPassword {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.authenticationDidSucceed = true
}
Once again, thanks for the help, and I hope I've done it right!
Delaying function in swift
You can use GCD (in the example with a 10 second delay):
Swift 2
let triggerTime = (Int64(NSEC_PER_SEC) * 10)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, triggerTime), dispatch_get_main_queue(), { () -> Void in
self.functionToCall()
})
Swift 3 and Swift 4
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
self.functionToCall()
})
Swift 5 or Later
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
//call any function
}
Adding delay between execution of two following lines
You can use gcd to do this without having to create another method
// ObjC
NSTimeInterval delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(@"Do some work");
});
// Swift
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Do some work)
}
You should still ask yourself "do I really need to add a delay" as it can often complicate code and cause race conditions
How to put delay for each iteration of loop
Your current code doesn't work because you are doing the increment asynchronously. This means that the for loop will still run at its normal speed.
To achieve what you want, you can use a timer like this:
var count = 0
let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ _ in
count += 1
print(count)
}
If you want it to stop after 5 times, do this:
var count = 0
var timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ t in
count += 1
print(count)
if count >= 5 {
t.invalidate()
}
}
How can I call a function after a time delay in the main thread in Swift 3?
I don't think it needs to be anywhere near that complicated. You can just use a Timer
;
class MyClass: UIViewController {
var tapCount = 0
var tapTimer: Timer?
@IBAction tapped(_ sender: Any) {
if tapCount < 3 {
tapCount += 1
tapTimer?.invalidate()
tapTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { (timer) in
switch (self.tapCount) {
case 1:
self.f1()
case 2:
self.f2()
case 3:
self.f3()
default:
// Hmm, shouldn't happen
}
self.tapCount = 0
})
}
}
The timer will be scheduled on the main queue by default, so there is no need to dispatch anything on the main queue specifically
Related Topics
Exc Bad Access While Creating a New Characterset
Implement a Crosshair Kind Behaviour in Realitykit
Swiftui Change on Multilevel Children Published Object Change
Setadvertisertrackingenabled Is Not Found in Settings Class of Fbsdk
How to Pass Data from Using Post/Form Leaf Template
How to Get a Full List of Running Processes
Calculate Range of String from Word to End of String in Swift
Why Is My App Returning Hundreds of Errors That Say "Undefinedsymbol"
How to Refer to a Global Type from Within a Class That Has a Nested Type with The Same Name
Swiftui Navigationview Not See Image
Pass and Print All Cases in an Enum in Swift
How to Calculate The Camera Position from Vuforia Gl Matrix
Swiftsupport Folder Not Included in The IPA When Generating Build from Script
Swift - Connect Delegate to Custom Xib Cell