#IOS/Swift入門開發(fā)從"白吃"到大神,全球最易懂,最全面,最前沿,最詳細(xì),一看就會教程之二!

f2da63e17923fd0a18be1c90b948eb43.jpg

序言

本文為入門教程:主要針對無任何編程基礎(chǔ)或是想了解IOS/Swfit編程開發(fā)的小伙伴。
若本文讓你感到任何不適,頭暈想吐等癥狀,嘿嘿嘿···本人概不負(fù)責(zé)!?。?

傳送門

由于本教程是連載類型,為了各位看客老爺跟加直觀的欣賞。
第一課:http://www.itdecent.cn/p/8e8ff60121c4
第二課:http://www.itdecent.cn/p/8cdabd470f6f
第四課: http://www.itdecent.cn/p/55ca9d54a610

概述

經(jīng)過上一周最基本的Swift基礎(chǔ)語法講解和練習(xí)之后,本周我們學(xué)習(xí)的是更為復(fù)雜和實用的語法和內(nèi)容。

內(nèi)容

1.字典和集合
//字典(存放鍵值對組合的容器)
//字典中的每個元素都是由兩部分構(gòu)成,冒號前面的是鍵,冒號后面的是值
var dict:[String:String] = ["abacus":"算盤","abnormal":"異常的","hello":"你好","good":"好的"]
//print 前面的鍵 就會輸出后面的值
//但是print 后面的值 不會輸出前面的鍵
print(dict["hello"]!)
print(dict["abcxyz"])
print(dict["你好"])
// 添加元素
dict["shit"] = "狗屎"
dict["delicious"] = "好吃的"
print(dict)

// 刪除元素
 dict.removeValueForKey("hello") //第一種
dict["hello"] = nil //第二種
print(dict)
print(dict["hello"])

// 修改元素
dict["shit"] = "牛糞"
print(dict)

// 遍歷字典中所有的值
for value in dict.values {
    print(value)
}

// 遍歷字典中所有的鍵
for key in dict.keys {
    print("\(key) ---> \(dict[key])")
}

// 直接通過一個元組獲得字典中的鍵和值(原始類型)
for (key, value) in dict {
    print("\(key) ---> \(value)")
}





下面介紹集合

var a: Set<Int> = [1, 2, 3, 1, 2, 5]
a.insert(100)           // 添加元素
a.remove(2)             // 刪除元素
print(a)
var b: Set<Int> = [3, 5, 7, 9, 11]
print(b)

print(a.intersect(b))   // 交集(a和b都有的元素)
print(a.union(b))       // 并集(a和b的所有元素)
print(a.subtract(b))    // 差集(a有b沒有的元素)

print(a == b)
print(b.isSubsetOf(a))

let c: Set<Int> = [1, 3]
print(c.isSubsetOf(a))      // 判斷c是不是a的子集
print(a.isSupersetOf(c))    // 判斷a是不是c的超集

let d: Set<Int> = [2, 1000, 10000]
print(a.isDisjointWith(d))  // 判斷兩個集合是否相交



集合中兩個值相同的元素,會合并到一起。

2.函數(shù)

函數(shù)我認(rèn)為是swift語言中最重要的章節(jié)之一。
下面是函數(shù)的定義和一些基礎(chǔ)的運(yùn)用
定義函數(shù)的關(guān)鍵詞為func

// 函數(shù)的參數(shù)名
// 函數(shù)名(外部參數(shù)名 內(nèi)部參數(shù)名: 類型, 外部參數(shù)名 內(nèi)部參數(shù)名: 類型)
// 如果不寫外部參數(shù)名那么內(nèi)部參數(shù)名也是外部參數(shù)名
// 可以使用_來作為外部參數(shù)名表示省略外部參數(shù)名
func myMin(a x: Int, b y: Int) -> Int {
    return x < y ? x : y
}

// 調(diào)用函數(shù)的時候要寫函數(shù)的外部參數(shù)名
print(myMin(a: 3, b: 5))

