swift

Let | Var | Reference & Value Types

This is about as short a post as it can get! For a deeper look at reference & value types in Swift, see my other post on the topic.

I see a lot of questions on SO that discuss mutability in Swift. Let's go over some basic points about mutable (and immutable) objects in Swift:

  1. Creating a let variable enforces immutability - that variable cannot point to a different piece of data. You cannot change the data at that memory adddress and you also can't point the variable to a different memory address. Say you have let a = 5 and let b = 8.
    You cannot then say a = b nor can you say a = 7.
  2. If you have a var variable, all that means is that your variable can be reassigned - that could mean that the value it points to changes or that you point it to a different memory address.
  3. Structs, enums and other Swift value types (primitives such as Int, Double, String, Array, Dictionary and Set) dispay deep copy semantics. This means that if two variable are pointing to the same memory location, changing the data of one won't change the data of the other. A deep copy of the changed variable will be made and it'll point to its own separate memory address. Each value type instance holds a unique reference to its data. The ability of values to point to the same memory address until they no longer have the same data is due to Swift's Copy-On-Write optimization.
    //Assume Student() is a struct that initializes a student with an age.
    let a = Student(25)
    let b = a
    print(a.age) //25
    print(b.age) //25
    a.age = 35
    print(a.age) //35
    print(b.age) //25
    • As you can see above, changing a property value for a won't cause a change in b. Additionally, both will point to the same memory address until we change a.age - then a deep copy is made, passed to b, and the two variables point to different places in memory
  4. With reference types (often classes) multiple instances can share a single copy of data (they can point to the same memory address). If we pass a class instance to a function, for example, we're actually passing in a reference to the memory address of the object.
    //Assume Student() is a class that initializes a student with an age.
    let a = Student(25)
    let b = a
    print(a.age) //25
    print(b.age) //25
    a.age = 35
    print(a.age) //35
    print(b.age) //35
    • Since we're dealing with reference types, a shallow copy is made, meaning both instances are pointing to the same memory address. A change to data in one will result in change to data in the other.
    • With reference types, it's easy to leave around many reference to an object. Changing data of one reference will change the rest, and this can result in unexpected behavior and leads to bugs. Immutable types are considered safer and can lead to more bug-free code.

Architecture - View and Navigation Logic Abstraction

Views

Aside from pulling out protocol code and putting it into its own file (as covered in my most recent post), we can also pull out view code to reduce the size of our VCs. 

In a typical VC, say we are putting view setup code into our "viewDidLoad" method - we may instantiate several UI components and add them as subviews here. You may choose to create other methods that customize the subclassed UI components when called (which we do from viewDidLoad), ending the customization with adding the component as a subview. This may include using Visual Formatting Language to implement AutoLayout in code. See below:

class BloatedVC: UIViewController {

  private let restaurantName = UILabel()

  private let restaurantImage = UIImageView()

  private let blankSpaceSeparator = UIView()


  override func viewDidLoad() {

  super.viewDidLoad()

  view.addSubview(restaurantName)

  view.addSubview(restaurantImage)

  view.addSubview(blankSpaceSeparator)

  // add a ton of constraint code here, along with other customization including fram  e sizing, color, animations, etc.

  }
}

Here's a thought - instead of putting this code into a VC, why not factor it out into a subclass of UIView? We can have all the same code in that subclass, literally the exact same code, but instead of putting it all in our VC, we just create an instance of that new class in our VC and say

class BloatedVC: UIViewController {

  private var viewObject: ExtractedVCViewCode?

  override func loadView() {
  if let abstractedView = viewObject {
  self.view = abstractedView
    }
  }
}

It's important to note that we set up our view in "loadView", not "viewDidLoad". This is called by a VC when its view is currently nil, so you can instantiate the abstracted view in there.

The code for the abstracted view looks almost identical to the original code we had in "viewDidLoad":

class ExtractedVCViewCode: UIView {

  private let restaurantName = UILabel()
  private let restaurantImage = UIImageView()
  private let blankSpaceSeparator = UIView()

  struct LayoutConstants {
    static let padding: CGFloat = 15.0
    //other constants here for use in autolayout
  }

