Transcript

Standford 2015 iOS讀書會 week1

彼得潘

1. Logistics , iOS 8 Overview 2. More Xcode and Swift, MVC

彼得潘簡介

App程式設計⼊入⾨門:iPhone.iPad

Swift程式設計⼊入⾨門

相關教學資源http://www.facebook.com/iphone.peterpan

http://deeploveapple.blogspot.tw

[email protected]

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

email

mediumhttps://medium.com/@apppeterpan

http://swiftbook.strikingly.com

Developing iOS 8 Apps with Swift

從iPad的iTunes U App看體驗更好

甩掉Objective-C

https://medium.com/@apppeterpan/如果我是初學者-我該投⼊入swift的懷抱嗎-d1e5091a95c

貼⼼心的iOS⽀支援度和 Objective-C相容性

• 如果使⽤用Swift,iOS⾄至少要7以上 (97%以上的市佔)

• Swift & Objective-C: ⿂魚與熊掌可以兼得

• 同⼀一個App裡可以同時存在Swift & Objective-C的程式碼 (不同檔案)

• Swift可呼叫Objective-C的程式碼,Objective-C也可呼叫Swift的程式碼

⼆二分天下的iOS 7 & iOS 8

https://developer.apple.com/support/appstore/

課程先修條件1. 了解基本的程式概念

2. 了解物件導向class, instance, object, method, inheritance, instance variable。

if else, for, variable, function

Programming Paradigms參考課程:

Programming AbstractionsCS50

Xcode 6.3

搭配Swift 1.2

Standford Video以Xcode 6.1 & Swift 1.1為主

千鈞⼀一髮之際,補上Swift 1.2的新書

iOS的分層

成為⼀一代宗師的關鍵 Framework

Demo: 計算機App

計算機功能加減乘除和Enter

按Enter輸⼊入下⼀一個數字

按加減乘除,將前兩個數字做相加(減乘除)

ex: (1)12 (2)enter(2)3 (4) - -> 9

Storyboard:打造App畫⾯面

正⽅方形的iPhone ?不⽤用⼀一⾏行code,即可打造電⼦子書App上架

傳統frame⼤大法打造UI

數字不⾒見了!

變回正常⻑⾧長⽅方形的iPhone

auto layout

• 沒有加auto layout時,Xcode會依據我們排版的畫⾯面,⾃自動設定對應的條件。

• ⼀一旦為UI元件加了auto layout,就⼀一定要設定⾜足夠的條件。

auto layout

Trailing Space to Container Margin

右鍵 + 拉線

problem

紅線: 有衝突的條件 橘線: 條件不⾜足

2個constraint

label只要固定⼀一邊的⽔水平和垂直間距, 即可決定x, y的位置。 ⽽而label的size將由⽂文字內容⾃自動調整

demo: view則必須同時設定兩邊的⽔水平和垂直間距才能決定x, y & size

update frame

不影響實際的畫⾯面

完美的auto layout

藍線

demo模擬器轉向

demo: ⽐比較label設定2個和4個constraint的差異

超能⼒力preview

View Controllerimport UIKit

class ViewController: UIViewController {

}

import,method定義和繼承

IBOutlet: 連結storyboard的UI元件和程式

變數宣告

@IBOutlet weak var display: UILabel!

! : optional

類別的propertystored property

練功遊樂場 - Playground

Playground主畫⾯面

宣告變數

可變

var

忘了分號吧• var age = 18

• var age = 18;

分號可有可無既然如此,不如丟了吧!

Swift程式碼不需要利⽤用分號標⽰示結尾

國際化的Unicode名稱

對象: 變數名,類別名,function名,struct名,enum名

⽤用中⽂文寫程式⼩小朋友也可以寫程式了 !

⼤大眼睛Quick Look

以” ”表達字串

quick look⽀支援的type

⼤大⼩小寫有差

• Var number = 18

compile error

顯⽰示console

把console打開,即時發現錯誤

console

• 顯⽰示錯誤

• compile error

• runtime error ( crash)

• 列印訊息類似Objective-C的NSLog

⼀一步錯,步步錯的playground

由上⽽而下執⾏行,遇錯即中斷

不會執⾏行

demo: 從程式控制storyboard的UI元件

method定義

override func viewDidLoad() { super.viewDidLoad() }

畫⾯面載⼊入時執⾏行

類別的⽅方法

無參數的function

有參數的function

function參數的外部名和內部名 external name & internal name

#:⾃自動產⽣生同名的 external name

function的回傳值

return多個資料: 利⽤用tuple

IBAction: 連結storyboard的事件和程式

@IBAction func appendDigit(sender: UIButton) { }

顯⽰示程式和storyboard的 連結

copy paste⼤大法同樣有IBAction的連結 IBOutlet的連結則不會保留

選多個物件,⼀一次copy paste多個

定義appendDigit

