Lecture 4 More Swift and Foundation Frameworks

Optional and enum

An optional is just an enum

Array, Dictionary<K, V>, Range

Array

Dictionary

Range

  • A Range is just two end points of a sensible type.
  • Range is generic. (Range)

  • An Array’s range would be a Range<Int>.

  • A String subrange is not Range<Int>. It is Range<String.Index>.

  • Syntax: either ... (inclusive) or ..< (exclusive)

Other classes

NSObject

  • Base class for all Objective-C classes.
  • Some advanced features will require you to subclass from NSObject (and it can’t hurt to do so).

NSNumber

Generic number-holding class

NSDate

NSData

A “bag of bits”.

Data Structures in Swift

  • Classes, structures and enumerations
  • They have similar declaration syntax. All of them can have properties and functions. Enums can only have computed properties. Enums store the value in an associated way, like optionals: some(value). They can have initializers.
  • Only class has inheritance, introspection, and casting.
    • Classes are reference type. Instances of class live in the heap, and managed by reference counting. On the other hand, structs and enums are passes by value.

Value (struct and enum)

  • Copied when passed as an argument to a function.
  • Copied when assigned to a different variable.
  • Immutable if assigned to a variable with let.
  • Function parameters are, by default, constant.
  • The keyword var on an parameter will make it mutable, but it’s still a copy.
  • Note any func that can mutate a struct/enum with the keyword mutating.

Reference (class)

  • Stored in the heap and reference counted (automatically).
  • Constant pointers to a class (let) still can mutate by calling methods and changing properties.
  • When passes as an argument, does not make a copy (just passing a pointer to same instance).

Choosing which to use

  • 90% of the time use class
  • structs and enums are mostly used for creating fundamental types, such as Double, Array and Dictionary.

Methods

  • Precede funs and vars with the keyword override to override the functions and variables in the superclass.
  • A method can be marked final which will prevent subclasses from being able to override.
  • Classes can also be marked final.
  • Both types and instances can have methods and properties

  • isSignMinus is an instance property of a Double

  • abs() is a type method of Double.

  • type method declaration

Parameters Names

  • All parameters to all functions have an internal name and an external name.
  • The internal name is the name of the local variable you use inside the method.
  • The external name is what callers will use to call the method.

  • Put _ if callers are not allowed to use an external name at all for a given parameter.

  • An _ is the default for the first parameter (only) in a method (but not for init methods)

  • Add # to force the first parameter’s external name to be the internal name.

  • For other (not the first) parameters, the internal name is, by default, the external name.

  • Any parameter’s external name can be changed.

  • Or even omitted (though this would be sort of “anti-Swift”)

Properties

Property Observers

  • Observe changes to any property with willSet and didSet

  • One very common thing to do in an observer in a controller is to update the user-interface

Lazy Initialization

  • A lazy property does not get initialized until someone accesses it.
  • You can allocate an object, execute a closure, or call a method if you want

  • Constants (such as let) can’t be initialized lazily.

  • This can be used to get around some initialization dependency conundrums.

Initialization

When is an init method needed?

  • init methods are not so common because properties can have their defaults set using =.
  • Or properties might be Optionals, in which case they start out nil.
  • You can also initialize a property by executing a closure.
  • Or use lazy instantiation.
  • So you only need init when a value can’t be set in any of these ways.

You also get some “free” init methods

  • If all properties in a base class (no superclass) have defaults, you get init() for free.
  • If a `struct has no initializers, it will get a default one with all parameters as arguments

What can you do inside an init?

  • You can set any property’s value, even those with default values.
  • Constant properties (i.e. properties declared with let) can be set.
  • You can call other init methods in your own class using self.init(<args>).
  • In a class, you can call super.init(<args>).

What are you required to do inside init?

  • By the time any init() is done, all properties must have values (optionals can have value nil).
  • There are two types of init in a class, convenience and designated.
  • A designated init must and can only call a designated init that is in its immediate superclass.
  • You must initialize all properties introduced by your class before calling a superclass’s init.
  • You must call a superclass’s init before you assign a value to an inherited property.
  • A convenience init must (and can only) call a designated init in its own class.
  • A convenience init may call a designated init indirectly (through another convenience init).
  • A convenience init must call a designated init before it can set any property values.
  • The calling of other inits must be complete before you can access properties or invoke methods.

Inheriting init

  • If you do not implement any designated inits, you’ll inherit all of your superclass’s designated.
  • If you override all of your superclass’s designated inits, you’ll inherit all its convenience inits.
  • If you implement no inits, you’ll inherit all your superclass’s inits.

Required init

  • A class can mark one or more of its init methods as required.
  • Any subclass must implement said init methods.

Failable init

  • If an init is declared with a ? (or!) after the word init, it returns an Optional

  • These are rare.

  • You’ll be able to tell because the compiler will warn you about the type when you access it.

Creating Objects

AnyObject, introspection and casting

Special “Type” (actually it’s a Protocol)

Used primarily for compatibility with existing Objective-C based APIs.

Where will you see it?

  • Just a pointer to an unknown class
  • As properties (either singularly or as an array of them)

  • As arguments to functions

  • Return types from functions

How do we use AnyObject?

Don’t use it directly. Instead, convert it to another known type

Casting AnyObject

  • We “force” an AnyObject to be something else by “casting” it using the as keyword.

  • To protect against a crash, we can use if let with as?

  • as? returns an Optional

  • We can check before we try to do as with is keyword

Casting Arrays of AnyObject

  • Cast each elements of the array

  • Case the entire array

  • Can’t do as? here because then it might be for toolbarItem in nil, which makes no sense.

Helpful Methods and Functions

Some Array<T> Methods

String

String.Index

Type Conversion

Conversion between types with init()

A sort of “hidden” way to convert between types is to create a new object by converting.

Assertions

Debugging Aid

  • Intentionally crash your program if some condition is not true.
  • The function argument is an “autoclosure”, so you don’t need the {}

Other Functions

Functions that work on Array, Dictionary, String

String vs. NSString, Array vs. NSArray, Dictionary vs. NSDictionary

Property List

NSUserDefaults

Leave a Reply

Your email address will not be published. Required fields are marked *