Skip to content

Instantly share code, notes, and snippets.

@JoshuaSullivan
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshuaSullivan/1aaee4e7af1555153eef to your computer and use it in GitHub Desktop.
Save JoshuaSullivan/1aaee4e7af1555153eef to your computer and use it in GitHub Desktop.
This is a Swift 2.0 Playground that demonstrates some use cases for lazy instantiation of object properties.
//: # Lazy Instantiation
//:
//: This playground demonstrates situations where lazily instantiating properties is valuable.
//: **NOTE:** This is a Swift 2.0 playground and must be opened in Xcode 7.
import UIKit
import CoreImage
//: A helper function to produce a random CGFloat in the range 0..<1
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UINT32_MAX)
}
class User : NSObject {
/// The user's name.
let name : String
/// A greeting for the user. Cannot be used until name has been set, so it's lazy.
lazy var greeting : String = {
// self must be unowned or it will create a retain cycle.
[unowned self] in
print("Generating greeting...")
return "Hello! My name is \(self.name)."
}()
/// A computationally intensive property. We don't want to calcualte this unless we have to!
lazy var avatar : UIImage = {
print ("Generating User avatar...")
// Create a couple of random colors.
let color0 = CIColor(red: randomCGFloat(), green: randomCGFloat(), blue: randomCGFloat())
let color1 = CIColor(red: randomCGFloat(), green: randomCGFloat(), blue: randomCGFloat())
// Create a CPU-driven rendering context.
let glContext = EAGLContext(API: EAGLRenderingAPI.OpenGLES2)
let ciContext = CIContext(EAGLContext: glContext)
// Create the basic checkerboard CIImage, guarding against failure.
guard let checkers = CIFilter(name: "CICheckerboardGenerator", withInputParameters: [
"inputColor0" : color0,
"inputColor1" : color1,
kCIInputWidthKey : randomCGFloat() * 100.0 + 20.0]
)?.outputImage else {
// This code executes when the filter creation fails.
print("ERROR: Unable to create checkerboard image.")
return UIImage()
}
// Rotate the image to add some additional visual interest.
let rotation = CGAffineTransformMakeRotation(randomCGFloat() * CGFloat(M_PI))
let rotatedCheckers = checkers.imageByApplyingTransform(rotation)
// Set up our drawing rectangle. The output size of the checkerboard is infinite, so we need to be explicit.
let drawRect = CGRectMake(0.0, 0.0, 200.0, 200.0)
// Create the output image. SWIFT BONUS: No need to manually release the returned CGImage!
let outputImage = ciContext.createCGImage(rotatedCheckers, fromRect: drawRect)
// Wrap the CGImage in a UIImage and return it.
return UIImage(CGImage: outputImage)
}()
/// A very simple initializer.
init(_ name: String) {
self.name = name
}
}
//: Create an unassuming User named "Bob".
let bob = User("Bob")
//: Accessing the property causes the creation closure to execute.
print(bob.greeting)
//: Note that you don't see the "Generating..." message a 2nd time.
print("Second take: \(bob.greeting)")
//: Accessing the property causes the creation closure to execute. Note that the print statement inside the
//: initialization closer occurs after the greeting on the previous line, proving that it didn't execute when the
//: Object was first initialized.
//:
//: Be sure to click the (+) button in the right gutter to see the actual image.
let avatarImage = bob.avatar
//: Again, note that the "Generating..." message only happens once.
let secondCopyOfAvatar = bob.avatar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment