首页 > 代码库 > Swift培训

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 = 10var a2 = 20var a = a1 > a2 ? "a1":"a2"

  2.指定数据类型

var a1:Int = 10var a2:Int = 20var a = a1 > a2 ? "a1":"a2"

  3.可以有分号结尾

var a1:Int = 10; var a2:Int = 20var 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  // 二进制17let octalInteger = 0o21  // 8进制17let hexadecimalInteger = 0x11  // 16进制17

5.4.布尔类型

  true和false

let orangesAreOrange = truelet turnipsAreDelicious = false

6.数据类型转换

6.1.整型转换

  不同类型的整数常量或变量所能存储的值域不同,需要显示地转换

let twoThousand:UInt16 = 2000let one:UInt8 = 1//let twoThousandAndOne = twoThousand + one  // 错误let twoThousandAndOne = twoThousand + UInt16(one)  // 正确

6.2.整型与浮点数转换

  整数与浮点数类型之间的转换,需要显示地转换

let three = 3let pointOneFourOneFiveNine = 0.14159let 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 = 3let 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?=404serverResponseCode = 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 = http://www.mamicode.com/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 value1default:otherwise}

  每个case不需要显示地添加break,每个case至少有一条语句。可以比较任何类型。

12.2.循环语句

  1.while语句

while condition{statements}

  示例:

var i = 100var r = 0var s = 0var t = 0while 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 = 100var r = 0var s = 0var t = 0do{    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 = 8var r = 0var s = 0for 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 = 3let power = 10var answer = 1for _ 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 = 5var description = "The number \(integerDescribe) is"switch integerDescribe{case 2,3,5:    description += " a prise number,and also"    fallthroughdefault:    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 instatements}

  示例:数组排序

  采用函数实现:

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 = 0var height = 0}class VideoMode{var resolution = Resolution()var interfaced = falsevar frameRate = 0.0var name:String?}

15.2.类和结构体的实例化

struct Resolution{var width = 0var height = 0}class VideoMode{var resolution = Resolution()var interfaced = falsevar frameRate = 0.0var 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访问器对其访问。

// 定义Pointstruct Point{    var x = 0.0,y = 0.0}// 定义Sizestruct Size{    var width = 0.0,height = 0.0}// 定义Rectstruct 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.centersquare.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 = 200stepCounter.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.0println("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.mmprintln("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    }} 

  源码下载