[swift-evolution] Removal of dispatch_once() in Swift 3?

Michael Peternell michael.peternell at gmx.at
Thu Jun 16 15:46:12 CDT 2016


I've used something that is very similar to dispatch_once in Swift 2.2. It looks like this (taken from real code in a real application):

public static let defaultMap: RAStaticMap = RAStaticMap.loadCountries()

The function RAStaticMap.loadCountries() is actually private, and it is called exactly once. This is a feature of the "static let". The accessor is threadsafe. I'm not sure if this is documented behavior or if it is merely an undocumented feature of static let's.

This works at least for the common use case that you want to create some value exactly once, e.g. for a singleton "+sharedInstance" initializer.

-Michael

> Am 16.06.2016 um 19:48 schrieb William Shipley via swift-evolution <swift-evolution at swift.org>:
> 
> I may be missing something, but I don’t understand how to get the behavior of dispatch_once() without a bunch more code in cases in which I was using it to initialize “lazy-ish" instance variables.
> 
> public class PlatonicPieceOfFurniture {
> 
>     internal var modelDirectoryURL: URL
> 
>     /* … */
> 
>     public var floorGeometryAndMaterial: FloorPlatonicGeometryAndMaterial {
>         dispatch_once(&dispatchOnceLoadGeometriesAndMaterials) {
>             self.floorGeometryAndMaterialBacking = try! FloorPlatonicGeometryAndMaterial(modelDirectory: self.modelDirectoryURL)
> 	}
>         return floorGeometryAndMaterialBacking!
>     }
>     private var floorGeometryAndMaterialBacking: FloorPlatonicGeometryAndMaterial?
>     private var dispatchOnceLoadGeometriesAndMaterials: dispatch_once_t  = 0
> 
> }
> 
> Note that ‘floorGeometryAndMaterial' isn’t a global, and that it requires ‘modelDirectoryURL’ as input when it is lazily initialized, so I can't just do:
> 
>     public lazy var floorGeometryAndMaterial: FloorPlatonicGeometryAndMaterial? = try! FloorPlatonicGeometryAndMaterial(modelDirectory: modelDirectoryURL)
> 
> Because that throws a “instance member ‘modelDirectoryURL’ cannot be used on type ‘PlatonicPieceOfFurniture’” error in Xcode. (Also, honestly, I don’t see much utility in lazy instance variables in Swift, since I can’t use any state from the current instance to initialize them, so they’re usually no better than static variables — I don’t think I’ve ever used them, despite trying a bunch.)
> 
> Also this needs to be thread-safe, and loading the backing is very slow so we really don’t want to ever accidentally do it twice (although it would be safe to do so in my code), so I can’t just check if ‘floorGeometryAndMaterialBacking’ is nil and load it up if it is.
> 
> 
> I could do an ugly version of this with semaphores and an extra flag, but it seems a lot cleaner with dispatch_once().
> 
> Am I missing something obvious? The Swift 3 converter completely mangled my code into a static case which didn’t compile at all and couldn’t possibly work.
> 
> 
> -Wil Shipley
> Delicious Monster
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list