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