@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle println("digit = \(digit)") }

始終如⼀一的常數(constant)

不可變,永遠18歲

let

variable & constant

• 為什麼要使⽤用限制重重的constant ?

• 使⽤用constant的好處:

• 安全

• 加快程式執⾏行速度

to var, or not to var, that is the question

Objective-C的variable & constant宣告

容易懶得宣告常數

查詢說明option加左鍵

tab⾃自動完成

console列印和字串罝換

@IBAction func appendDigit(sender: UIButton) { let digit = sender.currentTitle println("digit = \(digit)") }

奇怪的Optional

string interpolation (字串置換)

( )裡還可以做運算

type inference let digit = sender.currentTitle

沒有宣告型別

option加左鍵,查詢變數(常數)資訊

如柯南般的型別⾃自動推理(Type Inference)

推理型別為Int

推理型別為String

嚴格檢查型別

⼀一⽇日存Int,終⽣生存Int

明明⽩白⽩白地宣告型別

Swift的type名稱習慣字⾸首⼤大寫變數名習慣字⾸首⼩小寫

安全: 禁⽌止⾃自動型別轉換Swift

Objective-C

變成30

變數和常數 使⽤用前⼀一定要初始化

宣告變數時不能只宣告變數名稱

更安全 !

可有可無的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變數

讀取optional : !force-unwrap

force-unwrap on nilruntime error

判斷optional是否有值

若不是nil,if即成⽴立

可搭配if , while, for

1. 判斷optional是否有值 2. 若是optional有值即可放⼼心地利⽤用驚嘆號取值

⾮非optional不能和nil⽐比較

判斷並取值的 optional binding

Swift 1.2: 進化的optional binding

!: ⾃自動取值的 Implicitly Unwrapped Optionals

⽤用 ! 取代 ?

⾃自動unwrapped,不⽤用再透過 ! 取值

在nil⾃自動取值 -> Crash

不加!即取值,更容易crash

利⽤用if檢查

不需要optional binding

if else• ⼀一定要⽤用true / false判斷條件是否成⽴立

不能⽤用⾮非0做為true的判斷for , while也⼀一樣要⽤用true / false判斷條件是否成⽴立

if else• ⼀一定要添加 { }

即使只有⼀一⾏行

if else

Objective-C的if容易因忘了{ }鑄成⼤大錯

解包裝取值: !如果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 } }

enter

problem: ⼀一箭雙鵰

@IBAction func enter() { userInTheMiddleOfTypingNumber = false }

demo 連結到不存在的IBOutlet / IBAction 會crash

array var operandStack:Array<Double> = Array<Double>()

型別名稱 + ( )建⽴立資料

( )裡可傳⼊入參數

var operandStack = Array<Double>()

領取號碼牌乖乖排隊的array

可容納任何型別成員必須屬於同⼀一個型別

array的新增成員

array由struct定義

value type & reference type

struct定義的array

array的移除成員

新⼿手不能不懂的array招式

多維array

Array只能儲存Double

computed propertyvar displayValue: Double { get { return NSNumberFormatter().numberFromString(display.text!)!.doubleValue } set { display.text = "\(newValue)" userInTheMiddleOfTypingNumber = false } }

精於算計的 computed property

精於算計的 computed property

demo

@IBAction func enter() { userInTheMiddleOfTypingNumber = false operandStack.append(displayValue) println("operandStack = \(operandStack)") }

運算

@IBAction func operate(sender: UIButton) { }

⽅方法⼀一:定義同⼀一個⽅方法 ⽅方法⼆二:定義不同的⽅方法

cmd + /

快速多⾏行注解

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

switch• ⼀一定要包含所有case

switch• ⾃自動跳出,不需要break

switch• 繼續執⾏行下個case的fallthrough

ex: 60分或 80分“送糖果”

switch• ⼀一個case⽐比對多個條件

switch• 可⽐比對任何型別

Objective-C的switch只能⽐比對整數

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當參數

化⾝身參數的function

closure performOperation( (op1:Double, op2:Double) -> Double { return op1 * op2 })

performOperation( { (op1:Double, op2:Double) -> Double in return op1 * op2 })

closure

• like Objective-C’s block

• 無名的function

• function is a special case of closure: 有名

從function變形成closure的演化之旅

closure performOperation( { op1, op2 in return op1 * op2 })

省略參數和回傳型別

performOperation( { op1, op2 in op1 * op2 })

只有⼀一⾏行,省略return

closure performOperation( { $0 * $1 })

省略參數

performOperation(){ $0 * $1 }

當function參數是最後⼀一名時

closure

performOperation{ $0 * $1 }

function是唯⼀一的參數

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() } }

精簡

performOperation { sqrt($0) }

auto layout

Update Frame

Update Frame

Demo

Clear Constraint

MVC

MVC

閱讀作業

The Swift Programming Language

實作作業


Recommended