owned this note
owned this note
Published
Linked with GitHub
###### tags: `App Developer行動開發工程師養成班`
Swift語法基礎
===
### 9X9(一行) 使用while用法
```swift=
var mt : Int
var chenSue : Int //乘數
var product : Int // 積
mt = 1 // 被乘數
chenSue = 1
while chenSue <= 9
{
product = mt * chenSue
print( "(\(mt)*\(chenSue)=" , terminator:"")
if product < 10
{
print("0", terminator:"")
}
print("\(product))" , terminator:"")
chenSue += 1
}
```
```
(1*1=01)(1*2=02)(1*3=03)(1*4=04)(1*5=05)(1*6=06)(1*7=07)(1*8=08)(1*9=09)
```
### 9X9(一行) 使用 for...in「stride」(from..through/to..by)用法
##### 「stride」 代表 決定 for in 語法的數字範圍
##### 「from」 代表 開始的數字
##### 「through」代表 結束的數字 ,through 的數字將被包含
##### 「to」代表 結束的數字, to 的數字將不被包含
```swift=
for cs in stride(from: 1, through: 9, by: 1) {
let mt = 7
let product = mt * cs
print("(\(mt)X\(cs)=\( product<10 ? "0":"")\(product))" , terminator:"")
}
print()
```
```
7X1=07)(7X2=14)(7X3=21)(7X4=28)(7X5=35)(7X6=42)(7X7=49)(7X8=56)(7X9=63)
```
### 9X9(一行) 使用dot.dot.dot與三元運算子用法
```swift=
// dot.dot.dot
for cs in 1...9 {
let mt = 5
let product = mt * cs
print("(\(mt)X\(cs)=\( product < 10 ? "0": "")\(product))" ,terminator: "")
}
print()
```
```
(5X1=05)(5X2=10)(5X3=15)(5X4=20)(5X5=25)(5X6=30)(5X7=35)(5X8=40)(5X9=45)
```
### 9X9(一行) 使用repeat...while用法
```swift=
var cs = 1
repeat {
let mt = 8
let product = mt * cs
print("(\(mt)X\(cs)=\( product < 10 ? "0": "")\(product))" ,terminator: "")
cs += 1
} while cs <= 9
print()
```
```
(8X1=08)(8X2=16)(8X3=24)(8X4=32)(8X5=40)(8X6=48)(8X7=56)(8X8=64)(8X9=72)
```
### 定義類別,並在主程式引用執行
```swift=
class func theWriteNineAline ( 被乘數 multiplicant : Int ) {
for chenShu in 1...9 {
let product = multiplicant * chenShu
print("(\(multiplicant)x\(chenShu)=", terminator: "" )
if product < 10 {
print("0", terminator: "" )
}
print("\(product))", terminator: "" )
}
}
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #1 如何改成執行時會印出 九九乘法
// fix 練習 #0 觀察執行會如何?
for cs in 1...9 {
ViewController.theWriteNineAline(被乘數: cs)
print()
}
}
```
### ternary 三元運算子
```swift=
var x = "unknown"
var p = 9
x = p < 10 ? "=0" : "0"
print(x)
print("p = 23")
p = 23
x = p < 10 ? "=0" : "0"
print(x)
```
```
=0
p = 23
0
```
### switch case 加上where,增加條件限制
```swift=
for x in 5...14 {
print("x 為 \(x)")
switch x {
case 7...13 where x % 2 == 1 :
print("為 7 或者 9 或者 11 或者 13")
print()
default :
print(" x 不等於 6 , 7 , 9 , 11 而且 也不等於 13")
print()
}
}
```
```
x 為 5
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
x 為 6
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
x 為 7
為 7 或者 9 或者 11 或者 13
x 為 8
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
x 為 9
為 7 或者 9 或者 11 或者 13
x 為 10
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
x 為 11
為 7 或者 9 或者 11 或者 13
x 為 12
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
x 為 13
為 7 或者 9 或者 11 或者 13
x 為 14
x 不等於 6 , 7 , 9 , 11 而且 也不等於 13
```
### 座標 switch case 不加上where用法
```swift=
var 座標 : ( x : Int , y : Int)
for cs in 0...3 {
座標.x = cs % 2 //取餘數
座標.y = cs / 2 //取整數
print("座標 為 (\(座標.x) , \(座標.y)) " )
switch 座標 {
case (0,0):
print("是原點")
case (0,_):
print("不是原點,但是在垂直軸上")
case (_,0):
print("不是原點,但是在水平軸上")
default:
print("不是原點,也不在垂直軸上,也不在水平軸上")
}
print("\n")
}
print()
```
```
座標 為 (0 , 0)
是原點
座標 為 (1 , 0)
不是原點,但是在水平軸上
座標 為 (0 , 1)
不是原點,但是在垂直軸上
座標 為 (1 , 1)
不是原點,也不在垂直軸上,也不在水平軸上
```
### 座標 switch case 加上「where」 用法
```swift=
for se in 0...3
{
座標.x = se % 2
座標.y = se / 2
print("座標 為 ( \( 座標.x ) , \( 座標.y ) )")
print()
// fix 練習 #1
// 觀察下面 switch 判斷語法
switch 座標 // 由上而下, ㄧㄧ比對
{
case ( 0 , _ ) where 座標.y != 0 :
print(" 落在垂直軸 而 y 等於 \(座標.y) , 但不是原點")
case ( _ , 0 ) where 座標.x != 0 :
print(" 落在水平軸 而 x 等於 \(座標.x) , 但不是原點")
case ( 0 , 0 ) :
print(" 是原點")
default :
print(" 座標 不是原點 而且 不在垂直軸 也不在水平軸")
print()
}
}
```
```
座標 為 ( 0 , 0 )
是原點
座標 為 ( 1 , 0 )
落在水平軸 而 x 等於 1 , 但不是原點
座標 為 ( 0 , 1 )
落在垂直軸 而 y 等於 1 , 但不是原點
座標 為 ( 1 , 1 )
座標 不是原點 而且 不在垂直軸 也不在水平軸
```
### while 與 break/ continue 的用法
```swift=
var x = 0
var y = 0
print ("B1002 rooom")
Nick :
while y < 9 {
x = 0
while x <= 4 {
x += 1
if x == 4 {
break //Nick//continue
}
print("\(x)" , terminator:" ")
}
print()
print(" y 是 \(y)" )
y += 1
}
print("MAPD35")
```
```
######break########
B1002 rooom
1 2 3
y 是 0
1 2 3
y 是 1
1 2 3
y 是 2
1 2 3
y 是 3
1 2 3
y 是 4
1 2 3
y 是 5
1 2 3
y 是 6
1 2 3
y 是 7
1 2 3
y 是 8
MAPD35
```
```
######break Nick 整個迴圈程式結束########
B1002 rooom
1 2 3 MAPD35
```
```
######continue########
B1002 rooom
1 2 3 5
y 是 0
1 2 3 5
y 是 1
1 2 3 5
y 是 2
1 2 3 5
y 是 3
1 2 3 5
y 是 4
1 2 3 5
y 是 5
1 2 3 5
y 是 6
1 2 3 5
y 是 7
1 2 3 5
y 是 8
MAPD35
```
### 型態方法
```swift=
// fix 練習 #0-1 觀察下面發明了ㄧ個 type method
// (翻譯成中文 為 型態方法)
// 此'型態方法'名稱為 theOdd
class func theOdd
(
// fix 練習 #0-2 觀察小括弧內為 參數宣告
// 此參數 名稱為 target 其型態為 Int 就是整數
// fix 練習 #0-6 觀察
// Int2detect 為此參數 target 的外部名稱
Int2detect target : Int) -> Bool
// fix 練習 #0-4 此方法的身體由 大括弧 { 開始
{
let 答案 : Bool
// fix 練習 #0-3 此名稱為 target 的參數
// 可在此方法的身體內被使用, 如下行 target % 2
let 餘數 : Int = target % 2
答案 = 餘數 == 1
return 答案
}// fix 練習 #0-5 此方法的身體在 大括弧 } 結束
override func viewDidLoad() {
super.viewDidLoad()
for 實際參數 in 2...5 {
let 是奇數 : Bool
// fix 練習 #0-7 觀察
// Int2detect 為此參數 target 的外部名稱
// '外部名稱' 可以讓呼叫這個method的程式設計師
// 比較能夠知道這個參數的意義.
// fix 練習 #0-8 觀察
// 讓呼叫這個 '型態方法' 的語法為 '型態名稱'.'型態方法名稱' (參數)
是奇數 = ViewController.theOdd ( Int2detect : 實際參數 )
print( "\(實際參數) 是 \( 是奇數==false ? "偶數" : "奇數" ) " )
}
print()
}
```
```
2 是 偶數
3 是 奇數
4 是 偶數
5 是 奇數
```
### 類型方法
```swift=
class 存款帳號 {
class func print利率()
{
// print("餘額 為 \(餘額)")
print("百分之 \"3.8\" ")
}
var 餘額 : Double = 100
func isVIP () -> Bool {
return 餘額 >= 10000000
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// print("新產品")
// 存款帳號.print利率()
var 郭昌明的帳戶 : 存款帳號 //宣告變數
郭昌明的帳戶 = 存款帳號() //指定參考值
var 是貴賓 = 郭昌明的帳戶.isVIP()
print("是貴賓 為 \(是貴賓)") // 執行class func
print("查完了")
郭昌明的帳戶.餘額 = 200000000
是貴賓 = 郭昌明的帳戶.isVIP()
print("是貴賓 為 \(是貴賓)")
print()
}
}
```
```
是貴賓 為 false
查完了
是貴賓 為 true
```
### 兩個問號 - ?? 如果某個變數可能是nil時,可以使用??來給予一個預設值
```swift=
print("MAPD35 在 B1002 教室" )
print("var pN : Int? = nil ")
// fix 練習 #0 觀察下行 pN 變數 的資料型態是 Int?
var pN : Int? = nil
// fix 練習 #1 您想寫出ㄧ個效果:
// 若 pN == nil 則 pN 存 0 的值, 否則不用改變 pN 所存的值
pN = pN ?? 0
// 看 pN 所存的 Int 的值
print( pN! )
print()
print("pN = -5 ")
pN = -5
pN = pN ?? 0
print( pN! )
print()
print()
print("var PS : Int? = nil ")
// fix 練習 #2 觀察下行 PS 變數 的資料型態是 Int!
var PS : Int! = nil
// fix 練習 #3 您想寫出ㄧ個效果:
// 若 PS == nil 則 PS 存 6 的值, 否則不用改變 PS 所存的值
PS = PS ?? 6
// 看 PS 所存的 Int 的值 加 200 的和
print( PS + 200 )
print()
PS = -300
PS = PS ?? 6 //沒有取6的值了,抓到-300
print( PS + 200 )
```
```
MAPD35 在 B1002 教室
var pN : Int? = nil
0
pN = -5
-5
var PS : Int? = nil
206
-100
```
### 變數指派預設值,如果有再指派新的值,會以新的執行結果
```swift=
// fix 練習 #0 以下程式碼是要做出數學分數的相關教學App
var son0 : Int = 2//這代表一個分數(我們姑且叫做分數 A )的分子
var mom0 : Int = 5//這代表一個分數(我們姑且叫做分數 A )的分母
son0 = 3
mom0 = 11
// 印出一個分數(我們姑且叫做分數 A )的表示式: 分子/分母
print("A 為 \( son0 )/\( mom0 )" )
var son1 :Int = 2// 這代表另一個分數(我們姑且叫做分數 B )的分子
var mom1 :Int = 5// 這代表另一個分數(我們姑且叫做分數 B )的分母
son1 = 13
mom1 = 7
// 印出另一個分數(我們姑且叫做分數 B )的表示式:
// 分數B的分子/分數B的分母
print("B 為 \( son1 )/\( mom1 )" )
```
```
A 為 3/11
B 為 13/7
```
### 字典dictionary
```swift=
var sz : Int
// fix 練習 #0 觀察下行 [ String : Int ] 為 字典 型態
// 字典: 為擁有「鍵」 搭配「值」 的成對組 存在其中的容器
// key(翻譯成 鍵 ) 的資料型態為 String
// value(翻譯成 值 ) 的資料型態為 Int
// 下行 [ : ] 代表空的字典, 也就是 「鍵」 搭配 「值」的成對組 , 連 1 組 都沒有
var dk : [ String : Int ] = [ : ]
// count 代表 字典有幾對(或是幾組) key value 配對
sz = dk.count
print(" dk.count 為 \(dk.count)")
// 下行 dk ["ktm"] 代表 想以鍵是 "ktm" 查出搭配 的值
// , 值的型態是 Int 整數, 但須注意不ㄧ定有這樣的成對組
// , 字典目前有 0 對
// , 用 dk ["ktm"] 語法, 不ㄧ定可查出任何值
// , 所以 dk ["ktm"] 是 Int? 資料型態
let pv : Int? = dk ["ktm"]
if let vu : Int = pv {
print(" vu 為 \(vu)")
} else {
print(" dk [\"ktm\"] == nil 為 \( dk ["ktm"] == nil )")
}
// 下行 代表 鍵是 "ktm" 搭配 值是 9 的成對組
dk ["ktm"] = 9
print( " dk [\"ktm\"] = 9 " )
print( " dk.count 為 \(dk.count)")
if let vu = dk ["ktm"] {
print(" vu 為 \(vu)")
} else {
print(" dk [\"ktm\"] == nil 為 \( dk ["ktm"] == nil )")
}
// 下行 代表 鍵是 "ktm" 搭配 值是 28 的成對組
dk ["ktm"] = 28
print( " dk [\"ktm\"] = 28 " )
print( " dk.count 為 \(dk.count)")
if let vu = dk ["ktm"] {
print(" vu 為 \(vu)")
} else {
print(" dk [\"ktm\"] == nil 為 \( dk ["ktm"] == nil )")
}
// 下行 代表要從字典移除 鍵是 "ktm" 搭配的值 的成對組
dk.removeValue(forKey: "ktm")
print( " dk [\"ktm\"] = 28 " )
print( " dk.count 為 \(dk.count)")
if let vu = dk ["ktm"] {
print(" vu 為 \(vu)")
} else {
print(" dk [\"ktm\"] == nil 為 \( dk ["ktm"] == nil )")
}
dk["ktm"]=9
dk["honda"]=3
dk["suzuki"]=2
dk["yamaha"]=1
dk["husquana"]=1
//鍵搭配值算ㄧ對,下面範例k 為鍵, v為值
for (k,v) in dk {
print( "k 為 \(k) 配的值 為 \(v)")
}
```
```
dk.count 為 0
dk ["ktm"] == nil 為 true
dk ["ktm"] = 9
dk.count 為 1
vu 為 9
dk ["ktm"] = 28
dk.count 為 1
vu 為 28
dk ["ktm"] = 28
dk.count 為 0
dk ["ktm"] == nil 為 true
k 為 ktm 配的值 為 9
k 為 suzuki 配的值 為 2
k 為 honda 配的值 為 3
k 為 yamaha 配的值 為 1
k 為 husquana 配的值 為 1
```
### 建立 「fetch」method 回傳更新數值
```swift=
class Myadt
{
var son : Int = 1
var mom : Int = 2
func fetch ( ) -> String
{
var answer : String
answer = "\(son)/\(mom)"
return answer
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var R0 : Myadt!
print("var R0 : Myadt!")
// fix 練習 #1 這語法 Myadt ( ) 代表產生一個分數(我們姑且叫做分數 A )
// 應該還要多寫點, 才能解決 fix #0 下面那ㄧ行錯誤的問題
R0 = Myadt()
// fix 練習 #0 下行程式執行會不會有問題
R0.son = 17 //分數 A 的分子 設成 17
print("R0.son = 17")
// fix 練習 #2 在下行寫點程式, 能分數 A 的分母 設成 23
R0.mom = 23
var msg : String = "1/1"
print(" R0 為 ")
/* 此實例方法 fetch( ) 產生一個分數A的表示式 "17/23" 被傳回來 */
msg = R0.fetch()
print( "\( msg )" )
// 比較ㄧ下: 沒用 object-oriented 物件導向 的理念來開發如下
// 印出一個分數(我們姑且叫做分數 A )的表示式: 分子/分母
// var son0 : Int = 17
// var mom0 : Int = 23
// print("A 為 \( son0 )/\( mom0 )" )
print("var R1 : Myadt!")
var R1 : Myadt!
R1 = Myadt ( ) /* 這代表一個分數(我們姑且叫做分數 B ) */
R1.son = 29
R1.mom = 19
print( "\( R1.fetch( ) )" ) // “29/19"
}
}
```
```
var R0 : Myadt!
R0.son = 17
R0 為
17/23
var R1 : Myadt!
29/19
```
### 定義類別方法 reference值
```swift=
class B {
var married : Bool = false
func Ido () {
married = true
}
func Divorce () {
married = false
}
}
class ViewController: UIViewController {
func kp ( _ _b : B ) {
_b.Divorce()
}
override func viewDidLoad() {
super.viewDidLoad()
let bb : B = B()
bb.Ido()
print( bb.married )
kp( bb )
print( "kp( bb )" )
print( bb.married )
}
}
```
```
true
kp( bb )
false
```
### Any 為可存任何資訊的資料型態
### as! 強型別轉換
```swift=
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let RG : Int = 83
// fix 練習 #0 觀察下面程式碼
// Any 為可存任何資訊的資料型態, 所以 nta 可存 Int 資料型態的資訊
var nta : Any = RG
nta = 83
print(" nta = 83")
var 整數K : Int
// fix 練習 #1 觀察下行, 執行此程式
// 當您想把 nta 存的 整數查出來, 必須要用 as! 來轉成 Int 資料型態
// , 但為什麼是 轉成 Int 資料型態, 是因您認為 nta 是存 Int 資料型態的資訊
// , 因為 nta 為 Any資料型態, 所以它可存任何資料型態的資訊, 萬ㄧ存的是 false
// 這種 Bool 值
// , 所以用 nta as! Int 語法 轉成 Int 會 閃退
整數K = nta as! Int
print("整數K + 1 為 \( 整數K + 1 )")
print()
print()
nta = false
print(" nta = false")
// nta is Int 語法 是去看 nta 存的是不是 Int
// 若是, 算出 Bool 型態的值 true, 否則算出 false
// fix 練習 #4-1 將下行註解取消
if nta is Int {
// fix 練習 #3 將下兩行註解取消, 觀察下行執行時會如何
// 整數K = nta as! Int
// print("整數K + 1 為 \( 整數K + 1 )")
// fix 練習 #4-2 再將下3行註解取消
} else {
print(" nta is Int 為 \( nta is Int )")
}
print()
// fix 練習 #5 執行此程式, 觀察下行
// fix 練習 #2 執行此程式, 觀察下行
print("你能執行到這裡嗎")
}
}
```
```
nta = 83
整數K + 1 為 84
nta = false
nta is Int 為 false
你能執行到這裡嗎
```
### 使用as?推測後轉型,若型別相符得到有值得 Optional,型別不符得到nil
```swift=
let RG : Int = 83
// fix 練習 #0 觀察下面程式碼
// Any 為可存任何資訊的資料型態, 所以 nta 可存 Int 資料型態的資訊
var nta : Any = RG
nta = 83
print(" nta = 83")
print()
var pg : Int?
// fix 練習 #1
// 當您想把 nta 存的 整數查出來, 必須要用 as? 來轉成 Int? 資料型態
// , 但為什麼是 轉成 Int? 資料型態, 是因為 nta 不一定是存 Int 資料型態的資訊
// , 因為 nta 為 Any資料型態, 所以它可存任何資料型態的資訊, 萬ㄧ存的是 false
// 這種 Bool 值
// , 所以這時 轉成 Int? 會是 nil
pg = nta as? Int
if let uw = pg {
print("uw + 1 為 \( uw + 1 )")
} else {
print("nta as? Int 為 \( nta as? Int )")
}
print()
print()
print()
nta = false
print(" nta = false")
print()
// fix 練習 #2
// 當您想把 nta 存的 整數查出來, 必須要用 as? 來轉成 Int? 資料型態
// , 但為什麼是 轉成 Int? 資料型態, 是因為 nta 不一定是存 Int 資料型態的資訊
// , 因為 nta 為 Any資料型態, 所以它可存任何資料型態的資訊, 萬ㄧ存的是 false
// 這種 Bool 值
// , 所以這時 轉成 Int? 會是 nil
pg = nta as? Int
if let uw = pg {
print("uw + 1 為 \( uw + 1 )")
} else {
print("nta as? Int 為 \( nta as? Int )")
}
```
```
nta = 83
uw + 1 為 84
nta = false
nta as? Int 為 nil
```
### Optional
```swift=
#####swift檔
class B {
var _s :String = "ktm"
func 傳回字串( ) -> String {
// fix 練習 #2 觀察下⾏程式可有執⾏?
print("第二步: 有人想要 拿到 _s 資料")
return _s
}
}
class A {
var _b : B? = nil // 初值設為 nil
func 傳回B( ) -> B? {
print("第ㄧ步: 有人想要 拿到 _b 資料")
print("第ㄧ步: _b == nil 為 \( _b == nil )")
print()
// fix 練習 #1 觀察下行程式碼
return _b
}
}
```
```swift=
#####主程式檔
// fix 練習 #0 觀察下面程式碼
let _a : A = A()
print("let _a : A = A()")
print()
// fix 練習 #3-1
// 下⾏ RV 變數的型態為 String?
var RV : String?
// 注意下⾏的這種 '傳回B( )?' 語法
// 這種語法就是代表盡力執行下去, 能做到哪裡就到哪裡
// 因為最後呼叫的副程式'傳回字串( )' 想傳回字串
// 但若沒有順利地一直執行到這個副程式, 就傳回 nil
RV = _a.傳回B( )?.傳回字串( )// fix 練習 #3-2
if let 成功傳回的字串 = RV {
print( 成功傳回的字串 )
} else {
print( "沒能傳回的字串" )
}
```
```
let _a : A = A()
第ㄧ步: 有人想要 拿到 _b 資料
第ㄧ步: _b == nil 為 true
沒能傳回的字串
```
```swift=
// fix 練習 #0 觀察下面程式碼
let _a : A = A()
print("let _a : A = A()")
let bb : B = B()
// fix 練習 #1 觀察下⾏程式
print("_a._b = bb")
_a._b = bb
print()
var RV : String?
// fix 練習 #2
// 注意下⾏的這種 '傳回B( )?' 寫法
// 盡力執行下去, 能做到哪裡就到哪裡
RV = _a.傳回B( )?.傳回字串( )
if let 成功傳回的字串 = RV {
print( 成功傳回的字串 )
} else {
print( "沒能傳回的字串" )
}
```
```
let _a : A = A()
_a._b = bb
第ㄧ步: 有人想要 拿到 _b 資料
第ㄧ步: _b == nil 為 false
第二步: 有人想要 拿到 _s 資料
ktm
```
### 同名方法
```swift=
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("theTotal 為 \(theTotal)")
print("add ( )")
// fix 練習 #0 觀察下面三次呼叫 add 方法
add ( )
print("theTotal 為 \(theTotal)")
print("add ( 什麼: 9 )")
add ( 什麼: 9 )
print("theTotal 為 \(theTotal)")
print("add ( howMany: 3 , what: 2 )")
add ( howMany: 3 , what: 2 )
print("theTotal 為 \(theTotal)")
}
var theTotal : Int = 0
func add ( howMany : Int , what : Int ) {
if howMany < 1 {
return
}
for _ in 1...howMany {
add( 什麼: what )
}
}
func add ( 什麼 what : Int ) {
theTotal += what
}
func add ( )
{
add(什麼: 1)
}
}
```
```
theTotal 為 0
add ( )
theTotal 為 1
add ( 什麼: 9 )
theTotal 為 10
add ( howMany: 3 , what: 2 )
theTotal 為 16
```
### guard
```swift=
func 把您的投資翻倍 ( 投資金額 AssetWr : Int? ) -> Int? {
var Answer : Int? = nil
// fix 練習 #0 觀察下行 guard let asset = AssetWr else {
// , 若 AssetWr == nil
// 則執行 else 搭配的 { } 內的程式, 以此範例來說
// , 就是執行 return Answer
// 若 AssetWr != nil , 則建立 asset 常數
// 然後繼續從 print("AssetWr != nil") 往下執行
// 注意: 此 asset 常數 可在'往下執行' 的程式碼中可以被使用
guard let asset = AssetWr else {
return Answer
}
print("AssetWr != nil")
// fix 練習 #1 觀察下行
// 上面 guard let 建立 的 asset 常數 可被使用
guard asset > 0 else {
return Answer
}
let 兩倍 = Double(asset * 2)
let 任意比率 = Double(arc4random()) / Double(UInt32.max)
Answer = Int( 兩倍 * 任意比率 )
return Answer
}
override func viewDidLoad() {
super.viewDidLoad()
var 募資 : Int? = nil
print("募資 = nil")
募資 = nil
// fix 練習 #2 觀察下行 '把您的投資翻倍' 被呼叫時的執行結果
if let outcome = 把您的投資翻倍(投資金額: 募資 ) {
print( " outcome 是 \(outcome)")
} else {
print( " 募資 == nil 為 \(募資 == nil)")
}
募資 = -200000
print("募資 = -200000")
// fix 練習 #3 觀察下行 '把您的投資翻倍' 被呼叫時的執行結果
if let outcome = 把您的投資翻倍(投資金額: 募資 ) {
print( " outcome 是 \(outcome)")
} else {
print( " 募資 == nil 為 \(募資 == nil)")
}
募資 = 1000000000
print("募資 = 1000000000")
// fix 練習 #4 觀察下行 '把您的投資翻倍' 被呼叫時的執行結果
if let outcome = 把您的投資翻倍(投資金額: 募資 ) {
print( " outcome 是 \(outcome)")
} else {
print( " 募資 == nil 為 \(募資 == nil)")
}
}
}
```
```
募資 = nil
募資 == nil 為 true
募資 = -200000
AssetWr != nil
募資 == nil 為 false
募資 = 1000000000
AssetWr != nil
outcome 是 1098705392
```
### designated initializer(指定初始) & convenience(便利初始) initializer
初始化函式有兩種:
Designated Initializer: 類別主要初始化函式。必須讓屬於類別本身所有的屬性完成初始化,然後呼叫父類別的初始化函式繼續完成初始化工作。
Convenience Initialize: 方便使用者設定的初始化函式。使用convenience關鍵字並將某些參數定為預設值,然後呼叫同層的 designaed initializer 或 convenience initializer。
```swift=
#####swift檔#####
class Myadt {
var 分子 : Int // = 1
var 分母 : Int // = 2
// fix 練習 #0 下行 init 稱呼為
// designated initializer
// , 此 initilaizer 會在您用
// Myadt(分子:6,分母:5) 語法產生物件時
// 自動被呼叫, 來達到運用傳進此 initializer
// 的兩個參數 來初始 儲存性屬性的值
init(分子 nume :Int,分母 deno :Int) {
// 參數 nume 來初始 '分子' 儲存性屬性的值
分子 = nume
// 參數 deno 來初始 '分母' 儲存性屬性的值
分母 = deno
// designated initializer 要初始
// 所有的 stored properties
}
// fix 練習 #0 下行 init 稱呼為
// convenience initializer
// , 此 initilaizer 會在您用
// Myadt(分子:34) 語法產生物件時
// 自動被呼叫, 來達到初始儲存性屬性的值
convenience init(分子 nume :Int) {
// convenience initializer 會在body的開始
// 就呼叫其他的 initializer
self.init(分子: nume, 分母: 10)
}
convenience init ( ) {
self.init(分子: 3, 分母: 8 )
}
}
```
```swift=
#####viewcontroller#####
class ViewController: UIViewController
{
override func viewDidLoad() {
super.viewDidLoad()
let 分數七 = Myadt(分子:6,分母:5)
print(
"分數七 為 \(分數七.分子)/\(分數七.分母)")
let 分數四 = Myadt(分子:34)
print(
"分數四 為 \(分數四.分子)/\(分數四.分母)")
let 分數八 = Myadt( )
print(
"分數八 為 \(分數八.分子)/\(分數八.分母)")
}
}
```
```
分數七 為 6/5
分數四 為 34/10
分數八 為 3/8
```
### 帶分數
```swift=
#####swift檔#####
// fix 練習 #0
// 帶分數 '是ㄧ種' 分數
// Myadt 是 '帶分數' 的 'super' 類別
// 帶分數 是 'Myadt' 的 '子類別' 或是
// '女兒類別' 註: 在此只是ㄧ種 相互的稱呼
class 帶分數 : Myadt {
// fix 練習 #1
var 整數 : Int //因 '帶分數' 的 '整數'部分要由 分子,分母算出來
// 而'super' 類別的 init(分子 nume :Int,分母 deno :Int)
// 沒有要由 分子,分母算出來的邏輯, 所以我們要'改寫' override
// 這個 init(分子 nume :Int,分母 deno :Int)
override init(分子 nume :Int,分母 deno :Int)
{
整數 = nume / deno
// fix 練習 #2
//要初始所有的 stored properties
//才能用 super 呼叫 父類別的 designated initializer.
super.init(分子: nume % deno, 分母: deno)
}
}
class Myadt {
var 分子 : Int
var 分母 : Int
init(分子 nume :Int,分母 deno :Int) {
分子 = nume
分母 = deno
}
convenience init(分子 nume :Int) {
self.init(分子: nume, 分母: 10)
}
convenience init ( ) {
self.init(分子: 3, 分母: 8 )
}
}
```
```swift=
#####viewcontroller#####
class ViewController: UIViewController
{
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #3 測試 '帶分數' 的設計
let 分數n = 帶分數(分子:6,分母:5)
print(
"\(分數n.整數) 又 \(分數n.分子)/\(分數n.分母)")
let 分數f = 帶分數( )
print(
"\(分數f.整數) 又 \(分數f.分子)/\(分數f.分母)")
}
}
```
```
1 又 1/5
0 又 3/8
```
### 帶分數-1
```swift=
#####swift檔#####
class 帶分數 : Myadt {
var 整數 : Int
// fix 練習 #1 想多設計 有 'intP' 參數的 init
init( 整數 intP :Int , 分子 nume :Int,分母 deno :Int) {
整數 = intP
super.init(分子: nume , 分母: deno)
}
// fix 練習 #2 因此必須也改寫 required 的 init
required init( 分子 nume :Int,分母 deno :Int) {
整數 = nume / deno
super.init(分子: nume % deno, 分母: deno)
}
}
class Myadt {
var 分子 : Int
var 分母 : Int
// fix 練習 #0 'required init' 的設計
required init(分子 nume :Int,分母 deno :Int) {
分子 = nume
分母 = deno
}
convenience init(分子 nume :Int) {
self.init(分子: nume, 分母: 10)
}
convenience init ( ) {
self.init(分子: 3, 分母: 8 )
}
}
```
```swift=
#####viewcontroller#####
class ViewController: UIViewController
{
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #3 測試 '帶分數' 的設計
let 分數n = 帶分數(整數:1, 分子:1, 分母:5)
print(
"\(分數n.整數) 又 \(分數n.分子)/\(分數n.分母)")
let 分數k = 帶分數( 分子:6,分母:5 )
print(
"\(分數k.整數) 又 \(分數k.分子)/\(分數k.分母)")
let 分數f = 帶分數( )
print(
"\(分數f.整數) 又 \(分數f.分子)/\(分數f.分母)")
}
}
```
```
1 又 1/5
1 又 1/5
0 又 3/8
```
### self
```swift=
#####swift檔#####
class A {
var _b : Int = 5
func 加幾個 ( _ 幾個 : Int , _ 什麼 : Int )
{
func 加 ( _ 什麼 : Int ) {}
for _ in 1...幾個 {
// fix 練習 #1 下行運用 self 避免
// 被swift認為您是要取用上面的 '加'
// nested function
// self 翻譯成 '自己'
self.加 ( 什麼 )
}
}
func 加 ( _ 什麼 : Int ) {
var _b : Int = 200
_b += 300
// fix 練習 #0 下行運用 self 避免
// 被swift認為您是要取用上面的 _b
// 區域變數
// self 翻譯成 '自己'
self._b += 什麼
}
}
```
```swift=
#####viewcontroller#####
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let aaa : A = A()
print("aaa._b 為 \(aaa._b)")
aaa.加幾個 ( 3 , 6 )
print("aaa._b 為 \(aaa._b)")
}
}
```
```
aaa._b 為 5
aaa._b 為 23
```
### protocol
```swift=
protocol The {
func 有氣質()
func 有貢獻( _ pay : Int )
}
class Harry : The {
func 有氣質() {
print("act like a king")
}
func 有貢獻( _ pay : Int ) {
print("spend \(pay) lb like a wolf licking the blood")
}
}
class William : The {
func 有氣質() {
print("act like his father")
}
func 有貢獻( _ pay : Int ) {
print("store all the \(pay) lb")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let goodBuy : The = Harry()
print("covid18 is spreading")
goodBuy.有貢獻(2000000)
print("show his grace")
goodBuy.有氣質()
let likeHisFather : The = William()
print("covid18 is spreading")
likeHisFather.有貢獻(200000000)
print("show his grace")
likeHisFather.有氣質()
}
}
```
```
covid18 is spreading
spend 2000000 lb like a wolf licking the blood
show his grace
act like a king
covid18 is spreading
store all the 200000000 lb
show his grace
act like his father
```
### protocol_lab
```swift=
// fix 練習 #2-1 觀察下面 ViewController 已繼承 UIViewController
class ViewController: UIViewController
// fix 練習 #2-2 將下行註解取消, 觀察會如何?
// 說明: 在此情形下, 要此 ViewController 遵守 The 協定
// 就先寫ㄧ個 , 再寫 The 即可
, The
{
// fix 練習 #3 將下 6 行註解取消, 觀察會如何?
func 有氣質 () {
print( "優雅地發表演說" )
}
func 有貢獻 ( _ pay :Int ) {
print( "把這些錢: \(pay) 元 用來找 免疫學專家 去發明疫苗" )
}
var w : The?
override func viewDidLoad() {
super.viewDidLoad()// fix 練習 #0 執行此程式, 看下面會如何?
// fix 練習 #1 將下兩行註解取消, 觀察會如何?
print("w = self")
w = self
// fix 練習 #4 執行此程式, 看下面會如何?
print()
print( "covid18 is spreading" )
w?.有貢獻 ( 2000000000 )
print("show his grace")
w?.有氣質()
print()
print()
}
}
protocol The {
func 有氣質 ()
func 有貢獻 ( _ pay :Int )
}
```
```
w = self
covid18 is spreading
把這些錢: 2000000000 元 用來找 免疫學專家 去發明疫苗
show his grace
優雅地發表演說
```
### data_soure_and_delegate 委派
```swift=
#####swift檔#####
// fix 練習 #5 觀察下面的 TheProduct 類別
class TheProduct {
var productName : String
var unitPrice : Int
init( 產品名稱 pn :String, 單價 ur :Int)
{
productName = pn
unitPrice = ur
}
}
```
```swift=
#####viewcontroller#####
class ViewController: UIViewController
// fix 練習 #2 將下行註解取消,
// 就會消除 fix #1 的語法錯誤
// 但變成這裡有錯誤
, UITableViewDataSource
{
// fix 練習 #0 執行此程式
// 並觀察 下行的 theTableView 儲存性屬性
// 它存著綠色的 UITableView 物件的參考
// 此 UITableView 上目前並沒有顯示任何產品
@IBOutlet weak var theTableView: UITableView!
var theRows : [ TheProduct ]! = []
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #1 將下行註解取消, 觀察下行
// theTableView 的 dataSource 屬性
// 它會設成自己這個 ViewController 的
// 物件的參考
//dataSource 是 UITableViewDataSource?
// 型態,而 UITableViewDataSource是ㄧ種協定
//因 ViewController 沒有遵守此協定
// ,所以語法有錯
theTableView.dataSource = self
var ep : TheProduct
ep = TheProduct(產品名稱: "Arod", 單價: 85)
theRows.append(ep)
ep = TheProduct(產品名稱: "Bee", 單價: 200)
theRows.append(ep)
ep = TheProduct(產品名稱: "CheShui", 單價: 105)
theRows.append(ep)
}
// fix 練習 #3 將下四行註解取消, 觀察
// 可有完全消除 fix #2 的語法錯誤
// , 此方法傳回的 Int 資料是代表
// 綠色的 UITableView 要顯示幾筆產品
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return theRows.count
}
// fix 練習 #4 將下10行註解取消, 觀察
// 總算完全消除 fix #2 的語法錯誤
// , 此方法傳回的 UITableViewCell 是代表
// 綠色的 UITableView 怎麼顯示每筆產品
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "mapd", for: indexPath)
let index : Int = indexPath.row
cell.textLabel?.text = theRows [ index ].productName
cell.detailTextLabel?.text = "\(theRows [ index ].unitPrice)"
return cell
}
}
```
### closure 閉包
```swift=
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #0 觀察下行 theGreaterThan 變數
// 的資料型態為 ( Int , Int )->Bool
// 此資料型態稱呼為 closure 翻譯成中文為 '閉包'
// '閉包' 資料型態 代表副程式
// 此例 ( Int , Int )->Bool '閉包' 資料型態
// 代表的副程式為 有兩個 Int 型態的參數, 傳回值為 Bool 型態
var theGreaterThan : (Int,Int)->Bool
print ("var theGreaterThan : ( Int , Int )->Bool")
theGreaterThan =
// fix 練習 #1 觀察上行 theGreaterThan 變數要設ㄧ個值, 如下
// 先有ㄧ對大括弧 { } 的左大括弧 {
{
// 兩個參數的資料型態為 ( Int , Int )
( Left :Int , Right : Int )
in
// 身體
let answer : Bool
answer = Left > Right
return answer // 傳回傳回值
} // 右大括弧 }
var s : Int
var t : Int
var RR : Bool
s = 8
t = 3
print( "s 為 \(s)" )
print( "t 為 \(t)" )
print( "RR = theGreaterThan ( s , t )" )
RR = /* 呼叫 '閉包' */theGreaterThan( s , t )
print( "RR 為 \(RR)" )
print()
s = 5
t = 5
print( "s 為 \(s)" )
print( "t 為 \(t)" )
print( "RR = theGreaterThan ( s , t )" )
RR = theGreaterThan( s , t )
print( "RR 為 \(RR)" )
print()
s = 9
t = 2
print( "s 為 \(s)" )
print( "t 為 \(t)" )
print( "RR = theGreaterThan ( s , t )" )
RR = theGreaterThan( s , t )
print( "RR 為 \(RR)" )
print()
s = 7
t = 8
print( "s 為 \(s)" )
print( "t 為 \(t)" )
print( "RR = theGreaterThan ( s , t )" )
RR = theGreaterThan( s , t )
print( "RR 為 \(RR)" )
}
}
class Myadt {
var 分子 : Int
var 分母 : Int
init ( 分子 nume : Int , 分母 deno : Int ) {
分子 = nume
分母 = deno
}
}
```
```
var theGreaterThan : ( Int , Int )->Bool
s 為 8
t 為 3
RR = theGreaterThan ( s , t )
RR 為 true
s 為 5
t 為 5
RR = theGreaterThan ( s , t )
RR 為 false
s 為 9
t 為 2
RR = theGreaterThan ( s , t )
RR 為 true
s 為 7
t 為 8
RR = theGreaterThan ( s , t )
RR 為 false
```
### closure 閉包_lab
```swift=
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// fix 練習 #0 觀察下行 theCLZ 變數
// 的資料型態為 ( )->Void
// 此例 ( )->Void '閉包' 資料型態
// 代表的副程式為 沒有參數, 沒有傳回值
var theCLZ : ( )->Void
print ("var theCLZ : ( )->Void")
theCLZ =
// fix 練習 #1 觀察上行 theCLZ 變數要設ㄧ個值, 如下
// 先有ㄧ對大括弧 { } 的左大括弧 {
{
// ( ) // 沒有參數
// in
// 身體
let RN : UInt32 = arc4random() % 99 + 201
print( "RN 為 \(RN)" )
} // 右大括弧 }
var RR : Bool
print( "RR = theCLZ ( ) 因為 theCLZ ( ) 沒有傳回值" )
//fix 練習 #3 將下行再變成註解
//fix 練習 #2 將下行註解取消
// 觀察下行的 呼叫 theCLZ '閉包'
// , 為什麼有錯
//RR = /* 呼叫 '閉包' */ theCLZ ( )
print()
print( "theCLZ ( )" )
//fix 練習 #4 觀察下行的 呼叫 theCLZ '閉包'
theCLZ ( )
print( "theCLZ ( )" )
//fix 練習 #5 觀察下行的 呼叫 theCLZ '閉包'
theCLZ ( )
}
}
class Myadt {
var 分子 : Int
var 分母 : Int
init ( 分子 nume : Int , 分母 deno : Int ) {
分子 = nume
分母 = deno
}
}
```
```
var theCLZ : ( )->Void
RR = theCLZ ( ) 因為 theCLZ ( ) 沒有傳回值
theCLZ ( )
RN 為 281
theCLZ ( )
RN 為 285
```
### select _ addTarget
```swift=
class ViewController: UIViewController {
var theBtn : UIButton!
@objc
func theIba ( _ sender : UIButton ) {
sender.backgroundColor = UIColor.green
}
override func viewDidLoad() {
super.viewDidLoad()
theBtn = UIButton()
theBtn.backgroundColor = UIColor.darkGray
let rct = CGRect(x: 90, y: 90, width: 20, height: 20)
theBtn.frame = rct
theBtn.addTarget(self,action: #selector( theIba(_:) ), for: .touchUpInside )
view.addSubview(theBtn)
}
}
```
### select _ addTarget_lab
```swift=
class ViewController: UIViewController
{
var theBtns : [ UIButton ] = [ ]
override func viewDidLoad() {
super.viewDidLoad()
theBtn = UIButton()
theBtn.backgroundColor = UIColor.darkGray
theBtn.frame = CGRect(x: 10, y: 90, width: 50, height: 50)
theBtn.addTarget( self ,action: #selector( theIba(_:) ), for: .touchUpInside )
view.addSubview(theBtn)
theBtns.append( theBtn )
//-----------------------------------------------------
theBtn = UIButton()
theBtn.backgroundColor = UIColor.purple
theBtn.frame = CGRect(x: 10 + 60 , y: 90, width: 50, height: 50)
theBtn.addTarget( self ,action: #selector( theIba(_:) ), for: .touchUpInside )
view.addSubview(theBtn)
theBtns.append( theBtn )
//-----------------------------------------------------
theBtn = UIButton()
theBtn.backgroundColor = UIColor.cyan
theBtn.frame = CGRect(x: 10 + 120 , y: 90, width: 50, height: 50)
theBtn.addTarget( self ,action: #selector( theIba(_:) ), for: .touchUpInside )
view.addSubview(theBtn)
theBtns.append( theBtn )
}
//-----------------------------------------------------
@objc
func theIba ( _ sender : UIButton ) {
print()
for index in 0..<theBtns.count {
if theBtns [ index ] === sender {
print( "第 \( index ) 個元素" )
break
}
}
print()
}
var theBtn : UIButton!
}
```
![](https://i.imgur.com/XASRPTW.png)
```
addTarget
第 0 個元素
第 1 個元素
第 2 個元素
```