Swift培訓


  本篇是Swift內部培訓整理的PPT材料,主要內容來源於蘋果Swift編程語言官方教程,參考了網上的一些視頻課程內容。在教程介紹完之后,本人附帶實現了一個項目開發中的常用場景的Demo:基於導航欄和Tab欄的應用。

1.Swift概述

  我們先來看一篇文章:蘋果新貴 Swift之前世今生

  Swift是用於設計iOS及Mac OS X應用的一門新語言。

1.1.Swift特點

  1. Swift保留了C與Objective-C的優點,並摒棄其為了兼容C語言所受的限制;
  2. Swift吸納了安全編程模式,並新增了一些現代化功能,使其更易使用、更為靈活、更具樂趣。
  3. Swift的簡潔風格與廣受歡迎的成熟框架Cocoa/Cocoa Touch相結合,將為重新構思軟件的開發過程帶來新機遇;
  4. Swift內存管理采用ARC風格。

1.2.Swift代碼的文件擴展名

  *.swift

2.第一個Swift程序

2.1.使用Xcode Project編寫

2.2.使用Playground編寫

  我們可以基於 Playground 做這些事情:

  1. 學習:通過 Playground 學習 Swift,制作 Swift 教程實現交互式學習,同時還可以培訓其他初學者。
  2. 代碼開發:執行算法程序,迅速看到算法結果,跟蹤變量;執行繪圖程序,即時看到圖像結果,及時調整。執行通用代碼,查看變量的改變情況。
  3. 實驗性代碼:無需創建項目,直接打開一個獨立的Playground文件即可編寫代碼,嘗試調用新的 API。

3.常量與變量

  let關鍵詞聲明常量,var關鍵詞聲明變量。

let maximumNumberOfLoginAttempts = 10  // 常量只有在初始化的時候可以賦值

var currentLoginAttempt = 0

4.運算符和表達式

4.1.運算符

  1. 算術運算符:*、/、+、—、%、++、——
  2. 關系運算符:>、<、>=、<=、==、!=
  3. 布爾邏輯運算符:!、&&、||
  4. 三元運算符:?:

4.2.表達式

  1.不指定數據類型

var a1 = 10

var a2 = 20

var a = a1 > a2 ? "a1":"a2"

  2.指定數據類型

var a1:Int = 10

var a2:Int = 20

var a = a1 > a2 ? "a1":"a2"

  3.可以有分號結尾

var a1:Int = 10; var a2:Int = 20

var a = a1 > a2 ? "a1":"a2"

4.3.注釋

//

/*    */

5.數據類型

5.1.整型

  Swift提供8、16、32、64位形式的有符號及無符號整數,這些整數類型遵循C語言的命名規約。與Swift中的所有類型一樣,這些整數類型的名稱以大寫字母開頭

  Swift還提供了一個整數類型Int;

  1. 在32位平台,Int與Int32寬度一致;
  2. 在64位平台,Int與Int64寬度一致;

  Swift還提供了無符號整數類型UInt。

5.2.浮點型

  1. 單精度浮點(32位) Float
  2. 雙精度浮點(64位) Double

5.3.數字型

  表示數字如下:

let decimalInteger = 17  // 表示是10進制

let binaryInteger = 0b10001  // 二進制17

let octalInteger = 0o21  // 8進制17

let hexadecimalInteger = 0x11  // 16進制17

5.4.布爾類型

  true和false

let orangesAreOrange = true

let turnipsAreDelicious = false

6.數據類型轉換

6.1.整型轉換

  不同類型的整數常量或變量所能存儲的值域不同,需要顯示地轉換

let twoThousand:UInt16 = 2000

let one:UInt8 = 1

//let twoThousandAndOne = twoThousand + one  // 錯誤

let twoThousandAndOne = twoThousand + UInt16(one)  // 正確

6.2.整型與浮點數轉換

  整數與浮點數類型之間的轉換,需要顯示地轉換

let three = 3

let pointOneFourOneFiveNine = 0.14159

let pi = Double(three) + pointOneFourOneFiveNine

7.字符串類型

7.1.字符串初始化

  1.初始化

let someString = "Some string literal value"

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"

let dollarSign = "\x24"  // $,Unicode scalar U+0024

  2.空值

var emptyString = ""  // 空串初始化

var anotherEmptyString = String()  // 通過初始化函數初始化

  3.空值判斷

if emptyString.isEmpty{

    println("Nothing to see here")

}

if emptyString == ""{

    println("Nothing to see here")

}

7.2.字符串修改

  var 聲明的可以修改,let不能修改。

var variableString = "Horse"

variableString += " and carriage"

7.3.字符串插入

  斜杠+括號+變量

let multiplier = 3

let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

7.4.字符串長度

  使用countElements函數。OC中使用length屬性。

let unusualMenagerie = "Koala , Snail, Penguin"

println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")

7.5.比較字符串相等

