Fundamental Design Patterns

Fundamental Design Patterns

https://developer.apple.com/library/mac/referencelibrary/GettingStarted/RoadMapOSX/books/StreamlineYourAppswithDesignPatterns/StreamlineYourApps/StreamlineYourApps.html

Use of the Model-View-Controller (MVC) design pattern ensures that the objects you create now can be reused or updated easily in future versions of your application. http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html#//apple_ref/doc/uid/TP40008195-CH32

The delegation design pattern allows you to change the runtime behavior of an object without subclassing. Delegation is a pattern where one object sends messages to another object—specified as its delegate—to ask for input or to notify the it that an event is occurring.
http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html#//apple_ref/doc/uid/TP40008195-CH14

Controls use the target-action design pattern to notify your application of user interactions. Target-Action is a design pattern in which an object holds the information necessary to send a message to another object when an event occurs.
http://developer.apple.com/library/mac/#documentation/General/Conceptual/Devpedia-CocoaApp/TargetAction.html#//apple_ref/doc/uid/TP40009071-CH3

Other Design Patterns
http://developer.apple.com/library/mac/#documentation/General/Conceptual/MOSXAppProgrammingGuide/CoreAppDesign/CoreAppDesign.html#//
apple_ref/doc/uid/TP40010543-CH3-SW1

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW6

The Launch Cycle

https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html

When your app is launched (either into the foreground or background), use your app delegate’s application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods.

At launch time, the system automatically loads your app’s main storyboard file and loads the initial view controller. For apps that support state restoration, the state restoration machinery restores your interface to its previous state between calls to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods.

 

Guide to Reference

ARC is a compile time feature that is Apple’s version of automated memory management. It stands for Automatic Reference Counting. This means that it only frees up memory for objects when there are zero strong references/ to them.

A guide to reference: when to use Strong reference, Weak reference, Unowned reference, ImplicitlyUnwrappedOptional property

  Optional non-Optional
Optional strong reference &

weak reference

 strong reference &

unowned reference

non-Optional strong reference &

unowned reference

 unowned reference &

implicitly unwrapped optional property

Extension

extension String {

func toFloat() -> Float {

if let unwrappedNum = Float(self) {

return unwrappedNum

}

else {

print(“Error converting \”” + self + “\” to Float”)

return 0.0

}

}

}

// Double to String with Format

var text = String.localizedStringWithFormat(“%.2f”, doubleValue)

// String to Float/Double

var floatValue = text.toFloat()

TemperatureConverter

// ConverterType
enum ConverterType : Int, CustomStringConvertible {
case FA_TO_CE = 1
case CE_TO_FA = 2
init(_ name: String) {
switch name {
case “FA_TO_CE”, “1”: self = .FA_TO_CE
case “CE_TO_FA”, “2”: self = .CE_TO_FA
default: self = .CE_TO_FA
}
}
var description: String {
switch self {
case .FA_TO_CE: return “FA_TO_CE”
case .CE_TO_FA: return “CE_TO_FA”
}
}
static func enumerate() -> AnyGenerator {
var nextIndex = FA_TO_CE.rawValue
return anyGenerator { ConverterType(rawVale: nextIndex++) }

}
}

// Converter
protocol Converter : CustomStringConvertible {
var description : String { get }
var type : ConverterType { get }
var fahrenheit : Double { get }
var celsius : Double { get }
}

// FahrenheitToCelsius
class FahrenheitToCelsius : Converter {
var temperature = 0.0

convenience init() {
self.init(temperature: 0.0)
}

init(temperature: Double) {
self.temperature = temperature
}

var description : String {
return “Converter=\(type.description) F=\(fahrenheit) => C=\(celsius)”
}
var type : ConverterType {
return ConverterType.FA_TO_CE
}

var fahrenheit : Double {
return self.temperature
}

var celsius : Double {
return (temperature – 32.0) * (5.0 / 9.0)
}
}

// CelsiusToFahrenheit
class CelsiusToFahrenheit : Converter {
var temperature = 0.0

convenience init() {
self.init(temperature: 0.0)
}

init(temperature: Double) {
self.temperature = temperature
}

var description : String {
return “Converter=\(type.description) C=\(celsius) => F=\(fahrenheit)”
}
var type : ConverterType {
return ConverterType.CE_TO_FA
}

var fahrenheit : Double {
return ((9.0/5.0) * temperature + 32.0)
}

var celsius : Double {
return self.temperature
}
}

