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 
> <[email protected]> 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
> [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