let quotation = "We're a lot alike,you and I."

let sameQuotation = "We're a lot alike,you and I."

if quotation == sameQuotation{

    println("These two strings are considered equal")

}

8.元組(tuple)類型

  元組將多個值組合為單個值。元組內的值可以是任意類型,各元素不必是相同的類型,元組在作為函數返回值時尤其有用

  1.定義方法1

let http404Error = (404,"Not Found")

println("The status code is \(http404Error.0)");

println("The status message is \(http404Error.1)");

  2.定義方法2

let http200Error = (statusCode:404,discription:"Not Found")

println("The status code is \(http200Error.statusCode)");

println("The status message is \(http200Error.discription)");

9.可選(Optional)類型

9.1.使用可選類型

  我們在如下情況下使用可選類型:

  1. 它有值但不確定;
  2. 沒有任何值。
let possibleNumber = "123"

let convertedNumber:Int?=possibleNumber.toInt()

  “Int?”是可選類型

if convertedNumber{

    println("\(possibleNumber) has an Integer value of \(convertedNumber!)")

}
else{

    println("\(possibleNumber) could not be convented to an integer")

}

  convertedNumber是從可選類型中取值

9.2.使用nil

  我們可以為可選類型的變量設置nil值,表示沒有任何值。

var serverResponseCode:Int?=404

serverResponseCode = nil

  如果不是可選類型,那么是不能設置為nil的

10.數組

10.1.數組初始化

  基本語法:

[value1,value2,value3]