// TemperatureConverter
class TemperatureConverter {

func getUserInputDouble() -> Double {
var value : Double
while true {
if let inputSeting = readLine() {
if let inputNumber = Double(inputString) {
value = inputNumber
return value
}
else {
print(“Error! Please re-enter Double value”)
}
}
}
}

func convert(mode: ConverterType) {
if (mode == ConverterType.FA_TO_CE) {
print(“Please enter temperature (F) : “)
let converter = FahrenheitToCelsius(temperature: getUserInputDouble())
print(converter.description)
}
else if (mode == ConverterType.CE_TO_FA) {
print(“Please enter temperature (C) : “)
let converter = CelsiusToFahrenheit(temperature: getUserInputDouble())
print(converter.description)
}
}

func getUserInputConverterType() -> ConverterType {
var i = 0
let g = ConvertType.FA_TO_CE
repeat {
print(“Please select converter type (1 or 2):”)
if let inputString = readLine() {
if let inputNumber = Int(inputString) {
i = inputNumber
if let c = ConverterType(rawValue: i) {
return c
}
}
}
} while i < 1 || i > 2
return g
}

func calculateAll() {
for i in 1…2 {
convert(ConverterType(rawValue: i)!)
}

for c in ConverterType.enumerate() {
convert(c)
}

var convertList = [Converter]()
convertList.append(FahrenheitToCelsius(temperature: 75.5))
convertList.append(CelsiusToFahrenheit(temperature: 25.5))
for c in convertList {
print(c.description)
}

convert(getUserInputConverterType())
}
}

DataStructureTest

//: Playground – noun: a place where people can play

// DataStructure (function, optional, enum, class, inheritance, struct)

// Kyoung Shin Park (2016 Fall)

import Cocoa

// function

func sayHello(personName: String = “World”) -> String {

let greeting = “Hello, ” + personName + “!”

return greeting

}

var delegate = sayHello()

print(sayHello())

print(sayHello(“Anna”))

print(delegate)

// Optional & Forced unwrapping & Optional binding

let planets = [“Mercury”:1, “Venus”:2, “Earth”:3] // assign dictionary

let planetID: Int? = planets[“Earth”]

if planetID != nil { // check if planetID is nil to prevent run-time error

print(“Earth = \(planetID!)”) // Forced unwrapping (using !) Earth = 3

} else {

print(“Earth is not found”)

}

// Optional binding (unwrapping an optional)

if let planetID = planets[“Earth”] { // return true if planetID has valid value

print(“Earth = \(planetID)”)       // Earth = 3

}

// ImplicitlyUnwrappedOptional

var w: Int! = 1 // same as var w: ImplicitlyUnwrappedOptional<Int> = 1

print(w) // you don’t need to put !

var z: Int! // same as var z: ImplicitlyUnwrappedOptional<Int> = nil

//print(z) // RUN-TIME ERROR (because z is nil)

w = nil // OK

//print(w) // RUN-TIME ERROR (because w is nil) while unwrapping

// Nil coalescing operator

let defaultColorName = “Red”

var userDefinedColorName: String? // set to nil

// colorNameToUse = “Red” (because userDefinedColorName = nil)

var colorNameToUse = userDefinedColorName ?? defaultColorName

// if planets[“Earth”] = nil then it will return the default value 0)

var ID : Int? = planets[“Earth”] ?? 0 // var earthID: Int? = 3

// Optional chaining

class Person {

var contact: Contact? // automatically set to nil

}

class Contact {

var address: String? // automatically set to nil

var telephone: String? // automatically set to nil

}

let p = Person()

//var phone = p.contact!.telephone! // run-time error(because contact=nil)

if let contact = p.contact { // optional binding to read optional property

if let phone = contact.telephone {

print(phone)

} else {

print(“phone is nil”)

}

} else {

print(“contact is nil”)

}

// optional chaining

var phone = p.contact?.telephone // phone=nil (because contact=nil)

print(phone)

// use optional chaining & optional binding together

p.contact = Contact()

p.contact?.telephone = “12345”

if let phone = p.contact?.telephone {

print(p.contact?.telephone)

}

// Enumeration

enum Gender {

case Female

case Male

init() { // initialization

self = .Female

}

init(_ name: String)

{

switch name {

case “Female”, “여자”: self = .Female

case “Male”, “남자”: self = .Male

default: self = .Female

}

}

var description: String {

switch self {

case .Female: return “FEMALE~”

case .Male: return “MALE~”

}

}

}

var gender = Gender()

print(gender.description)

gender = Gender(“남자”)

print(gender.description)

gender = Gender.Female

gender = .Male

print(Gender.Male.description)

switch gender {

case .Female: print(“FEMALE!!”)

case .Male: print(“MALE!!”)

}

// Enum, multiple member values can appear on a single line, separated by commas

// Enum rawValue

enum Planet: Int {

case Mercury=1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune

}

let earthID = Planet.Earth.rawValue

let somePlanet = Planet.Earth

switch somePlanet {

case .Earth:

print(“Mostly harmless”)

default:

print(“Not a safe place for humans”)

}