  override init(frame: CGRect) {
    super.init(frame:frame)
    addSubview(restaurantName)
    addSubview(restaurantImage)
    addSubview(blankSpaceSeparator)

    // add a ton of constraint code here, along with other customization including g     frame sizing, color, animations, etc.
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }
}

Navigation

Another quick (and to some, perhaps insignificant) way to reduce the amount of code in a VC is by separating out navigation logic - if a cell is clicked, instantiate this VC, pass in this restaurant as the data being provided, and present VC. This won't work for you if you're using IB segues (I prefer writing everything in code for many reasons unless I have a very simple idea I want to quickly prototype). 

First, we have two view controllers - the first displays a list of restaurants, the second displays information for one specific restaurant. We'll leave out typical navigation code, as it will be handled by a third class that neither VC knows about (yay for abstraction). Here's the gist of things - VC #1 declares a protocol with a method that takes a restaurant object as an argument - we also declare a weak var delegate that is of that delegate type. In "didSelectRowAtIndexPath", we invoke that method and say "whoever is implementing our delegate method, go ahead and execute now, here's the restaurant object you'll be needing". That's ALL THE CODE we have for navigation in our first VC.

The third class, that "navigation event handler", is what conforms to the protocol (the code below refers to this class as the "DefaultCoordinator"). This class is what will act as our delegate and actually execute our navigation code. VC #2 doesn't do anything in terms of navigation - it just exists here. The flow of things is VC #1 -> call method in navigation event handler and pass it restaurant object -> navigation event handler creates instance of VC #2, passes restaurant object over to it and pushes it onto the nav stack. Let's check out the code: 

class Restaurant: NSObject {
    var restoName: String
    var restoPic: UIImageView
    
    init (name: String, picture: UIImageView) {
        self.restoName = name
        self.restoPic = picture
        super.init()
    }
}

protocol RestaurantTableViewControllerDelegate:class {
    func RestoTableViewDidSelectRestaurant(restaurant: Restaurant)
}

class RestaurantListVC: UITableViewController {
    weak var navigationDelegate: RestaurantTableViewControllerDelegate?
    private var restaurants = [Restaurant] ()
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let selectedResto = restaurants[indexPath.row]
        navigationDelegate?.RestoTableViewDidSelectRestaurant(selectedResto)
    }
}

class DefaultCoordinator: RestaurantTableViewControllerDelegate {
    weak var navigationController: UINavigationController?
    
    func RestoTableViewDidSelectRestaurant(restaurant: Restaurant) {
        let VC = SingleRestaurantVC (restaurant: restaurant)
        navigationController?.pushViewController(VC, animated: true)
    }
}

class SingleRestaurantVC: UITableViewController {
    private var singleRestaurant: Restaurant?
    