// 定義函數(shù)
// func 函數(shù)名(參數(shù)列表) -> 返回類型 { 函數(shù)的執(zhí)行體 }
// Swift中函數(shù)的參數(shù)可以設(shè)定默認(rèn)值
// 如果調(diào)用函數(shù)的時候沒有給該參數(shù)賦值就直接使用默認(rèn)值
func sayHello(personName: String, alreadyGreeted: Bool = false) -> String {
    // let greeting = "Hello, " + personName + "!"
    // 如果函數(shù)的返回類型不是Void 那么函數(shù)中一定有return語句
    // return greeting
    // personName = "王小錘"   // 編譯錯誤
    if alreadyGreeted {
        return "怎么又是你, " + personName + "!"
    }
    else {
        return "你好, " + personName + "!"
    }
}

// 調(diào)用函數(shù)
// 函數(shù)名(參數(shù)值)
// 調(diào)用Swift的函數(shù)時, 在默認(rèn)情況下從第二個參數(shù)開始需要寫參數(shù)名
print(sayHello("王大錘", alreadyGreeted: true))
// 如果沒有給第二個參數(shù)賦值那么就直接使用默認(rèn)值false
let str = sayHello("Jack")
print(str)

// Swift中函數(shù)的參數(shù)列表可以是可變參數(shù)列表(參數(shù)的個數(shù)是任意多個)
func sum(nums: Int...) -> Int {
    var total = 0
    for num in nums {
        total += num
    }
    return total
}

print(sum())
print(sum(999))
print(sum(1, 2, 3))
print(sum(90, 82, 37, 68, 55, 11, 99))

// 可以使用元組(tuple)讓函數(shù)一次返回多條數(shù)據(jù)
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.count == 0 {
        return nil
    }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        }
        else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

if let b = minMax([23, 45, 99, 68, 72, 12, 55]) {
    print(b.min)        // print(b.0)
    print(b.max)        // print(b.1)
}
else {
    print("數(shù)組中沒有元素!!!")
}

func swap(inout a: Int, inout _ b: Int) -> Void {
    (a, b) = (b, a)
//    let temp = a
//    a = b
//    b = temp
}

var a = 300, b = 500
swap(&a, &b)
print("a = \(a)")
print("b = \(b)")

// inout - 輸入輸出參數(shù)(不僅將數(shù)據(jù)傳入函數(shù)還要從函數(shù)中取出數(shù)據(jù))
func createX(inout x: Int) {
    x = 1000
}

var x = 1
// inout類型的參數(shù)前要加上&符號
createX(&x)
print(x)




函數(shù)的兩個小例子

// 設(shè)計一個函數(shù)根據(jù)系統(tǒng)時間返回不同的問候語
func sayHello(name: String) -> String {
    let date = NSDate()
    let cal = NSCalendar.currentCalendar()
    let hour = cal.component(.Hour, fromDate: date)
//這三句代碼的意思為:第一句 獲取當(dāng)前系統(tǒng)時間 
//第二句是 當(dāng)前歷法
//第三句是 當(dāng)前小時
    var greeting: String
    switch hour {
    case 0...6:         // 不同的分支可以有重疊的部分
        greeting = "滾去碎覺了"
        // fallthrough  // 繼續(xù)執(zhí)行下一個case
    case 4...10:        // 匹配了一個分支之后不再匹配其他的分支
        greeting = "早起的鳥兒有蟲吃"
    case 11...13:
        greeting = "中午好"
    case 14...18:
        greeting = "下午好"
    default:
        greeting = "晚上好"
    }
    return name + ", " + greeting + "!"
}

print(sayHello("小剛"))

// 設(shè)計一個函數(shù)傳入兩個正整數(shù)m和n, 計算從m加到n的和
func sum(m: Int, _ n: Int) -> Int {
    let (a, b) = m > n ? (n, m) : (m, n)
    var value = 0
    for i in a...b {
        value += i
    }
    return value
}

print(sum(1, 100))
print(sum(5, -4))
print(sum(-1, -5))

調(diào)用蘋果自身的Api,進(jìn)行程序應(yīng)用開發(fā)