var shoppingList:String[] = [“Eggs","Milk"]

  對比一下OC中的方式:

NSArray *array = @[@"aa",@"bb"];

10.2.數組追加元素

  使用append函數追加或通過+操作符:

var shoppingList:String[] = ["Eggs","Milk"]

shoppingList.append("Flour")

shoppingList += ["Cheese","Butter"]

10.3.數組插入元素

  使用insert方法

var shoppingList:String[] = ["Eggs","Milk"]

shoppingList.insert("Butter", atIndex: 0)

shoppingList += ["Cheese","Chocolate Spread"]

  比較一下OC中:

[array insertObject:@"dd" atIndex:1];

10.4.數組刪除元素

  使用removeAtIndex方法

var shoppingList:String[] = ["Eggs","Milk","Butter"]

let deleteItem = shoppingList.removeAtIndex(2)

println(deleteItem)

println(shoppingList)

10.5.數組長度

  使用count屬性(和OC中一樣)

var shoppingList:String[] = ["Eggs","Milk","Butter"]

println("The shopping list contains \(shoppingList.count) items.")

10.6.數組遍歷

  1.遍歷方法1

var shoppingList:String[] = ["Eggs","Milk","Butter"]

for item in shoppingList{

    println(item)

}

  2.遍歷方法2

  有循環變量

for(index,value) in enumerate(shoppingList){

    println("Item \(index + 1):\(value)")

}

11.字典

11.1.字典初始化

  基本語法:

[key1:value1,key2:value2,key3:value3]

var airports:Dictionary<String,String> = ["TYO":"Tokyo","DUB":"Dublin"]

11.2.字典追加元素

var airports:Dictionary<String,String> = ["TYO":"Tokyo","DUB":"Dublin"]

airports["LHR"] = "Lonton"

println("The dictionary of airports contains \(airports.count)")

11.3.字典刪除元素

  通過removeValueForKey(key)方法刪除

var airports:Dictionary<String,String> = ["TYO":"Tokyo","DUB":"Dublin"]

if let removedValue = airports.removeValueForKey("DUB"){

    println("The removed airport's name is \(removedValue)")

}
else{

    println("The airports dictionary does not contains a value for DUB")

}

11.4.字典長度

  使用count屬性

println("The count of airport's is \(airports.count)")

11.5.字典遍歷

  1.遍歷字典

var airports:Dictionary<String,String> = ["TYO":"Tokyo","DUB":"Dublin"]

for (airportCode,airportName) in airports{

    println("\(airportCode):\(airportName)")

}

  2.遍歷鍵和值

for airportCode in airports.keys{

    println("Airport code:\(airportCode)")

}

for airportName in airports.values{

    println("Airport name\(airportName)")

}

  3.獲得鍵和值的數組

let airportCodes = Array(airports.keys)

let airportNames = Array(airports.values)

12.控制語句

12.1.分支語句

  1.條件語句if-else

if boolean-expression{

statement1;

}[else if boolean-expression{

statement2;

}]
[else{

statement3;

}]

  2.多分支語句switch

switch some value to consider{

case value1,value2,value3:

respond to value1

default:

otherwise

}

  每個case不需要顯示地添加break,每個case至少有一條語句。可以比較任何類型。

12.2.循環語句

  1.while語句

while condition{

statements

}

  示例:

var i = 100

var r = 0

var s = 0

var t = 0

while i < 1000 {

    r = i / 100 ;

    s = (i - r * 100) / 10;

    t = i - r * 100 - s * 10;

    if(i == r * r * r + s * s * s + t * t * t){

        println("i=\(i)");

    }

    i++

}

  2.do-while語句

do{

statements

}while condition

  示例:

var i = 100

var r = 0

var s = 0

var t = 0

do{

    r = i / 100 ;

    s = (i - r * 100) / 10;

    t = i - r * 100 - s * 10;

    if(i == r * r * r + s * s * s + t * t * t){

        println("i=\(i)");

    }

    i++

}while i < 1000

  3.for語句

for initialization;condition;increment{

statements

}

  示例:

var i = 8

var r = 0

var s = 0

for var j = 0;j <= i;j++ {

    r = j * j;

    s = j * j * j;

    println("\(j)的平方:\(r) \(j)的立方:\(s)");

}

  4.for in語句

  一般用於遍歷集合

  1.遍歷范圍

for index in 1...5{

    println("\(index) times 5 is \(index * 5)");

}

  2.忽略循環變量

let base = 3

let power = 10

var answer = 1

for _ in 1...power{

    answer *= base;

}

println("\(base) to the power of \(power) is \(answer)")

  3.遍歷數組

let names = ["Anna","Alex","Jack"]

for name in names{

    println("Hello,\(name)")

}

  4.遍歷字典

let numberofLegs = ["spider":8,"ant":6,"car":4];

for(animalName,legCount) in numberofLegs{

    println("\(animalName) have \(legCount) legs")

}

  5.遍歷字符串

for character in "Hello"{

    println(character)

}

12.3.跳轉語句

  1. continue:終止當次循環,接着進入下一次循環
  2. break:終止循環;
  3. fallthrough:其他語言沒有的,貫穿的意思,常用於switch語句中,示例如下:

 

 

let integerDescribe = 5

var description = "The number \(integerDescribe) is"

switch integerDescribe{

case 2,3,5:

    description += " a prise number,and also"

    fallthrough

default:

    description += " an integer.";

}

 

    4.return

13.函數

13.1.函數定義

  使用func定義一個函數。調用函數使用它的名字加上小括號中的參數列表。使用->分隔參數的名字和返回值類型。

  函數聲明:

func greet(name:String,day:String) -> String{

    return "Hello \(name),today is \(day)"

}

  函數調用:

greet("Bob", "Tuesday")

13.2.無返回值函數

func sayGoodBye(personName:String){

    println("Goodbye,\(personName)");

}

sayGoodBye("Tony");

13.3.多返回值函數

  使用元組類型返回多個值

func count(string:String) -> (vowels:Int,consonants:Int,others:Int){

    var vowel = 0,consonant = 0,other = 0;

    for character in string{

        switch String(character).lowercaseString{

        case "a","e","i","o","u":

            ++vowel;

        case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":

            ++consonant;

        default:

            ++other;

        }

    }

    return (vowel,consonant,other);

}

let total = count("Some thing is change!");

println("\(total.vowels)元音,\(total.consonants)輔音")

13.4.嵌入函數

func chooseStepFunction(backwards:Bool) -> (Int) -> Int{

    func stepForward(input:Int) -> Int{
        return input + 1
    }

    func stepBackward(input:Int) -> Int{
        return input - 1
    }

    return backwards ? stepBackward : stepForward
}

var currentValue = -4

// moveNearerToZero是一個函數指針
let moveNearerToZero = chooseStepFunction(currentValue > 0)

while currentValue != 0{

    println("\(currentValue)......")

    currentValue = moveNearerToZero(currentValue)

}

14.閉包(Closure)

  語法:

{(parameters) -> return type in

statements

}

  示例:數組排序

  采用函數實現:

let names = ["Chris","Alex","Ewa","Barry","Daniella"]

func backwards(s1:String,s2:String) -> Bool{

    return s1 > s2

}

// sort排序函數,backwards通過排序規則的函數
var reversed = sort(names,backwards)

println(reversed)

  采用閉包實現:

var reversed = sort(names,{(s1:String,s2:String) -> Bool in 

return s1 > s2

})

println(reversed)

15.類與結構體

  類和結構體有很多共性:

  1. 定義屬性存儲數據;
  2. 定義方法執行功能處理;
  3. 定義下標,通過下標訪問它們的值;
  4. 初始化它們的狀態;
  5. 通過擴展(Extension)擴展其功能;
  6. 遵守協議(Protocol),協議提供一種特定的標准功能。

  類比結構體多出的功能:

  1. 能夠繼承另外一個類;
  2. 能夠核對運行期對象的類型;
  3. 析構對象釋放資源;
  4. 引用計數允許一個類實例有多個引用。

15.1.類和結構體的定義

  定義類和結構體:

class SomeClass{

// class definition goes here

}

struct SomeStructure{

// structure definition goes here

}

  示例:

struct Resolution{

var width = 0

var height = 0

}

class VideoMode{

var resolution = Resolution()

var interfaced = false

var frameRate = 0.0

var name:String?

}

15.2.類和結構體的實例化

struct Resolution{

var width = 0

var height = 0

}

class VideoMode{

var resolution = Resolution()

var interfaced = false

var frameRate = 0.0

var name:String?

}

let someResolution = Resolution()

// let someResolution = Resolution(width:10,height:20)

let someVideoMode = VideoMode()

16.屬性

16.1.屬性的存儲

  屬性的主要作用是存儲數據,可以分為常量屬性和變量屬性;

struct FixedLengthRange{

    var firstValue:Int

    let length:Int

}

var rangeOfThreeItems = FixedLengthRange(firstValue:0,length:3)

rangeOfThreeItems.firstValue = 6
// 注意:length是常量屬性,值是不可以修改的

16.2.延時存儲屬性

  延時存儲屬性是初始化時候不分配值,直到第一次使用它。屬性@lazy聲明。

  為什么要用延時存儲屬性?當一個屬性是一個龐大類時,並且這個屬性很少用到,那么就可以考慮使用延時存儲屬性,這樣可以避免大量數據加載到內存中。

class DataImporter{

    var fileName = "data.txt"

}

class DataManager{

    @lazy var importer = DataImporter()

    var data = ""

} 

let manager = DataManager();

manager.data += "Some Data"

manager.data += "Some more data"

println(manager.importer.fileName)

  去掉@lazy關鍵字在playground里面試試,看看有什么不一樣?

16.3.計算屬性

  有的時候一些屬性是通過其他的屬性計算得出的,通過get和set訪問器對其訪問。

// 定義Point
struct Point{

    var x = 0.0,y = 0.0

}

// 定義Size
struct Size{

    var width = 0.0,height = 0.0

}

// 定義Rect
struct Rect{

    var origin = Point()

    var size = Size()

    var center:Point{

    get{

        let centerX = origin.x + (size.width / 2)

        let centerY = origin.y + (size.height / 2)

        return Point(x:centerX,y:centerY)

    }

    set(newCenter){

        origin.x = newCenter.x - (size.width / 2)

        origin.y = newCenter.y - (size.height / 2)

    }

    }

}

var square = Rect(origin:Point(x:0.0,y:0.0),size:Size(width:10.0,height:20.0))

let initialSquareCenter = square.center

square.center = Point(x:15.0,y:15.0)

println("square origin is now at (\(square.origin.x),\(square.origin.y))")

16.4.屬性觀察者

  為了監聽屬性的變化,swift通過了屬性觀察者。

  1. willset觀察者是在存儲之前調用;
  2. didSet新值存儲后調用。
class StepCounter{

    var totalSteps:Int = 0{

    willSet(newTotalSteps){

        println("About to set totalSteps to \(newTotalSteps)")

    }
    didSet{

        if totalSteps >= oldValue{

            println("Added \(totalSteps - oldValue) steps")

        }

    }

    }

}

let stepCounter = StepCounter()

stepCounter.totalSteps = 200

stepCounter.totalSteps = 360

16.5.靜態屬性

  靜態屬性在結構體中使用static定義,類中使用class定義。

struct SomeStructure{

    static var storedTypeProperty = "Some Value"

}

class SomeClass{

    class var computedTypeProperty:Int{

        return 3

    }

}

17.方法

  Swift中的方法是與特定類型(類和結構體)相關的函數

17.1.方法

class Counter{

    var count = 0

    func increment(){

        count++

    }

    func incremmentBy(amount:Int){

        count += amount

    }

    func reset(){

        count = 0

    }

}

let counter = Counter()

counter.increment()

counter.incremmentBy(5)

counter.reset()

17.2.使用self

  self代表當前對象。

struct Point{

    var x = 0.0,y = 0.0

    func isToTheRightOfX(x:Double) -> Bool{

        return self.x > x

    }

}

let somePoint = Point(x:4.0,y:5.0)

if somePoint.isToTheRightOfX(1.0){

    println("This point is to the right of the line where x == 1.0")

}

18.下標

18.1.定義下標

  還記得字典嗎?

var numberOfLegs = ["bird":2,"cat":4,"ant":6]

let birdLeg = numberOfLegs["bird"]

  ["bird"]就是下標

  下標可以在類和結構體中定義

18.2.只讀下標

struct TimesTable{

    let multiplier:Int

    subscript(index:Int) -> Int{

        return multiplier * index

    }

}

let threeTimesTable = TimesTable(multiplier:3)

println("six times three is \(threeTimesTable[6])")

19.繼承

  Swift中的類能夠繼承其他類的屬性、方法等。

19.1.定義基類

class Vehicle{

    var numberOfWheels:Int

    var maxPassengers:Int

    func description() -> String{

        return "\(numberOfWheels) wheels;up to \(maxPassengers)"

    }

    init(){

        numberOfWheels = 0

        maxPassengers = 1

    }

}

let someVehicle = Vehicle()

19.2.定義子類

class Bicycle:Vehicle{

    init() {

        super.init()

        numberOfWheels = 2

    }

}

let bicycle = Bicycle()

println("Bicycle:\(bicycle.description())")

19.3.重寫(Overriding)

  子類能夠重寫父類的方法、屬性、下標。

19.3.1方法重寫

class Vehicle{

    var numberOfWheels:Int

    var maxPassengers:Int

    func description() -> String{

        return "\(numberOfWheels) wheels;up to \(maxPassengers)"

    }

    init(){

        numberOfWheels = 0

        maxPassengers = 1

    }

}

class Car:Vehicle{

    var speed:Double = 0.0

    init() {

        super.init()

        numberOfWheels = 4

        maxPassengers = 5

    }

    override func description() -> String{

        return super.description() + ";" + "traveling at \(speed)"

    }

}

let car = Car()

println("Car:\(car.description())")

19.3.2屬性重寫

class Vehicle{

    var numberOfWheels:Int

    var maxPassengers:Int

    func description() -> String{

        return "\(numberOfWheels) wheels;up to \(maxPassengers)"

    }

    init(){

        numberOfWheels = 0

        maxPassengers = 1

    }

}

class Car:Vehicle{

    var speed:Double = 0.0

    init() {

        super.init()

        numberOfWheels = 4

        maxPassengers = 5

    }

    override func description() -> String{

        return super.description() + ";" + "traveling at \(speed)"

    }

}

class SpeedLimitedCar:Car{

    override var speed:Double{

    get{

        return super.speed

    }
    set{

        super.speed = min(newValue,40.0)

    }

    }

}

let limitedCar = SpeedLimitedCar()

limitedCar.speed = 60.0

println("SpeedLimitedCar:\(limitedCar.description())")

20.構造器(Initializer)

  為了初始化結構體和類等類型的實例屬性。

20.1.默認構造器

struct Fahrenheit{

    var temperature:Double

    init(){

        temperature = 32.0

    }

}

var f = Fahrenheit()  // 調用默認構造器init(),沒有參數和返回值

println("The default temperature is \(f.temperature)")

20.2.自定義構造器

  定義類兩個構造器:init(fromFahrenheit:) 和 init(fromKelvin:)

struct Celsius{

    var temperatureInCelsius:Double

    init(fromFahrenheit fahrenheit:Double){

        temperatureInCelsius = (fahrenheit - 32.0) / 1.8

    }

    init(fromKelvin kelvin:Double){

        temperatureInCelsius = kelvin - 273.15

    }

//    init(fahrenheit:Double){

//        temperatureInCelsius = (fahrenheit - 32.0) / 1.8

//    }

//    

//    init(kelvin:Double){

//        temperatureInCelsius = kelvin - 273.15

//    }

}

let boilingPointOfWater = Celsius(fromFahrenheit:212.0)

let freezingPointOfWater = Celsius(fromKelvin:273.15)

//let boilingPointOfWater = Celsius(fahrenheit:212.0)

//let freezingPointOfWater = Celsius(kelvin:273.15)

21.析構器(Deinitializer)

  析構器與構造器相反,在對象釋放時候調用。

  使用關鍵字deinit,語法如下:

deinit{

}

  實例:

class Player{

    var coinsInPurse:Int

    init(coins:Int){

        println("call init")

        coinsInPurse = coins

    }

    func winCoins(coins:Int){

        coinsInPurse += 10

    }

    deinit{

        coinsInPurse = 0

    }

}

var playerOne:Player? = Player(coins:100)

println("PlayerOne has coins \(playerOne!.coinsInPurse)")

playerOne = nil;

22.擴展(Extension)

  在現有類和結構體的基礎上,擴展新的功能。

  語法:

extension SomeType{

}

extension SomeType:SomeProtocol,AnotherProtocol{

}

  OC中的擴展:

@interface UIImage (UIImageScale)

22.1.計算屬性

extension Double{

    var km:Double{return self * 1000.0}

    var m:Double{return self}

    var cm:Double{return self / 100.0}

    var mm:Double{return self / 1000.0}

}

let oneInch = 25.4.mm

println("OneInch is \(oneInch) meters")

22.2.使用構造器

struct Size{

    var width = 0.0,height = 0.0

}

struct Point{

    var x = 0.0,y = 0.0

}

struct Rect{

    var origin = Point()

    var size = Size()

}

extension Rect{

    init(center:Point,size:Size){

        let originX = center.x - (size.width / 2)

        let originY = center.y - (size.height / 2)

        self.init(origin:Point(x:originX,y:originY),size:size)
    }
}

let centerRect = Rect(center:Point(x:4.0,y:4.0),size:Size(width:3.0,height:3.0))

22.3.方法擴展

extension Int{

    func message() -> String{

        var message = "";

        switch self{

        case 0:

            message = "成功"

        case -1:

            message = "用戶登錄失敗"

        default:

            message = "未知錯誤"

        }

        return message;

    }

}

3.message();

0.message();

(-1).message();

23.協議(Protocol)

  協議是為方法、屬性等定義一套規范,沒有具體的實現。協議能夠被類、結構體等具體實現。

protocol SomeProtocol{

}

struct SomeStructure:SomeProtocol{

}

class SomeClass:SomeProtocol{

}

23.1.屬性

// 1.set和get訪問器
protocol SomeProtocol{

    var mustBeSettable:Int{get set}

    var doesNotNeedToBeSettable:Int{get}

}

// 2.靜態屬性
protocol AnotherProtocol{

    class var someTypeProperty:Int{get set}

}

// 3.只讀
protocol FullyNamed{

    var fullName:String{get}

}

  示例:

protocol FullyNamed{

    var fullName:String{get}

}

struct Person : FullyNamed{

    var fullName:String

}

let john = Person(fullName:"John Appleseed")

class Starship : FullyNamed{

    var prefix:String?

    var name:String

    init(name:String,prefix:String? = nil){

        self.name = name

        self.prefix = prefix

    }

    var fullName:String{

    return (prefix ? prefix! + " " : "") + name

    }

}

var ncc1701 = Starship(name:"Enterprise",prefix:"USS")

println("\(ncc1701.fullName)")

23.2.方法

// 1.定義方法
protocol RandomNumberGenerator{

    func random() -> Double

}


// 2.定義靜態方法
protocol SomeProtocol{

    class func someTypeMethod()

}

  示例:

class LinearCongruentialGenerator:RandomNumberGenerator{

    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0

    func random() -> Double{

        lastRandom = ((lastRandom * a + c) % m)

        return lastRandom / m

    }

}

let generator = LinearCongruentialGenerator()

println("Here's a random number:\(generator.random())")

23.3.把協議作為類型使用

protocol RandomNumberGenerator{

    func random() -> Double

}

class LinearCongruentialGenerator:RandomNumberGenerator{

    var lastRandom = 42.0

    let m = 139968.0

    let a = 3877.0

    let c = 29573.0

    func random() -> Double{

        lastRandom = ((lastRandom * a + c) % m)

        return lastRandom / m

    }

}

class Dice{

    let sides:Int

    let generator:RandomNumberGenerator

    init(sides:Int,generator:RandomNumberGenerator){

        self.sides = sides

        self.generator = generator

    }

    func roll() -> Int{

        return Int(generator.random() * Double(sides)) + 1

    }

}

var d6 = Dice(sides:6,generator:LinearCongruentialGenerator())

for _ in 1...5{

    println("Random dice roll is \(d6.roll())")

}

24.Swift的應用

  在這一部分,我實現了一個小Demo:導航欄和Tab欄結合使用。具體代碼說明如下:

24.1.項目結構說明

  主要文件說明:

  1. AppDelegate:系統委托類;
  2. TabBarViewController:Tab欄管理類;
  3. CustomNavigationController:自定義的導航欄類,在這個類里面,做了4英寸屏和3.5英寸屏的處理;
  4. ViewController文件夾:具體的頁面控制器;
  5. NSStringExt:對String類型的擴展,主要是IOS7的判斷、根據字符串長度返回在控件中顯示的高度(常用於UITableViewCell中自適應調整Cell的高度使用);
  6. .......

 24.2.運行效果截圖

  iPhone 5S截圖:

  iPhone 4S截圖:

 24.3.主要代碼

  AppDelegate里面:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
    {
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        
        var tabbarViewCtrl = TabBarViewController(nibName:nil,bundle:nil);
//        var navigationViewController = UINavigationController(rootViewController:tabbarViewCtrl);
        
        var navigationViewController = CustomNavigationController(rootViewController: tabbarViewCtrl);
        self.window!.rootViewController = navigationViewController;
        
        self.window!.makeKeyAndVisible()
        return true
    }

  TabBarViewController:

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
    {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        
        self.title = "任務";
    }

    override func viewDidLoad()
    {
        super.viewDidLoad()

        configureTabBar();
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    /*******************************************************************************
    * 方法名稱:configureTabBar
    * 功能描述:配置TabBar控件
    * 輸入參數:
    * 輸出參數:
    ******************************************************************************/
    func configureTabBar()
    {
        self.view.backgroundColor = UIColor.whiteColor();
        self.tabBar.hidden = true;  // 隱藏自帶的Tab
        var width = self.view.frame.size.width;
        var height = self.view.frame.size.height;
        
        self.myTabbar = UIView(frame:CGRectMake(0, height - 48 - 64, width, 112));
        let currentVersion = UIDevice.currentDevice().systemVersion;
        
        if (currentVersion.isIos7())
        {
            self.myTabbar!.frame = CGRectMake(0, height - 48, width, 112);
        }
        self.myTabbar!.backgroundColor = UIColor(patternImage:UIImage(named:"tab_bg_ico.png"));
        self.view.addSubview(self.myTabbar);
        self.view.bringSubviewToFront(self.myTabbar);
        
        // 任務
        var btnTask = UIButton.buttonWithType(UIButtonType.Custom) as UIButton;  // 后面必須要加上as UIButton
        btnTask.frame = CGRectMake(0, 0, 80, 48);
        btnTask.tag = 100;
        btnTask.selected = true;
        btnTask.setImage(UIImage(named:"tabtask_sel_ico.png"),forState:UIControlState.Normal);
        btnTask.addTarget(self,action: "tabBarButtonClicked:",forControlEvents:UIControlEvents.TouchUpInside);
        self.myTabbar!.addSubview(btnTask);
        
        // 單據
        var btnBill = UIButton.buttonWithType(UIButtonType.Custom) as UIButton;
        btnBill.frame = CGRectMake(80, 0, 80, 48);
        btnBill.tag = 101;
        btnBill.setImage(UIImage(named:"tabbill_nor_ico.png"),forState:UIControlState.Normal);
        btnBill.addTarget(self,action: "tabBarButtonClicked:",forControlEvents:UIControlEvents.TouchUpInside);
        self.myTabbar!.addSubview(btnBill);
        
        // 查詢
        var btnQuery = UIButton.buttonWithType(UIButtonType.Custom) as UIButton;
        btnQuery.frame = CGRectMake(160, 0, 80, 48);
        btnQuery.tag = 102;
        btnQuery.setImage(UIImage(named:"tabquery_nor_ico.png"),forState:UIControlState.Normal);
        btnQuery.addTarget(self,action: "tabBarButtonClicked:",forControlEvents:UIControlEvents.TouchUpInside);
        self.myTabbar!.addSubview(btnQuery);
        
        // 設置
        var btnSetting = UIButton.buttonWithType(UIButtonType.Custom) as UIButton;
        btnSetting.frame = CGRectMake(240, 0, 80, 48);
        btnSetting.tag = 103;
        btnSetting.setImage(UIImage(named:"tabset_nor_ico.png"),forState:UIControlState.Normal);
        btnSetting.addTarget(self,action:"tabBarButtonClicked:",forControlEvents:UIControlEvents.TouchUpInside);
        self.myTabbar!.addSubview(btnSetting);
        
        var taskViewCtrl = MyTaskViewController(nibName:"MyTaskViewController",bundle:nil);
        var billViewCtrl = MyBillViewController();
        var queryViewCtrl = QueryViewController(nibName:"QueryViewController",bundle:nil);
        var settingViewCtrl = SettingViewController(nibName:"SettingViewController",bundle:nil);
        
        self.viewControllers = [taskViewCtrl,billViewCtrl,queryViewCtrl,settingViewCtrl];
    }
    
    /*******************************************************************************
    * 方法名稱:configureTabBar
    * 功能描述:配置TabBar控件
    * 輸入參數:
        sender:事件源
    * 輸出參數:
    ******************************************************************************/
    func tabBarButtonClicked(sender:UIButton)
    {
        var index       = sender.tag;
        var btnTask     = self.view.viewWithTag(100) as UIButton
        var btnBill     = self.view.viewWithTag(101) as UIButton
        var btnQuery    = self.view.viewWithTag(102) as UIButton
        var btnSetting  = self.view.viewWithTag(103) as UIButton
        
        switch index{
            case 100:  // 任務
                self.title = "任務";
                btnTask.selected    = true;
                btnBill.selected    = false;
                btnQuery.selected   = false;
                btnSetting.selected = false;
                btnTask.setImage(UIImage(named:"tabtask_sel_ico.png"),forState:UIControlState.Normal);
                btnBill.setImage(UIImage(named:"tabbill_nor_ico.png"),forState:UIControlState.Normal);
                btnQuery.setImage(UIImage(named:"tabquery_nor_ico.png"),forState:UIControlState.Normal);
                btnSetting.setImage(UIImage(named:"tabset_nor_ico.png"),forState:UIControlState.Normal);
            case 101:  // 單據
                self.title = "單據";
                btnTask.selected    = false;
                btnBill.selected    = true;
                btnQuery.selected   = false;
                btnSetting.selected = false;
                btnTask.setImage(UIImage(named:"tabtask_nor_ico.png"),forState:UIControlState.Normal);
                btnBill.setImage(UIImage(named:"tabbill_sel_ico.png"),forState:UIControlState.Normal);
                btnQuery.setImage(UIImage(named:"tabquery_nor_ico.png"),forState:UIControlState.Normal);
                btnSetting.setImage(UIImage(named:"tabset_nor_ico.png"),forState:UIControlState.Normal);
            case 102:  // 查詢
                self.title = "查詢";
                btnTask.selected    = false;
                btnBill.selected    = false;
                btnQuery.selected   = true;
                btnSetting.selected = false;
                btnTask.setImage(UIImage(named:"tabtask_nor_ico.png"),forState:UIControlState.Normal);
                btnBill.setImage(UIImage(named:"tabbill_nor_ico.png"),forState:UIControlState.Normal);
                btnQuery.setImage(UIImage(named:"tabquery_sel_ico.png"),forState:UIControlState.Normal);
                btnSetting.setImage(UIImage(named:"tabset_nor_ico.png"),forState:UIControlState.Normal);
            case 103:  // 設置
                self.title = "設置";
                btnTask.selected    = false;
                btnBill.selected    = false;
                btnQuery.selected   = false;
                btnSetting.selected = true;
                btnTask.setImage(UIImage(named:"tabtask_nor_ico.png"),forState:UIControlState.Normal);
                btnBill.setImage(UIImage(named:"tabbill_nor_ico.png"),forState:UIControlState.Normal);
                btnQuery.setImage(UIImage(named:"tabquery_nor_ico.png"),forState:UIControlState.Normal);
                btnSetting.setImage(UIImage(named:"tabset_sel_ico.png"),forState:UIControlState.Normal);
            default:
                println("No Selected Items");
        }
        
        self.selectedIndex = index - 100;
    }

  CustomNavigationController:

class CustomNavigationController: UINavigationController
{
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
    {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }
    
    init(rootViewController: UIViewController!)
    {
        return super.init(rootViewController: rootViewController);
    }

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        let currentVersion = UIDevice.currentDevice().systemVersion;

        if (currentVersion.isIos7())
        {
            self.navigationBar.setBackgroundImage(UIImage(named:"navbg_ico.png").stretchableImageWithLeftCapWidth(20,topCapHeight: 30),forBarMetrics:UIBarMetrics.Default);
        }
        else
        {
            self.navigationBar.setBackgroundImage(UIImage(named:"navbg_ico.png"),forBarMetrics:UIBarMetrics.DefaultPrompt);
        }
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func pushViewController(viewController: UIViewController!, animated: Bool)
    {
        super.pushViewController(viewController,animated:animated);
    }
    
    override func popViewControllerAnimated(animated: Bool) -> UIViewController!
    {
        return super.popViewControllerAnimated(animated);
    }
}

  MyTaskViewController

    override func viewDidLoad()
    {
        super.viewDidLoad()

        self.tableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "Cell");
    }
    
    override func viewWillAppear(animated: Bool)
    {
        var width = self.view.frame.size.width
        var height = self.view.frame.size.height
        
        self.tableView.frame = CGRectMake(0, 0, width, height - 48);
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // =========================================================================
    // Table view data source
    
    func numberOfSectionsInTableView(tableView: UITableView!) -> Int
    {
        return 1;
    }
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
    {
        return 50;
    }
    
    func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat
    {
        return 56;
    }
    
    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        let cell = tableView .dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell;
        var lblBillCode = UILabel(frame:CGRectMake(10,4,140,22));
        lblBillCode.text = "JTBX1404020601";
        lblBillCode.font = UIFont(name: "Arial",size: 16);
        
        cell.addSubview(lblBillCode);
        var lblContent = UILabel(frame:CGRectMake(160,4,150,22));
        lblContent.text = "市內交通費用報銷單";
        lblContent.textAlignment = NSTextAlignment.Right;
        lblContent.font = UIFont(name: "Arial",size: 16);
        cell.addSubview(lblContent);
        
        var lblTime = UILabel(frame:CGRectMake(160,30,150,22));
        lblTime.text = "2014-05-23 22:10:10";
        lblTime.font = UIFont(name: "Arial",size: 14);
        lblTime.textColor = UIColor.grayColor();
        lblTime.textAlignment = NSTextAlignment.Right;
        cell.addSubview(lblTime);
        return cell;
    }
    
    // =========================================================================
    // Table view data delegate
    
    func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!){
        println("row = %d",indexPath.row)
    }

  NSStringExt:

extension String {
    
    /*******************************************************************************
    * 方法名稱:isIos7
    * 功能描述:配置TabBar控件
    * 輸入參數:
    * 輸出參數:true:IOS7及以上系統;false:IOS7以下系統。
    ******************************************************************************/
    func isIos7() -> Bool?
    {
        return self >= "7.0"
    }
    
    func stringHeightWith(fontSize:CGFloat,width:CGFloat)->CGFloat
    {
        var font = UIFont.systemFontOfSize(fontSize)
        var size = CGSizeMake(width,CGFLOAT_MAX)
        var paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .ByWordWrapping;
        var  attributes = [NSFontAttributeName:font,
            NSParagraphStyleAttributeName:paragraphStyle.copy()]
        
        var text = self as NSString
        var rect = text.boundingRectWithSize(size, options:.UsesLineFragmentOrigin, attributes: attributes, context:nil)
        return rect.size.height
    }
} 

  源碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM