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 
> <[email protected]>:
> 
> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to