調(diào)用蘋果的指紋識別,開發(fā)一個帶有指紋識別的支付功能的app。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let errPointer = NSErrorPointer()
        let ctx = LAContext()
        // 判斷設(shè)備是否支持指紋識別
        if ctx.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, error: errPointer) {
            // z = f(x, g(y))
            // Swift中允許將一個函數(shù)作為另一個函數(shù)的參數(shù)
            // evalutePolicy方法的第三個參數(shù)是一個函數(shù)
            // 該函數(shù)有兩個參數(shù)沒有返回值
            // 給該參數(shù)傳參時可以在花括號中寫一個匿名函數(shù)傳進(jìn)去
            // 該匿名函數(shù)通常也稱之為閉包(closure)
            ctx.evaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "請輸入指紋進(jìn)行支付", reply: { (isOK, err) -> Void in
                if isOK {
                    print("支付成功!!!")
                }
                else {
                    print("指紋驗證失敗, 請輸入支付密碼")
                }
            })
        }
        else {
            print("你的設(shè)備不支持指紋識別")
        }
    }
}




3.閉包

閉包也稱:匿名函數(shù) 意思是沒有名字的函數(shù)
閉包由來:
在swift中函數(shù)也是一種類型
這也就意味著函數(shù)可以作為變量或常量的類型
同理函數(shù)也可以作為另一個函數(shù)和參數(shù)或返回值

func sum(a: Int, _ b: Int) -> Int {
    return a + b
}

func mul(a: Int, _ b: Int) -> Int {
    return a * b
}

func foo(array: [Int], fn: (Int, Int) -> Int) -> Int {
    var sum = array[0]
    for x in array[1..<array.count] {
        sum = fn(sum, x)
    }
    return sum
}

由于在swift中能省則省的原則和傳統(tǒng)就將調(diào)用函數(shù)做了以下幾步寫法省略

let a = [1, 2, 3, 4, 5]
// 當(dāng)調(diào)用foo函數(shù)時第二個參數(shù)可以傳什么?
// 1. 所有自定義的(Int, Int) -> Int類型的函數(shù)
print(foo(a, fn: sum))
// 2. 傳入已有的二元運(yùn)算符: +-*/%(因為運(yùn)算符也是函數(shù))
print(foo(a, fn: +))
// 3. 傳入匿名函數(shù)(閉包)
// 3.1 完整的閉包寫法
print(foo(a, fn: { (a, b) -> Int in
    return a + b
}))
// 3.2 省略掉類型和不必要的括號
print(foo(a, fn: { a, b in a + b }))
// 3.3 省略參數(shù)名
print(foo(a, fn: { $0 + $1 }))
// 3.4 尾隨閉包
print(foo(a) { (a, b) -> Int in
    return a + b
})
print(foo(a) { $0 + $1 })

需要注意的是:

如果函數(shù)的最后一個參數(shù)是閉包可以寫成尾隨閉包的形式
也就是將閉包放到函數(shù)參數(shù)的圓括號外面寫在一對花括號中
如果函數(shù)后面有尾隨閉包且函數(shù)的圓括號中沒有參數(shù)
那么函數(shù)的圓括號也可以省略(僅限于有尾隨閉包的場景)
例如

var array = ["game", "abacus", "hello", "cat", "good", "internationalization", "chaos", "dislike", "zealot", "young"]

// array.sortInPlace(>)
array.sortInPlace({ $0 > $1 })
array.sortInPlace() { $0 > $1 }
array.sortInPlace { $0 > $1 } //這就是尾隨閉包的最簡寫法

4.數(shù)組最重要的三個功能

1.過濾 2.映射 3.縮減

let array = [23, 37, 96, 55, 40, 92, 68, 88]

// 1. 過濾
let newArray1 = array.filter { $0 > 50 } //找到數(shù)組中比50大的數(shù)輸出出來
print(newArray1)

let newArray2 = array.filter { $0 % 2 == 0 } //找到數(shù)組中得偶數(shù)
print(newArray2)

// 2. 映射
let newArray3 = array.map { $0 * $0 } //將數(shù)組中的每個數(shù)平方
print(newArray3)
let newArray4 = array.map { sqrt(Double($0)) } //將數(shù)組中得每個數(shù)開根號
print(newArray4)

// 3. 縮減
let result1 = array.reduce(0, combine: +)// 將數(shù)組中的每個數(shù)想加
print(result1)
let result2 = array.reduce(1, combine: *)//將數(shù)組中的每個數(shù)相乘
print(result2)
let result3 = array.reduce(array[0]) { //取數(shù)組中最大的數(shù)
    $1 > $0 ? $1 : $0
}
print(result3)

