standford 2015 ios讀書會 week1: 1.logistics , ios 8 overview 2. more xcode and swift, mvc
TRANSCRIPT
相關教學資源http://www.facebook.com/iphone.peterpan
http://deeploveapple.blogspot.tw
https://github.com/AppPeterPan/It-s-all-about-App/wiki/It's-all-about-App
FB粉絲團
blog
iOS學習資源wik
i
http://deeploveiossdk.tumblr.com英⽂文wiki
mediumhttps://medium.com/@apppeterpan
http://swiftbook.strikingly.com
貼⼼心的iOS⽀支援度和 Objective-C相容性
• 如果使⽤用Swift,iOS⾄至少要7以上 (97%以上的市佔)
• Swift & Objective-C: ⿂魚與熊掌可以兼得
• 同⼀一個App裡可以同時存在Swift & Objective-C的程式碼 (不同檔案)
• Swift可呼叫Objective-C的程式碼,Objective-C也可呼叫Swift的程式碼
課程先修條件1. 了解基本的程式概念
2. 了解物件導向class, instance, object, method, inheritance, instance variable。
if else, for, variable, function
Programming Paradigms參考課程:
Programming AbstractionsCS50
2個constraint
label只要固定⼀一邊的⽔水平和垂直間距, 即可決定x, y的位置。 ⽽而label的size將由⽂文字內容⾃自動調整
demo: view則必須同時設定兩邊的⽔水平和垂直間距才能決定x, y & size
定義appendDigit
@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle println("digit = \(digit)") }
console列印和字串罝換
@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle println("digit = \(digit)") }
奇怪的Optional
optional• optional發明的緣由 (在Objective-C)
• 指到物件的變數可以設成nil代表無值 危險 -> 有些變數不該是nil
• 無物件變數不能設成nil,只能⾃自訂特定的value代表未設定的狀態
• 以-1表達容易誤解
• 修改需仔細檢查,⽐比⽅方改以-2表達未設定狀態
optional
optional預設初始為nil
• 可能有值,也可能沒有
• 無值: nil
• var age: Int?
• var age:Int? = nil
• type後加 ? ( 記得緊貼著,中間連⼀一個空⽩白都容不下)
• 任何type皆可nil,不像Objective-C只有物件可設為nil
只有optional會⾃自動初始 ⾮非optional不會⾃自動初始
var age1: Int?
var age2 = age1
optional預設初始為nil
⾮非optional不會⾃自動給初始值compile error沒有初始值,不能使⽤用
只有optional可有無值狀態
var number1: Int? = nil
var number2: Int = nil
var number3 = nilcompile error
依資料是否可能有無值狀態,決定是否設為optional
更安全
判斷optional是否有值
若不是nil,if即成⽴立
可搭配if , while, for
1. 判斷optional是否有值 2. 若是optional有值即可放⼼心地利⽤用驚嘆號取值
⾮非optional不能和nil⽐比較
解包裝取值: !如果optional是nil會crash
@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle! println("digit = \(digit)") }
解包裝後才能運算
@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle! display.text = display.text! + digit }
解法 var userInTheMiddleOfTypingNumber: Bool = false
⽅方法⼀一
⽅方法⼆二 var userInTheMiddleOfTypingNumber: Bool?
⽅方法三initializer
⾃自動初始為nil
判斷是否正在輸⼊入@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle! if userInTheMiddleOfTypingNumber { display.text = display.text! + digit } else { display.text = digit userInTheMiddleOfTypingNumber = true } }
!的optional⾃自動解包裝取值
@IBOutlet weak var display: UILabel! var userInTheMiddleOfTypingNumber: Bool = false @IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle! if userInTheMiddleOfTypingNumber { display.text = display.text! + digit } else { display.text = digit userInTheMiddleOfTypingNumber = true } }
implicitly unwrapped optional
適合IBOutlet, ⼀一開始和storyboard連結後,就會⼀一直有值
如果改成?的optional
@IBOutlet weak var display: UILabel? var userInTheMiddleOfTypingNumber: Bool = false @IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle! if userInTheMiddleOfTypingNumber { display!.text = display!.text! + digit } else { display!.text = digit userInTheMiddleOfTypingNumber = true } }
array var operandStack:Array<Double> = Array<Double>()
型別名稱 + ( )建⽴立資料
( )裡可傳⼊入參數
var operandStack = Array<Double>()
computed propertyvar displayValue: Double { get { return NSNumberFormatter().numberFromString(display.text!)!.doubleValue } set { display.text = "\(newValue)" userInTheMiddleOfTypingNumber = false } }
demo
@IBAction func enter() { userInTheMiddleOfTypingNumber = false operandStack.append(displayValue) println("operandStack = \(operandStack)") }
switch@IBAction func operate(sender: UIButton) { let operation = sender.currentTitle! if userInTheMiddleOfTypingNumber { enter() } switch operation { case "×": if operandStack.count >= 2 { displayValue = operandStack.removeLast() * operandStack.removeLast() enter() } case "÷": if operandStack.count >= 2 { displayValue = operandStack.removeLast() / operandStack.removeLast() enter() } case "+": if operandStack.count >= 2 { displayValue = operandStack.removeLast() + operandStack.removeLast() enter() } case "−": if operandStack.count >= 2 { displayValue = operandStack.removeLast() - operandStack.removeLast() enter() } default: break } }
沒有成員時,removeLast會crash
better code func performOperation(operation:(Double, Double) -> Double) { if operandStack.count >= 2 { displayValue = operation(operandStack.removeLast(), operandStack.removeLast() ) enter() } } func multiply(op1:Double, op2:Double) -> Double { return op1 * op2 } @IBAction func operate(sender: UIButton) { let operation = sender.currentTitle! if userInTheMiddleOfTypingNumber { enter() } switch operation { case "×": performOperation(multiply) default: break } }
function當參數
closure performOperation( (op1:Double, op2:Double) -> Double { return op1 * op2 })
performOperation( { (op1:Double, op2:Double) -> Double in return op1 * op2 })
closure performOperation( { op1, op2 in return op1 * op2 })
省略參數和回傳型別
performOperation( { op1, op2 in op1 * op2 })
只有⼀一⾏行,省略return
Best code @IBAction func operate(sender: UIButton) { let operation = sender.currentTitle! if userInTheMiddleOfTypingNumber { enter() } switch operation { case "×": performOperation{ $1 * $0 } case "÷": performOperation{ $1 / $0 } case "+": performOperation{ $1 + $0 } case "−": performOperation{ $1 - $0 } default: break } }
開根號 func performOperation2(operation:Double -> Double) { if operandStack.count >= 1 { displayValue = operation(operandStack.removeLast()) enter() } }
case "√": performOperation { op1 in sqrt(op1) }
Objective-C does not support method overloading, you have to use a different method name. When you inherited UIViewController you inherited NSObject and made the class interopable to Obj-C. Swift on the other hand supports overloading, that's why it works when you remove the inheritance
func performOperation(operation:Double -> Double) { if operandStack.count >= 1 { displayValue = operation(operandStack.removeLast()) enter() } } func performOperation(operation:(Double, Double) -> Double) { if operandStack.count >= 2 { displayValue = operation(operandStack.removeLast(), operandStack.removeLast() ) enter() } }