let aPlanet = Planet(rawValue: 7)

switch aPlanet! {

case .Earth:

print(“Mostly harmless”)

default:

print(“Not a safe place for humans”)

}

if let possiblePlanet = Planet(rawValue: 9) {

switch possiblePlanet {

case .Earth:

print(“Mostly harmless”)

default:

print(“Not a safe place for humans”)

}

} else {

print(“There isn’t a planet at position 9”)

}

// Enum associated values

enum TrainStatus {

case OnTime

case Delayed(Int)

}

var status:TrainStatus = .Delayed(5)

status = .OnTime

switch status {

case .OnTime:

print(“Train is on time”)

case .Delayed(let minutes):

print(“Train is delayed by \(minutes) minutes”)

}

// class

class Vehicle {

// stored properties

var numberOfPassengers: Int = 2

var numberOfWheels: Int = 4

 

// computed properties

var NumberOfWheels: Int {

get { return numberOfWheels }

set { numberOfWheels = newValue }

}

var description: String {

return “\(numberOfWheels) number of wheels”

}

}

class Bicycle: Vehicle {

override init() {

super.init()

numberOfPassengers = 1

numberOfWheels = 2

}

}

class Car: Vehicle {

// stored properties

var minVelocity: Int = 30

var accelVelocity: Int = 10

// computed properties

var speed: Int {

get {

return minVelocity + accelVelocity

}

set(newVelocity) {

accelVelocity = newVelocity – minVelocity

}

}

}

// struct

struct Frame {

var x: Int, y: Int // stored property

var width: Int, height: Int // stored property

var area: Int { // computed property (don’t need to enclose getter)

return width * height

}

mutating func addWidth(width: Int) {// method

self.width += width // mutating modifies the value of a stored property

}

}

let f = Frame(x: 5, y: 10, width: 100, height: 100) // member-wise initializer

//f.width = 250 // invalid (can’t change the struct properties stored in a let)

var g = Frame(x: 5, y: 10, width: 100, height: 100)

g.addWidth(15) // use mutating func to modify the value of a stored property

print(g.width) // 15

let h = Frame(x: 5, y: 10, width: 100, height: 100)

//h.addWidth(15) // compile error (can’t call mutating func of struct stored in a let)

EnumTest

//: Playground – noun: a place where people can play

// Swift EnumType (enum)

// Kyoung Shin Park (2016 Fall)

import Cocoa

import Foundation

// enum

enum Geometry : Int, CustomStringConvertible {

case Sphere = 1

case Cone

case Cylinder

case RectangularPrism

case SquarePyramid

case IsoscelesTriangularPrism

 

init(_ name: String)

{

switch name {

case “Sphere”, “구”, “1”: self = .Sphere

case “Cone”, “원뿔”, “2”: self = .Cone

case “Cylinder”, “원기둥”, “3”: self = .Cylinder

case “RectangularPrism”, “사각기둥”, “4”: self = .RectangularPrism

case “SquarePyramid”, “정사각뿔”, “5”: self = .SquarePyramid

case “IsoscelesTriangularPrism”, “이등변삼각기둥”, “6”: self = .IsoscelesTriangularPrism

default: self = .Sphere

}

}

var description: String {

switch self {

case .Sphere: return “Sphere”

case .Cone: return “Cone”

case .Cylinder: return “Cylinder”

case .RectangularPrism: return “RectangularPrism”

case .SquarePyramid: return “SquarePyramid”

case .IsoscelesTriangularPrism: return “IsoscelesTriangularPrism”

}

}

static func getGeometryBy(index : Int) -> Geometry? {

switch index {

case 1: return .Sphere

case 2: return .Cone

case 3: return .Cylinder

case 4: return .RectangularPrism

case 5: return .SquarePyramid

case 6: return .IsoscelesTriangularPrism

default: return nil

}

}

// use anyGenerator to get a generator that can enumerate across your values

static func enumerate() -> AnyGenerator<Geometry> {

var nextIndex = Sphere.rawValue

return anyGenerator { Geometry(rawValue: nextIndex++) }

}

}

for geo in Geometry.enumerate() {

print(geo.description)

}

var geo = Geometry(“1”)

print(geo.description)

geo = Geometry(“원뿔”)

print(geo.description)

geo = Geometry(“Cylinder”)

print(geo.description)

geo = Geometry.RectangularPrism

print(geo.description)

geo = .SquarePyramid

print(geo.description)

if let g = Geometry.getGeometryBy(6) {

print(g.description)

}

 

ArrayDictionaryTest

// Array & Dictionary: Playground – noun: a place where people can play

// Kyoung Shin Park (2016 Fall)

import UIKit

var a = Array<String>()

var b = [String]()

var c = [Int](count: 3, repeatedValue: 1)