let strArray = ["I", "love", "you"]
let result4 = strArray.reduce("") { $0 + " " + $1 }//將數(shù)組中的三個元素合為一個
print(result4)


5.類

類和上文提到的函數(shù) 緊密相關(guān)
類是一類事物 而對象是這類事物中具體的實例

 步驟1: 定義類(如果你要用的類蘋果已經(jīng)提供了就直接進(jìn)入第2步)
 定義類就可以創(chuàng)建出新的類型
 學(xué)生類
class Student {
    // 變量定義到類的外面就叫變量 - variable
    // 變量定義到類的里面就叫屬性 - property
    // 數(shù)據(jù)抽象 - 找到和學(xué)生相關(guān)的屬性(找名詞)
    var name: String
    var age: Int
    
    // 初始化方法(構(gòu)造方法/構(gòu)造器) - constructor
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    // 函數(shù)寫到類的外面就叫函數(shù) - function
    // 函數(shù)寫到類的里面就叫方法 - method
    // 行為抽象 - 找到和學(xué)生相關(guān)的方法(找動詞)
    func eat() {
        print("\(name)正在吃飯.")
    }
    
    func study(courseName: String) {
        print("\(name)正在學(xué)習(xí)\(courseName).")
    }
    
    func watchJapaneseAV() {
        if age >= 18 {
            print("\(name)正在動作片.")
        }
        else {
            print("親愛的\(name), 我們推薦你觀看《熊出沒》")
        }
    }
}

// 步驟2: 創(chuàng)建對象(調(diào)用初始化方法)
let stu1 = Student(name: "小剛", age: 35)
// 步驟3: 給對象發(fā)消息(通過給對象發(fā)消息來解決問題)
stu1.eat()
stu1.study("Swift程序設(shè)計")
stu1.watchJapaneseAV()

let stu2 = Student(name: "王大錘", age: 15)
stu2.eat()
stu2.study("中國近代史")
stu2.watchJapaneseAV()


下面定義一個圓的類
類里面有求圓的面積和周長的方法(函數(shù))
eg:

// 0. 發(fā)現(xiàn)類
//  - 在對問題的描述中找名詞和動詞
//  - 名詞會成為類或者類中的屬性 動詞會成為類中的方法

// 1. 定義類
//  - 數(shù)據(jù)抽象(屬性)
//  - 行為抽象(方法)
//  - 初始化方法

// 訪問修飾符
//  - public (公開)
//  - internal (內(nèi)部的) - 默認(rèn)
//  - private (私有)
class Circle {
    // stored property
    // 存儲屬性(保存和圓相關(guān)的數(shù)據(jù)的屬性)
    var center: Point
    var radius: Double
    
    init(center: Point, radius: Double) {
        self.center = center
        self.radius = radius
    }
    
    // 通常獲得某個計算出的值的方法都可以設(shè)計成計算屬性
    // computational property
    // 計算屬性(通過對存儲屬性做運(yùn)算得到的屬性)
    var perimeter: Double {
        // 圓的周長是一個只讀屬性
        // 所以此處只有g(shù)et{}沒有set{}
        get { return 2 * M_PI * radius }
    }
    
    var area: Double {
        get { return M_PI * radius * radius }
    }
}
注意:運(yùn)算符重載

