Seeking an exit equivalent in Swift
The exit
function isn't a keyword or built-in in C or Objective-C either. It's a library function. In Swift, you can access it by importing Darwin
:
import Darwin
exit(0)
Waiting until the task finishes
Use DispatchGroup
s to achieve this. You can either get notified when the group's enter()
and leave()
calls are balanced:
func myFunction() {
var a: Int?
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
a = 1
group.leave()
}
// does not wait. But the code in notify() gets run
// after enter() and leave() calls are balanced
group.notify(queue: .main) {
print(a)
}
}
or you can wait:
func myFunction() {
var a: Int?
let group = DispatchGroup()
group.enter()
// avoid deadlocks by not using .main queue here
DispatchQueue.global(attributes: .qosDefault).async {
a = 1
group.leave()
}
// wait ...
group.wait()
print(a) // you could also `return a` here
}
Note: group.wait()
blocks the current queue (probably the main queue in your case), so you have to dispatch.async
on another queue (like in the above sample code) to avoid a deadlock.
Use break into closures [Swift]
Desipte it's very important to know count of images , you can use this
func getImages(_ i:Int) {
let downloadURL = URL(string: "serverURL")
Database.downloadImage(withURL: downloadURL!) { (image) in
if let img = image {
self.imagesArray.append(img)
self.collectionView?.reloadData()
getImages(i+1)
}
else {
print("image is nil final call")
}
}
}
}
Also may be the download is dependent on i as not to make an infinite loop
Swift iOS -CMTimeMakeWithSeconds: warning: error of -0.433 introduced due to very low timescale
I did some research and AVPlayer
has a seek
method on it:
player.seek(to: <CMTime>, toleranceBefore: <CMTime>, toleranceAfter: <CMTime>)
With this method you can set a tolerance on it to compensate for the truncated overflow which in my situation was the additional -0.433 seconds.
In the first argument you put the time your seeking to and in the second and third arguments you put in kCMTimeZero
. Like this:
// seekTime is the time I’m seeking to
player.seek(to: seekTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
I also followed this answer and the trick was when I initialized my seek time for the second argument I had to put 1000 for everything to work. Like this:
let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1000)
Here's the code for my fast forward button:
@objc fileprivate func fastForwardButtonTapped() {
guard let playerItem = playerItem else { return }
guard let player = player else { return }
let duration: Float64 = CMTimeGetSeconds(playerItem.duration)
let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1000)
player.seek(to: seekTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
}
How to make async / await in Swift?
Thanks to vadian's comment, I found what I expected, and it's pretty easy. I use DispatchGroup()
, group.enter()
, group.leave()
and group.notify(queue: .main){}
.
func myFunction() {
let array = [Object]()
let group = DispatchGroup() // initialize
array.forEach { obj in
// Here is an example of an asynchronous request which use a callback
group.enter() // wait
LogoRequest.init().downloadImage(url: obj.url) { (data) in
if (data) {
group.leave() // continue the loop
}
}
}
group.notify(queue: .main) {
// do something here when loop finished
}
}
Programmatically change the state of a UILongPressGestureRecognizer
You're getting this error because by default, when you import UIKit into your implementation file, it imports UIGestureRecognizer.h, which publicly declares its state property as readonly. If you want to be able to set this property, you have to import UIGestureRecognizerSubclass.h, which redeclares this property as readwrite. Be warned, this is meant for use within a subclass of UIGestureRecognizer, and I don't know enough about how this works under the hood to say this usage is safe.
#import <UIKit/UIGestureRecognizerSubclass.h>
conversion from NSTimeInterval to hour,minutes,seconds,milliseconds in swift
Swift supports remainder calculations on floating-point numbers, so we can use % 1
.
var ms = Int((interval % 1) * 1000)
as in:
func stringFromTimeInterval(interval: TimeInterval) -> NSString {
let ti = NSInteger(interval)
let ms = Int((interval % 1) * 1000)
let seconds = ti % 60
let minutes = (ti / 60) % 60
let hours = (ti / 3600)
return NSString(format: "%0.2d:%0.2d:%0.2d.%0.3d",hours,minutes,seconds,ms)
}
result:
stringFromTimeInterval(12345.67) "03:25:45.670"
Swift 4:
extension TimeInterval{
func stringFromTimeInterval() -> String {
let time = NSInteger(self)
let ms = Int((self.truncatingRemainder(dividingBy: 1)) * 1000)
let seconds = time % 60
let minutes = (time / 60) % 60
let hours = (time / 3600)
return String(format: "%0.2d:%0.2d:%0.2d.%0.3d",hours,minutes,seconds,ms)
}
}
Use:
self.timeLabel.text = player.duration.stringFromTimeInterval()
Related Topics
How to Quit Swift Repl Without Using Ctrl-D
Detecting iOS Dark Mode Change
Swift: Function with Default Parameter Before Non-Default Parameter
iOS 13 Strange Search Controller Gap
Why Does a Public Class/Struct in Swift Require an Explicit Public Initializer
Storyboard Entry Point Missing
Difference Between Swift's Hash and Hashvalue
Coredata Crash Error Xcode 11 Beta, iOS 13 Beta
Present Actionsheet in Swiftui on iPad
Swiftui Views with a Custom Init
Nested Types Inside a Protocol
How to Override Layerclass in Swift
Xcode Autocomplete Does Not Work in Sources Folder of Swift Playgrounds
Disable Audio (And Interruption) with Mpmovieplayercontroller Using Swift
Stopping an Running Skaction - Sprite Kit