let animals = [“Giraffe”, “Cow”, “Dog”, “Cat”]

//animals.append(“Bird”) // due to let

var animal = animals[1]

//var animal2 = animals[5] // due to out of bounds

for animal in animals {

print(animal)

}

for (index, value) in animals.enumerate() {

print(“animals[\(index)]=\(value)”)

}

b.append(“Egg”)

b += [“Cocoa”, “Milk”, “Flour”]

b[1…3] = [“Apple”, “Butter”]

print(b)

c.insert(4, atIndex: 1)

c.insertContentsOf([5,6], at: 2)

c.removeAtIndex(1)

c.removeRange(0..<2)

c.replaceRange(0…1, with: [8,9,7])

let sorted = c.sort { $0 < $1 }

for value in sorted {

print(value)

}

// map, filter, reduce

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var arr1 = arr.map { (x)->Int in return x+1 }

print(arr1)

var arr2 = arr.map { (x)->Int in return x*2 }

print(arr2)

var arr3 = arr.filter { (x)->Bool in return x%2 == 0 }

print(arr3)

var sum = arr.reduce(0, combine: { (result, x)->Int in return result+x } )

print(sum)

let sum2: Int = arr.reduce(0) { $0 + $1 }

print(sum2)

let stringified = arr.map { “\($0)” }

print(stringified)

// dictionary

var planets1 = Dictionary<String, Int>() //empty dictionary

var planets = [String: Int]() // empty dictionary

planets = [ “Mercury”:1, “Venus”:2

] // assign

planets[“Mars”] = 3 // append

for (key, value) in planets {

print(“\(key) = \(value)”)

}

planets[“Mars”] = 4 // replace

for (key, value) in planets {

print(“\(key) = \(value)”)

}

let earth = planets[“Earth”] // earth is an Int? (should be nil)

if earth == nil {

print(“Earth is not found”)

} else {

let earthID = earth! // use forced unwrapping !

print(“Earth = \(earthID)”)

}

planets[“Earth”] = 3 // append Earth

// optional binding

if let earthID = planets[“Earth”] {

print(“Earth = \(earthID)”)

}

ArrayTest

//: Playground – noun: a place where people can play

// Swift2 string, array

// Kyoung Shin Park (2016 Fall)

import UIKit

//string

let hello = “Hello”

let world = “World”

let smile = “?”

var h = hello + ” ” + world // “Hello World”

h += “, Swift” // “Hello World, Swift”

h.append(Character(“!”)) // “Hello World, Swift!”

var strH = h.stringByAppendingString(smile) // Hello World, Swift!

print(strH)

print(strH.uppercaseString)

var len = hello.characters.count // “Hello” 5

var len2 = hello.startIndex.distanceTo(hello.endIndex) // “Hello” 5

for s in hello.characters { // using foreach

print(“\(s)”)

}

for i in 0..<hello.characters.count { // using String.Index & range

print(“\(i): \(hello[hello.startIndex.advancedBy(i)])”)

}

for (index, value) in hello.characters.enumerate() { // using array & tuple

print(“\(index): \(value)”)

}

// array

func fillArray(inout arr: [Int]) {

    arr.appendContentsOf([1, 2, 3])

}

var myArray : [Int] = []

fillArray(&myArray)

print(myArray)

 

var a = Array<String>()

var b = [String]()

var c = [Int](count: 3, repeatedValue: 1)

var animals = [“Giraffe”, “Cow”, “Dog”, “Cat”]

animals.append(“Bird”)

var animal = animals[1]

for animal in animals { // using foreach

print(animal)

}

for i in 0..<animals.count { // using index & range

print(“animals[\(i)]=\(animals[i])”)

}

for (index, value) in animals.enumerate() { // using tuple & enumerate

print(“animals[\(index)]=\(value)”)

}

b.append(“Egg”)

print(b)

b += [“Cocoa”, “Milk”, “Flour”]

print(b)

b[1…3] = [“Apple”, “Butter”]

print(b)

c.insert(4, atIndex: 1)

print(c)

c.insertContentsOf([5,6], at: 2)

print(c)

c.removeAtIndex(1)

print(c)

c.removeRange(0..<2)

print(c)

c.replaceRange(0…1, with: [8,9,7])

print(c)

let sorted = c.sort { $0 < $1 }

for value in sorted {

print(value)

}

// http://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/

// collections – map, filter, reduce

let odd: [Int] = sorted.filter { $0 % 2 != 0}

print(odd)

let stringified: [String] = sorted.map { “\($0)” }

print(stringified)

let squares: [Int] = sorted.map { $0 * $0 }

print(squares)

let sum: Int = [1, 2, 3].reduce(0) { $0 + $1 } // adds up the numbers in the Array

print(sum)