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

Charlie Monroe charlie at charliemonroe.net
Thu Jun 16 13:32:37 CDT 2016


Hard to say without full code, but the following code compiles just fine in Xcode 8:

class FloorPlatonicGeometryAndMaterial {
	init(modelDirectory: NSURL) throws {
		/// ...
	}
}

class PlatonicPieceOfFurniture {
	internal var modelDirectoryURL: URL
	
	var floorGeometryAndMaterial: FloorPlatonicGeometryAndMaterial {
		return self.floorGeometryAndMaterialBacking!
	}
	
	private lazy var floorGeometryAndMaterialBacking: FloorPlatonicGeometryAndMaterial? = 
				try! FloorPlatonicGeometryAndMaterial(modelDirectory: self.modelDirectoryURL)
	
	init(modelDirectoryURL: URL) {
		self.modelDirectoryURL = modelDirectoryURL
		/// ...
	}
}

All lazy initialization pretty much uses dispatch_once. Also remember, that your code can be as followed:

private lazy var stringValue: String? = {
	var str = self.description
	str += "\n"
	...
	return str
}()

lazy var initialization doesn't have to be a one-liner, but can be an applied closure.

> On Jun 16, 2016, at 7:48 PM, William Shipley via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160616/39b8ad42/attachment.html>


More information about the swift-evolution mailing list