```swift
//運(yùn)算符重載(為自定義的類型定義運(yùn)算符)
func +(one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}

func -(one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}

func *(one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}

func /(one: Fraction, two: Fraction) -> Fraction {
    return one.div(two)
}

6.繼承
// 繼承: 從已有的類創(chuàng)建新類的過程
// 提供繼承信息的稱為父類(超類/基類)
// 得到繼承信息的稱為子類(派生類/衍生類)
// 通常子類除了得到父類的繼承信息還會增加一些自己特有的東西
// 所以子類的能力一定比父類更強(qiáng)大
// 繼承的意義在于子類可以復(fù)用父類的代碼并且增強(qiáng)系統(tǒng)現(xiàn)有的功能
class Teacher: Person {
    var title: String
    
    init(name: String, age: Int, gender: Gender, title: String) {
        self.title = title
        super.init(name: name, age: age, gender: gender)
    }
    
    func teach(courseName: String) {
        print("\(name)\(title)正在教\(courseName).")
    }
}



//父類和子類關(guān)系
let p1 = Person(name: "王大錘", age: 25, gender: .Male)
p1.eat()

// 可以將子類型的對象賦值給父類型的變量(因為子類跟父類之間是IS-A關(guān)系)
// 學(xué)生是人, 老師是人, 所以學(xué)生和老師的對象可以賦值給人類型的變量
let p2: Person = Student(name: "張尼瑪", age: 18, gender: .Female, major: "計算機(jī)科學(xué)與技術(shù)")
p2.eat()
// 如果要將父類型的變量轉(zhuǎn)換成子類型需要用as運(yùn)算符進(jìn)行類型轉(zhuǎn)換
// 如果能夠確認(rèn)父類型的變量中就是某種子類型的對象可以用as!進(jìn)行轉(zhuǎn)換
// 如果不確定父類型的變量中是哪種子類型可以用as?嘗試轉(zhuǎn)換
(p2 as! Student).study("Swift程序設(shè)計")
if let temp = p2 as? Teacher {
    temp.teach("Java")
}
else {
    print("\(p2.name)不是老師!!!")
}


let p3: Person = Teacher(name: "駱昊", age: 35, gender: .Male, title: "叫獸")

p3.eat()

7.多態(tài)

同樣的對象類型(pet類型)接受了相同的消息(調(diào)用了相同的方法)
但是做了不同的事情 這就是多態(tài)(polymorphism)

例如:貓(cat)繼承它的父類動物(pet)

// Cat和Pet之間是IS-A關(guān)系(繼承)
class Cat: Pet {
    var hairColor: String?
    
    // 父類有的方法子類可以重新實現(xiàn) 這個過程叫方法重寫
    // 需要在方法前添加override關(guān)鍵字
    // 重寫有時也被稱為置換/覆蓋/覆寫
    
    override func play() {
        super.play()
        print("\(nickname)正在玩毛線球.")
    }
    
    override func shout() {
        print("\(nickname): 喵喵喵……")
    }
    
    func catchTheMouse() {
        print("\(nickname)正在抓老鼠.")
    }
}

對父類的方法可以重新實現(xiàn), 這個過程叫方法重寫
這是實現(xiàn)多態(tài)的重要步驟之一!
下面是實現(xiàn)多態(tài)的第二個步驟:

let petsArray = [
    Cat(nickname:"加菲",gender: .Male,age:2),
    Dog(nickname: "吉娃娃", gender: .Male, age: 3, isLarge: false),
    Dog(nickname: "大黃", gender: .FeMale, age: 2, isLarge: true),
    Mistress(nickname: "小花",gender: .FeMale,age:16)
]

for pet in petsArray{
    pet.eat()
    // 同樣的對象類型(pet類型)接受了相同的消息(調(diào)用了相同的方法)
    // 但是做了不同的事情 這就是多態(tài)(polymorphism)
    
    // 實現(xiàn)多態(tài)的關(guān)鍵步驟:
    // 1.方法的重寫(子類在繼承父類的過程中對父類已有的方法進(jìn)行重寫,而且不同的子類給出各自不同的實現(xiàn)版本)
    // 2.對象造型(將子類對象當(dāng)成父類型來使用)
    pet.play()
    pet.shout()
    // 如果dog是屬于pet中 如果dog是Dog類型就可以調(diào)用keepTheDoor這個特有的方法
    if let dog = pet as? Dog{
        dog.keepTheDoor()
    }
    else if let cat = pet as? Cat{
        cat.catchTheMouse()
    }
    else if let mistress = pet as? Mistress{
        mistress.makeTrouble()
    }
}


//枚舉
enum Gender{
    case Male
    case FeMale
    
}

總結(jié)

本周主要講的就是類和函數(shù)的定義和使用,在類的使用中又遇見各種問題 例如:重要的繼承和多態(tài)還有類的擴(kuò)展,運(yùn)算符重載,枚舉····主要是掌握它們之間的關(guān)系,如何定義還有使用的方法。

本次教程到處就要結(jié)束了,如果你有什么更好的建議和想法,可以聯(lián)系我,讓我們一同進(jìn)步。

未完待續(xù)····每周日更新新的教程,敬請期待!88····

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容