How to use lazy initialization with getter/setter method? - ios

How i can use lazy initialization with get and set() closure.
Here is lazy initialization code:
lazy var pi: Double = {
// Calculations...
return resultOfCalculation
}()
and here is getter/setter code :
var pi: Double {
get {
//code to execute
return someValue
}
set(newValue) {
//code to execute
}
}

I assume what you're trying to do is lazily generate the default for a writable property. I often find that people jump to laziness when it isn't needed. Make sure this is really worth the trouble. This would only be worth it if the default value is rarely used, but fairly expensive to create. But if that's your situation, this is one way to do it.
lazy implements one very specific and fairly limited pattern that often is not what you want. (It's not clear at all that lazy was a valuable addition to the language given how it works, and there is active work in replacing it with a much more powerful and useful system of attributes.) When lazy isn't the tool you want, you just build your own. In your example, it would look like this:
private var _pi: Double?
var pi: Double {
get {
if let pi = _pi { return pi }
let result = // calculations....
_pi = result
return result
}
set { _pi = newValue }
}
This said, in most of the cases I've seen this come up, it's better to use a default value in init:
func computePi() -> Double {
// compute and return value
}
// This is global. Globals are lazy (in a thread-safe way) automatically.
let computedPi = computePi()
struct X {
let pi: Double // I'm assuming it was var only because it might be overridden
init(pi: Double = computedPi) {
self.pi = pi
}
}
Doing it this way only computes pi once in the whole program (rather than once per instance). And it lets us make pi "write-exactly-once" rather than mutable state. (That may or may not match your needs; if it really needs to be writable, then var.)
A similar default value approach can be used for objects that are expensive to construct (rather than static things that are expensive to compute) without needing a global.
struct X {
let pi: Double
init(pi: ExpensiveObject = ExpensiveObject()) {
self.pi = pi
}
}
But sometimes getters and setters are a better fit.

The point of a lazy variable is that it is not initialized until it is fetched, thus preventing its (possibly expensive) initializer from running until and unless the value of the variable is accessed.
Well, that's exactly what a getter for a calculated variable does too! It doesn't run until and unless it is called. Therefore, a getter for a calculated variable is lazy.
The question, on the whole, is thus meaningless. (The phrase "How i can use lazy initialization" reveals the flaw, since a calculated variable is never initialized — it is calculated!)

Related

What's the main difference between property observers and property wrappers?

What's the main difference between property observers and property wrappers? They seem to be very similar in that they manage how the properties are stored. The only thing I can think of is that you can reuse property wrappers since there is a layer of separation between code that manages how a property is stored and the code that defines a property.
Property Wrapper
#propertyWrapper
struct TwelveOrLess {
private var number: Int
init() { self.number = 0 }
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
struct Rectangle {
#TwelveOrLess var height: Int
#TwelveOrLess var width: Int
}
Property Observer
struct Rectangle {
var height: Int {
didSet {
if oldValue > 12 {
height = 12
} else {
height = oldValue
}
}
}
var width: Int {
didSet {
if oldValue > 12 {
width = 12
} else {
width = oldValue
}
}
}
}
The two cases above accomplish pretty much the same thing, which is to set the properties to be equal to or less than 12.
You say:
The only thing I can think of is that you can reuse property wrappers since there is a layer of separation between code that manages how a property is stored and the code that defines a property.
Your example (and some of your text) appears to be lifted from the Swift Programming Language: Property Wrapper manual:
A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property. For example, if you have properties that provide thread-safety checks or store their underlying data in a database, you have to write that code on every property. When you use a property wrapper, you write the management code once when you define the wrapper, and then reuse that management code by applying it to multiple properties.
So, yes, the virtue of the property wrapper is the reuse achieved by separating the “code that manages how a property is stored and the code that defines a property.” This resulting reuse is the whole m.o. of property wrappers.
You clearly, you can write your own setters and getters (which is better, IMHO, than a pattern of writing an observer that mutates itself), too, but you lose the reuse and abstraction that the property wrappers offer.
You go on to say:
The two cases above accomplish pretty much the same thing, which is to set the properties to be equal to or less than 12.
Sure, but if you want to do this for ten different properties, the wrapper avoids you from needing to repeat this code ten times. It also abstracts the details of this “equal to or less than 12” logic away from where you declare the property.
Another big difference betwixt property observers and property wrappers is that property observers can access self, whilst property wrappers cannot yet (as of this writing) access self using a stable, documented interface.
You can work around this limitation by manually passing self to the property wrapper in init. This workaround is described in the property wrapper proposal.
You can access self in a property wrapper using an undocumented, unstable interface which you can learn about by typing “property wrapper _enclosingInstance” into your favorite search engine.

how is it more efficient to use final/const instead of var?

final/const are nice to keep a variable's value from changing, but is it more efficient to use than using var to declare the variable? I wasn't able to find if i gain any efficiency by using final/const over using var.
Ok, let me try to explain.
class Foo {
var bar = 4;
function doSomething() {
return 3 + bar;
}
}
Must compute an addition everytime doSomething is called at runtime, because "bar" might change. If bar is final, the compiler can compute at compiletime. After all the remaining is something like:
class Foo {
// compiler erased "bar" and substituted any occurence by the value
function doSomething() {
return 7; // nothing to be computed at runtime
}
}
Note: most compilers detect a privat var as const, if it is never changed within its scope. But if the field is public, the compiler still won't know.

Passing argument to instance method to avoid retain cycle?

I've recently started profiling one of my iOS app written in swift and realized how annoying ARC is compared to other more adopted GC like Mark-And-Sweep.
One of the most prevalent causes for Strong Reference Cycle was retaining instance property within a closure that is passed to another object retained, again, by the class.
For example,
class MyClass {
private let text = "hello world"
private let anotherClass = AnotherClass()
init() {
addText()
}
private func addText() {
anotherClass.addText { return self.text }
}
}
Retain cycle like above can be avoided by passing argument to the method instead of accessing self directly.
class MyClass {
private let text = "hello world"
private let anotherClass = AnotherClass()
init() {
addText(text)
}
private func addText(text:String) {
anotherClass.addText { return text }
}
}
Is the second approach considered a good practice?
FYI, I'm aware that retain cycle like above can be broken using capture list. I'm just curious as to patterns that are more resilient to memory leaks.
Since the property let text ... is a constant, I think that the second approach is fine and can be considered a best practice.
But if you use the same approach with a var text ... property, then the behaviour changes:
in the first approach an execution of the closure will use the current value of text,
while in the second approach an execution of the closure will always use the original value of text.

initializing class properties before use in Swift/iOS

I'm having trouble grasping the proper way of instantiating variables that always need to be set before an object is fully functional but may need to be instantiated after the constructor. Based on Swift's other conventions and restrictions it seems like there is a design pattern I'm unaware of.
Here is my use case:
I have a class that inherits from UIViewController and will programmatically create views based on user actions
I need to attach these views to this class, but to do so I need to retrieve their content based on configuration data supplied by another controller
I don't care if this configuration data is passed to the constructor (in which case it would always be required) or supplied by a secondary call to this object before it is used
My problem seems to be that both of the approaches in bullet 3 seem flawed.
In the first case, there is only one legitimate constructor this class can be called with, yet I'm forced to override other constructors and initialize member variables with fake values even if the other constructors are never intended to be used (I'm also trying to keep these variables as let types based on Swift's best practices).
In the second case, I'm effectively splitting my constructor into two parts and introduce an additional point of failure in case the second part fails to be called prior to class being used. I also can't move this second part to a method that's guaranteed to be called prior to usage (such as viewDidLoad) because I still need to pass in additional arguments from the config. While I can make sure to call the initPartTwo manually, I'd prefer to have a mechanism that better groups it with the actual constructor. I can't be the first one to run into this and it seems like there is a pattern I'm not seeing to make this cleaner.
UPDATE:
I ended up going with a modified version of the pattern matt suggested:
struct Thing {
let item1: String
let item2: String
struct Config {
let item3: String
let item4: String
}
var config:Config! {
willSet {
if self.config != nil {
fatalError("tried to initialize config twice")
}
}
}
init() {
self.item1 = ...
self.item2 = ...
...
}
public func phaseTwoInit(item3: String, item4: String) {
self.item3 = item3
self.item4 = item4
...
}
}
var t = Thing()
...
t.phaseTwoInit(...)
...
// start using t
If an initial instance variable property value can't be supplied at object initialization time, the usual thing is to declare it as an Optional. That way it doesn't need to be initialized by the class's initializers (it has a value - it is nil automatically), plus your code subsequently can distinguished uninitialized (nil) from initialized (not nil).
If the Optional if an implicitly unwrapped Optional, this arrangement need have no particular effect on your code (i.e. it won't have to be peppered with unwrappings).
If your objection is that you are forced to open the door to multiple settings of this instance variable because now it must be declared with var, then close the door with a setter observer:
struct Thing {
var name:String! {
willSet {
if self.name != nil {
fatalError("tried to set name twice")
}
}
}
}
var t = Thing()
t.name = "Matt" // no problem
t.name = "Rumplestiltskin" // crash

Faulting or "lazy initialisation" pattern in Swift

I commonly use a "faulting" or lazy initialization pattern in iOS when dealing with big objects.
Whenever a class has a property pointing to a "fat" object, I create a custom getter that checks if the iVar is nil. If it is, it creates the fat object and returns it. If it isn't, it just returns the "fat" object.
The container of this property also subscribes to memory warnings, and when one is received, it sets the iVar to nil, reducing the memory footprint. As you see, it's pretty similar to faulting in Core Data.
I'm trying to reproduce this in Swift, but haven't found a decent and elegant solution so far.
a) First Attempt: lazy stored properties
This doesn't work, because if I set the property to nil, it will remain nil forever. The "magic" only happens the first time you access the property:
struct FatThing{
// I represent something big, which might have to be
// "faulted" (set to nil) when a memory warning
// is received
var bigThing = "I'm fat"
}
class Container {
lazy var fat: FatThing? = FatThing()
}
var c = Container()
c.fat
c.fat = nil
c.fat // returns nil
b) Second attempt: A stored property with observers
This also fails, because of the lack of get observers. I need a willGet and didGet, not just willSet and didSet.
Why on Earth are there no get obeservers? What's the use of this half backed thing called observers?
c) Third attempt: A computed property with a stored helper property
This is the only working option I've found so far, but it's as ugly as a baboon's rear end!
struct FatThing{
// I represent something big, which might have to be
// "faulted" (set to nil) when a memory warning
// is received
var bigThing = "I'm fat"
}
class Container {
private var _fat : FatThing? // having this extra and exposed var kills my inner child
var fat: FatThing? {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat
}
set{
_fat = newValue
}
}
}
var c = Container()
c.fat
c.fat = nil
c.fat // returns FatThing
So much for making my code look simpler and shorter...
Is there a simple and elegant way to implement this? This is no exotic stuff in a memory deprived environment as iOS!
The ability to override the getter or setter individually is a peculiarity of objective C that has no counterpart in swift.
The right option at your disposal is no. 3, using a backing property to store the fat data and a computed property to make it accessible. I agree that there's some boilerplate code, but that's the tradeoff for having what you need.
However, if you use that pattern frequently, then you can create a protocol:
protocol Instantiable {
init()
}
and implement it in your FatThing struct/class. Next, create a generic function containing the boilerplate code:
func lazyInitializer<T: Instantiable>(inout property: T?) -> T {
if property == nil {
property = T()
}
return property!
}
Note that T must implement Instantiable - that allows you to create an instance with a parameterless constructor.
Last, use it as follows:
private var _fat : FatThing? // having this extra and exposed var kills my inner child
var fat: FatThing? {
get { return lazyInitializer(&self._fat) }
set { _fat = newValue }
}
Note that in your code you don't have to declare the fat computer property as optional - you are ensuring in the get implementation that it is always not nil, so a better implementation is:
var fat: FatThing {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat!
}
set{
_fat = newValue
}
}

Resources