    init (restaurant: Restaurant) {
        self.singleRestaurant = restaurant
        super.init(style: .Plain)
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

As you can see, the navigation code for the VC we are navigating away from is minimal. The DefaultCoordinator (which is acting as our navigation event handler) can conform to multiple protocols declared by multiple VCs - all navigation logic can be abstracted away and handled by the DefaultCoordinator. The (potential) downside is that once an app gets very complex with dozens of navigation options, it may be nicer to see the destination VC right there in the "from" VC (instead of tucked away in this coordinating class).

There are so many ways to reduce the amount of code in a VC - it's worth experimenting with. I find that it's easier for me to look at view controllers very conceptually instead of worrying about code involved - this lets me make up a sort of "map" in my head that allows for me to be more free-thinking in my architecture choices.

Reference and Value Types in Swift

References and Values in Theory

In Swift, a class is considered a reference type, plain and simple. This is similar to Objective-C, where everything that inherits from NSObject is a reference type. Being a reference type means that references share one single copy of data in memory, and they all refer to that same memory address. An issue with this involves the mutability of such an object - if somebody using a reference to Object A in a class changes some mutable values around, and I’m using Object A in a different class and I’m expecting a different value, we have a problem. 

Structs, enums and tuples are all value types in Swift (Objective-C also uses value types in number literals or C structs). If we say that:

let entree = Entree ()

let entree.protein = “Tofu”

let meal = entree

meal.protein = “Chicken”

Then entree.protein should ALSO have a value of “Chicken”. Both entree and meal reference the same object in memory, so changing the value of one changes the other. 

If we redefined the above as a struct, then the it would become a value type, and changing one would NOT change the other. Changing the protein value of meal wouldn’t change the protein value of entree.

It’s important to note that “let” as a constant keyword means different things for value and reference types - for reference types, let means that the reference must remain constant, but the properties are mutable. For value types, let means that the instance must remain constant, meaning that properties are immutable. 

Struct foo { var isReferenceType = False }

Class foo2 {var isReferenceType = True }

let exampleOne = foo ()

let exampleTwo = foo2 ()

// the below code WON’T work, since we are attempting to change the reference of a reference type

exampleTwo = foo

//the below code WILL work, since we are attempting to change a property value for a reference type

exampleTwo.isReferenceType = False

//the below code WON’T work, since we are attempting to change a property value for a value type

exampleOne.isReferenceType = True

 

To sum up, we can’t change the reference of a let constant if it’s a class, but we can change property values of that reference. We also can’t change property values of a let constant if it’s a struct. 


It’s important to note that Swift favors values almost exclusively. If you need to compare two struct instances for equality (assume we’re talking about value equality, not memory equality) then we need to conform to the Equatable protocol (this is something often required with value types). 

extension structName: Equatable { 

    func == (firstArgument: structName, secondArgument: structName) {

        return (firstArgument.value1 == secondArgument.value1) && (firstArgument.value2 == secondArgument.value2)

    }

}

To make data thread-safe, we would need to use a reference type (class) and implement locking. If you need to compare memory (physical) equality, then you should use a reference type. 

References and Values in Practice

Swift makes use of an optimization technique known as Copy-on-Write for value types - if you assign Object B = Object A, Swift will let both share a memory address even though they're value types. Object B will simply contain a reference to Object A. When the value of one changes, a copy is made, and the objects no longer share a memory address. In a cool optimization twist, if you later change one other object to match the other AGAIN, they'll once again share a memory address.

With some low-level Swift programming (of which there are a few resources about online, none of them actually any good), you can prove that copy-on-write exists - HOWEVER, it only seems to work for a few built-in types (such as arrays)! That's because if you want all that optimized goodness that comes from copy-on-write, you've got to implement it yourself for your custom value types. 

To learn about implementing it yourself, and how to build a Swift array from scratch, check out this article by Mike Ash. He runs an incredibly deep and advanced blog on Objective-C and Swift programming, and writes articles all the way down to the compiler level. Most of it is beyond me right now, but it's still good to glance at. 

You mix and match reference and value types all the time - remember that literals are value types, so whenever you have a a class variable that’s a string or a custom struct you created in a different file, your class is a reference type containing value types. This is common, and works out nicely. 

Things get tricky when you have a reference type contained within a value type. 

Let’s get something cleared up that’s related to the protocol-oriented nature of swift - value types should be equatable! This the expected behavior of a value type (as mentioned in a WWDC15 talk); if we have two integers (a value type in swift), don’t we expect to be able to compare their VALUES? I know I do. The same goes for strings, which, as a literal, are also equatable value types. 

Value types need to implement the == operator. The three properties of equality that must be addressed are that the comparison must be reflexive, symmetric and transitive

  1. To be reflexive, we must make sure that “x == x” returns true.
  2. To be symmetric, we must make sure that “x==y” and “y==x” return the same value, whether true or false.
  3. To be transitive, our == operator must make sure that is “a==b” is true, and “b==c” is true, then “a==c” must also be true. 

If your struct contains variables that are already literal value types, then you can declare the equatable function as a global function and simply compare the variables using the == operator. If your struct contains a struct, that nested struct should also conform to the equatable protocol in order to work your way up. It’s also convention to declare protocol adherence as an extension of the Type definition. 

Making reference types equatable is slightly different - it’s entirely case-specific. Say you have a “Person” class (a reference type) - it has a name variable. Two people can have the same name, but be different people. So how you implement whether or not they're equatable is up to you. 

Let’s return to a value type containing a reference type. We can have a struct be mutated very easily if it contains a reference type. There are ways around this, some better than others, which we’ll visit in a moment. Look at the screenshot below - we have two struct instances, one equal to the other (remember copy-on-write here). We change the value of a reference type variables of the first - desired behavior would be that since they’re both value types, changing data in one wouldn’t affect the other. Not so.

We've managed to mutate a struct by changing data in a different struct! This showcases their coupling based on the existence of a reference type in the struct definition.

We've managed to mutate a struct by changing data in a different struct! This showcases their coupling based on the existence of a reference type in the struct definition.

We can prevent this by forcing our Restaurant to use an explicit initializer - this actually creates a copy of the Person being passed in, instead of holding a reference to it. If we do this, and we pass in "managerTest" to be the manager, our Restaurant will use a COPY of the "managerTest" object. You can check the memory addresses and see that they're different. This means that mutating values of the "managerTest" object won't mutate the "manager" property of our Restaurant. Without this initializer, the two share a memory address, so mutating one mutates the other. The flaw in our design is when we act directly on "bestResto.manager.name" - there is nothing preventing this kind of mutation. 

We can mutate struct values here by just acting directly on the struct instance instead of the original reference type we used to create the "Manager".

We can mutate struct values here by just acting directly on the struct instance instead of the original reference type we used to create the "Manager".

The concept at hand here, a far cry from where we came, is data encapsulation. We've covered this in a previous post, but not with the complexity of a reference type contained within a value type. Let's start planning: a good solution would be to create setters and getters for the “manager” property of our Restaurant struct - get simply returns the current value, and set would create a copy of the manager and set the “manager” property to be equal to the new value. This way, if the data is changed, a deep copy of the reference type is created (vs a shallow copy, which creates a new object that simply points to the copied object...aka a referencing object). 

See any problems with this? I do. For one, we're creating a copy every single time the data is written to, instead of just mutating the existing copy. How can we say "If this object is currently referencing another object (shared resource) then make a deep copy with the changes. If nothing else is referencing this, just mutate the existing object instead of making a copy"? In comes "isUniquelyReferencedNonObjC", a method that detects the reference count of an object and returns a boolean value. You pass in the address of an object, it find other references to that object, and if there are no other references, it returns "True". Basically, if this returns "True" for our manager object, it has nothing else referencing it, and we can just mutate the existing copy. This raises a few questions that we'll address in a moment. 

Check out the code below - this is in a project. We have out VC code which creates two structs, the second equal to the first. We check the memory address of the MANAGER (which is a reference type), NOT the struct. We only implemented copy-on-write for the manager here - remember that custom structs don't implement copy-on-write automatically, so if we wanted that, we'd have to implement it ourselves. In this case, we just did it for the Person object. 

The managers share the same memory address - this is what we'd expect. After we change the manager object of the second restaurant object, the memory addresses are suddenly different! Our copy-on-write worked! The "withUnsafePointer" code is how we get the memory address of a struct. This is to prove that our struct doesn't implement copy-on-write (they have different addresses in memory from the very beginning, even though they have equivalent values). The other functions used to obtain memory addresses are just C functions that we're using in our Swift code.  

Memory address console prints to show copy-on-write in action

Memory address console prints to show copy-on-write in action

The last thing I'll add is a screenshot of my code for Restaurant - it changed since the last time we wrote it. The "manager" variable is now private, and we can only change it by using explicit APIs - this is to avoid developers accidentally changing the manager of a restaurant. If they want to change it, they call a clearly defined API that tells them exactly what they're doing so that any confusion is avoided. We get the current manager through a computed property "currentManager" and we implement copy-on-write in our "assignNewManager" function. The function is mutating since, if the manager object is uniquely referenced, we want to change it in place. Else, create a copy of the manager being passed in and assign it to our manager property. 

Encapsulated logic for creating a Restaurant struct

Encapsulated logic for creating a Restaurant struct

There's one more thing to talk about! What if we want to have two restaurants that share the same manager? This is a perfect representation of our situation - Restaurants are unique, and so should be value types. Managers can be the same person, and so CAN be references, but managers with the same name can ALSO be unique, and so CAN be value types (read - structs). Solution - it doesn't work here. We can create a new Restaurant object and pass in the Person we created as the manager, but our init method forces a copy to be made. We need to tinker with our init method and perhaps implement copy-on-write somewhere else in our code.

There are other edge cases to consider where our code WILL NOT WORK. I've been racking my brains for a few days here and there, trying to come up with an elegant solution that works. I'll keep working on it and I'll be sure to post here when I find a good solution.

That’s a ton to cover - we’ve reviewed lazy variables and working with constants, lazy sequences, reference and value types, equatable protocol implementation for value types, and discussed scenarios where you may WANT to have a reference type within a value type and how to write solid, defensive code in that situation. This was a long post, but definitely one of value. 

Being Lazy in Swift

Lazy Variables & Constants in Swift

Say you’re working on some application that has optional features - perhaps you have an image that CAN be resized if a thumbnail is required, but there is a chance that a thumbnail will never be viewed. Image scaling algorithms are computationally taxing - what if our user never ends up accessing a thumbnail? In that case, it doesn’t seem right to demand that a user ALWAYS wait for such an operation to be performed. Remember, allocation is slow, so defer until needed, and memory is limited, so don’t waste it. Use lazy instantiating when the initial value for a property isn’t known until after object initialization, when performing some intense algorithm or perhaps when calculating a large number (like pi to a large number of digits). 

In comes lazy loading - this is a technique used to defer instantiation of a variable or sequence (in swift) until it is actively needed. In swift, if you have a variable in a class that is part of the class’ designated initializer, the value must be computed since the compiler forces that every property within an initializer method be initialized. That may look something like this:

extension UIImage {

    fun resizedTo(size: CGSize) -> UIImage {

        // insert algorithm here    

    }

}

Class UserImage {

    static let smallSize = CGSize(width:36, height: 36)

    var thumbnail: UIImage

    var defaultImage: UIImage

    init (defaultImage: UIImage) {
        self.defaultImage = defaultImage

        self.thumbnail = defaultImage.resizedTo(UserImage.smallSize)

    }

}

What if we never need to use the thumbnail? We just performed an intensive operation for no reason at all - lazy variables take away this problem. In Objc we could leave the thumbnail out of the initializer and do a check for its value by making the thumbnail a computed property with set and get values. In the get, if the value is nil, THEN we would call our resizedTo method; in the set, simply give it a new value. We can immediately set a thumbnail value if we wish to, but if we end up attempting to access it without having initially set a value, it will call our resizing method. Thankfully, lazy instantiation with swift allows us to write less code while still achieving the same result.

The above can be achieved with just a single line of code- 

lazy var thumbnail: UIImage = self.defaultImage.resizedTo(UserImage.smallSize)

If we need to add more lines of code to compute our property, we can just use a closure - 

lazy var thumbnail: UIImage = { 

    let size = CGSize(

        width:min(UserImage.smallSize.width, self.defaultImage.size.width), 

        height: min(UserImage.smallSize.height, self.defaultImage.size.height)

    return self.defaultImage.resizedTo(size) 

} ()

The fact that a property is lazy means the value will only be computed when the entire class has been initialized, so it is safe to reference self within a computed lazy property. 

Note that let constants, if declared at global scope or as a type property (static let) are automatically lazy. Other than that, you can’t make them lazy. An interesting thing to note, as stated by Chris Lattner (designer and project leader of LLVM, Clang and Swift), is that “let” is about physical immutability, not logical immutability. Physical immutability means that once the bits are set in memory (when the let value is initialized), they can’t be changed.

Lazy Sequences in Swift

The SequenceType and CollectionType protocols in Swift have a computed property named lazy - it returns a LazySequence or LazyCollection, depending on which protocol we’re implementing. Lazy applies only to high-order functions in Swift (array.lazy.map(addOneFunction)). This code would only execute for values we actually need; if we printed (array[0], array[10], array[20]) and lazily mapped our function to those values, our program would only make three calculations, one for each value we try to access. If our array has 20,000 elements in it, we can use this to avoid calculating the values of each element after mapping a function to it, and limit our processing to just the values we want. 

Data Structures in Swift!

I recently added a README file to my GitHub repo to add a bit of clarity to anybody checking out the code. It includes sort and search algorithms and some basic data structures. I've covered linked lists previously on this blog, so the next few posts will be on the various algorithms I've implemented in Swift.

To finish up the series, I'll be doing a (possibly multi-part) post on Binary Search Trees - they're easily my favorite way to review recursion (or learn about it for the first time, if you're new to programming). I've written a BST in two ways - with a "node" data structure that is used to create a tree and without a node structure. The latter version uses itself as structure, meaning that each node is treated as an independent subtree. The logic is extremely different between the two, and although I would personally recommend writing a BST without a node structure, it's still good practice to review.

Swift Algorithms & Data Structures

The various files make use of Swifty features, all of which can be reviewed by looking at the README file on the repo. This includes preconditions, subscripting, extensions, sequencetypes and computed properties. Enjoy!

Swift Generics

Generic programming refers to the ability to write functions and data types that don’t specify a type. In this way, an algorithm or, say, a collection data type can have high reusability and specify a type when instantiated. For example, an array can hold many kinds of objects - it’s a generic data structure. When you want an array that specially holds objects of type Struct Gen, you can declare it (specifically in swift) as:

var genericArray = [Gen]()

You could also declare an empty array of integers as:

var intArray = [Int]() or, using explicit generic syntax, as var intArray = Array<Int>()

In this way, it’s clear that there is one array type, but we can specify what types the array can hold. You can almost treat a data type as a function, with a type being passed as an argument.

Arrays, Dictionaries, and Optionals are all generic types in swift and, as such, they can only hold one type - they are type-safe data structures. There are workarounds for this - say you want an array that holds both instances of Struct A and Struct B. You can declare the generic array to hold type <Any>, which will allow you to insert objects of different types in the same array. 

*Note : when using <Any>, be aware that the compiler won’t check whether a method exists or not when called on an object of type Any. All returns of an <Any> instance would be an optional value - a safe way to access an object of type Any would be to type cast it. 

You can also have different classes conform to the same protocol and declare a generic array that takes <protocol> objects. However, this can get tricky - imagine you have two separate structs and both conform to the same protocol. Struct A has a function named “testing” that takes an int and returns an int, while Struct B has a function of the same name that takes a string and returns a string. Say you randomly grab an object from your array, call the “testing” function on that object, and pass it an integer. If you grabbed an object typed as class B, you’d have a problem.

If you wanted to write a function that took a generic collection and returned the first element, regardless of the type, you could write something like this:

func firstFromCollection<T: CollectionType>(a:T) ->(T.Generator.Element)?{

    guard !a.isEmpty else {

        return nil

    }

       return a.first 

}

We can call it for arrays and strings like so:

 

print(firstFromCollection([1,2,3,4]))

print(firstFromCollection(“abc".characters))

 

Swift is a protocol-oriented language, and GeneratorType is a protocol used with collections; it is used for iterating over collection types. Typical "for in" loops actually use generators under the hood in swift. Take this time to read more about generators, lazy mapping functions, guards and collection types. 

Check out my github for swift code (heavily commented, of course) to implement a generic linked list. When you create an instance of the data structure, you specify the element type! Generic programming FTW! Link to code here

Pay attention to one particular function in the generic linked list:

func replaceItemAtIndex (position: Int, withValue value : T).

Notice the second argument has "withValue value:T" - the "withValue" is referred to as an external parameter name. This means that a user of the function will see "withValue" as an argument being passed, which is slightly more explicit and readable than just "value". Internally, we use "value" to define our function. Think about which you'd prefer to see - 

replaceItemAtIndex(position:Int, value:T) or replaceItemAtIndex(position:Int, withValue:T)

The latter simply reads more like English; this is just a personal preference, but coming from Objective-C, I'm a fan of this. 

NOTE - The code for my linked list includes a CustomStringProtocol extension which allows for me to print the contents of my list by using the "print" function as in print(linkedList). Before doing this, I had to write a custom print function. Additionally, I've made use of subscripts (including setters and getters). This allows for array and dictionary like access to elements, either to get the element or set it - this looks like linkedList[0] to get the head node or linkedList[0] = "New" to replace the head node. Internally, the subscript just calls my getItemAtIndex function and my replaceItemAtIndex function. This exercise was extremely helpful in my getting used to general swiftyness, utilizing some of the important changes to the language when moving over from Objective-C. 

Writing pure swift code allows me to focus on new syntax and architecture rather than the Cocoa Touch API's. Learning how to use a framework doesn't mean you know best practices of the language itself - it's important to develop good habits early.

 

EXTERNAL RESOURCE:

This link is for a group of slides from a meetup presentation at Google HQ I went to on advanced generics!