本篇是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 =   // 常量只有在初始化的时候可以赋值

var currentLoginAttempt = 

4.运算符和表达式

4.1.运算符

  1. 算术运算符:*、/、+、—、%、++、——
  2. 关系运算符:>、<、>=、<=、==、!=
  3. 布尔逻辑运算符:!、&&、||
  4. 三元运算符:?:

4.2.表达式

  1.不指定数据类型

var a1 = 

var a2 = 

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

  2.指定数据类型

var a1:Int = 

var a2:Int = 

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

  3.可以有分号结尾

var a1:Int = ; var a2:Int = 

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 =   // 表示是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 = 

let one:UInt8 = 

//let twoThousandAndOne = twoThousand + one  // 错误

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

6.2.整型与浮点数转换

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

let three = 

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 = 

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 = (,"Not Found")

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

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

  2.定义方法2

let http200Error = (statusCode:,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 = ""

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?=

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: )

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

  比较一下OC中:

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

10.4.数组删除元素

  使用removeAtIndex方法

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

let deleteItem = shoppingList.removeAtIndex()

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 = 

var r = 

var s = 

var t = 

while i <  {

    r = i /  ;

    s = (i - r * ) / ;

    t = i - r *  - s * ;

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

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

    }

    i++

}

  2.do-while语句

do{

statements

}while condition

  示例:

var i = 

var r = 

var s = 

var t = 

do{

    r = i /  ;

    s = (i - r * ) / ;

    t = i - r *  - s * ;

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

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

    }

    i++

}while i < 

  3.for语句

for initialization;condition;increment{

statements

}

  示例:

var i = 

var r = 

var s = 

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

    r = j * j;

    s = j * j * j;

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

}

  4.for in语句

  一般用于遍历集合

  1.遍历范围

for index in ...{

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

}

  2.忽略循环变量

let base = 

let power = 

var answer = 

for _ in ...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":,"ant":,"car":];

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 = 

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

switch integerDescribe{

case ,,:

    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 = ,consonant = ,other = ;

    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 +
} func stepBackward(input:Int) -> Int{
return input -
} return backwards ? stepBackward : stepForward
} var currentValue = - // moveNearerToZero是一个函数指针
let moveNearerToZero = chooseStepFunction(currentValue > ) while currentValue != { 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 = 

var height = 

}

class VideoMode{

var resolution = Resolution()

var interfaced = false

var frameRate = 0.0

var name:String?

}

15.2.类和结构体的实例化

struct Resolution{

var width = 

var height = 

}

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:,length:)

rangeOfThreeItems.firstValue =
// 注意: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 / ) let centerY = origin.y + (size.height / ) return Point(x:centerX,y:centerY) } set(newCenter){ origin.x = newCenter.x - (size.width / ) origin.y = newCenter.y - (size.height / ) } } } 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 = {

    willSet(newTotalSteps){

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

    }
didSet{ if totalSteps >= oldValue{ println("Added \(totalSteps - oldValue) steps") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = stepCounter.totalSteps =

16.5.静态属性

  静态属性在结构体中使用static定义,类中使用class定义。

struct SomeStructure{

    static var storedTypeProperty = "Some Value"

}

class SomeClass{

    class var computedTypeProperty:Int{

        return 

    }

}

17.方法

  Swift中的方法是与特定类型(类和结构体)相关的函数

17.1.方法

class Counter{

    var count = 

    func increment(){

        count++

    }

    func incremmentBy(amount:Int){

        count += amount

    }

    func reset(){

        count = 

    }

}

let counter = Counter()

counter.increment()

counter.incremmentBy()

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":,"cat":,"ant":]

let birdLeg = numberOfLegs["bird"]

  ["bird"]就是下标

  下标可以在类和结构体中定义

18.2.只读下标

struct TimesTable{

    let multiplier:Int

    subscript(index:Int) -> Int{

        return multiplier * index

    }

}

let threeTimesTable = TimesTable(multiplier:)

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 = 

        maxPassengers = 

    }

}

let someVehicle = Vehicle()

19.2.定义子类

class Bicycle:Vehicle{

    init() {

        super.init()

        numberOfWheels = 

    }

}

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 = 

        maxPassengers = 

    }

}

class Car:Vehicle{

    var speed:Double = 0.0

    init() {

        super.init()

        numberOfWheels = 

        maxPassengers = 

    }

    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 = 

        maxPassengers = 

    }

}

class Car:Vehicle{

    var speed:Double = 0.0

    init() {

        super.init()

        numberOfWheels = 

        maxPassengers = 

    }

    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 += 

    }

    deinit{

        coinsInPurse = 

    }

}

var playerOne:Player? = Player(coins:)

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 / )

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

        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 :

            message = "成功"

        case -:

            message = "用户登录失败"

        default:

            message = "未知错误"

        }

        return message;

    }

}

.message();

.message();

(-).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)) + 

    }

}

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

for _ in ...{

    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(, height - - , width, ));
let currentVersion = UIDevice.currentDevice().systemVersion; if (currentVersion.isIos7())
{
self.myTabbar!.frame = CGRectMake(, height - , width, );
}
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(, , , );
btnTask.tag = ;
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(, , , );
btnBill.tag = ;
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(, , , );
btnQuery.tag = ;
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(, , , );
btnSetting.tag = ;
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() as UIButton
var btnBill = self.view.viewWithTag() as UIButton
var btnQuery = self.view.viewWithTag() as UIButton
var btnSetting = self.view.viewWithTag() as UIButton switch index{
case : // 任务
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 : // 单据
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 : // 查询
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 : // 设置
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 - ;
}

  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(,topCapHeight: ),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(, , width, height - );
} override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} // =========================================================================
// Table view data source func numberOfSectionsInTableView(tableView: UITableView!) -> Int
{
return ;
} func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
{
return ;
} func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat
{
return ;
} func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cell = tableView .dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell;
var lblBillCode = UILabel(frame:CGRectMake(,,,));
lblBillCode.text = "JTBX1404020601";
lblBillCode.font = UIFont(name: "Arial",size: ); cell.addSubview(lblBillCode);
var lblContent = UILabel(frame:CGRectMake(,,,));
lblContent.text = "市内交通费用报销单";
lblContent.textAlignment = NSTextAlignment.Right;
lblContent.font = UIFont(name: "Arial",size: );
cell.addSubview(lblContent); var lblTime = UILabel(frame:CGRectMake(,,,));
lblTime.text = "2014-05-23 22:10:10";
lblTime.font = UIFont(name: "Arial",size: );
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
}

  源码下载

Swift培训的更多相关文章

  1. Swift给每个开发者赢取500万的机会!不看一生后悔。

    [导语] Swift的横空出世,很多有想法的人已经发现其中的蕴含的巨大商机,而很多新手却只是云里雾里,只知道大家最近讨论Swift很欢乐.内行看门道,外行看热闹,说的就是这个理.如果你能把swift用 ...

  2. Swift视频教程,Swift千人学iOS开发编程语言

    此时大家站在同一起跑线.Swift语言将将是下一个风靡程序猿界的编程语言,是否能抢占先机,近在咫尺. 本期推荐Swift编程语言视频教程,内容包含:开发环境基本使用.数据类型和常量.数据自己主动检查和 ...

  3. 我收录整理的优秀OC技术类文章

        自定义导航按钮UIBarButtonItem   关于导航栏的六个小技巧   ios开发的一些小技巧篇一 制作一个可以滑动操作的 Table View Cell - IOS - 伯乐在线 一个 ...

  4. swift UI特殊培训38 与滚动码ScrollView

    有时我们适合页面的全部内容,我们需要使用ScrollView,额外的内容打通滚动. 什么样的宽度和高度首先,定义,健身器材轻松. let pageWidth = 320 let pageHeight ...

  5. Swift语言快速入门

    Swift语言快速入门(首部同步新版官方API文档和语法的Swift图书,确保代码可编译,作者专家在线答疑,图书勘误实时跟进) 极客学院 编著   ISBN 978-7-121-24328-8 201 ...

  6. Swift让编程更简单 人人都是开发者

    全称为苹果全球开发者大会的WWDC,每年的这个时候,都会如这段时间前后所举行的Google I/O 和微软的BUILD开发者会议一样,吸引全球科技媒体的目光.近几年来,因为在会上爆的猛料越来越多,“开 ...

  7. swift错误和异常处理

    异常 (exception) 和错误 (error). 在 Objective-C 开发中,异常往往是由程序员的错误导致的 app 无法继续运行,比如我们向一个无法响应某个消息的NSObject 对象 ...

  8. Swift - 语言指南,来自github学习

    @SwiftLanguage 更新于 2016-6-6,更新内容详见 Issue 55.往期更新回顾详见<收录周报> 这份指南汇集了 Swift 语言主流学习资源,并以开发者的视角整理编排 ...

  9. 《Swift开发指南》

    <Swift开发指南> 基本信息 作者: 关东升    赵志荣 丛书名: 图灵原创 出版社:人民邮电出版社 ISBN:9787115366245 上架时间:2014-8-5 出版日期:20 ...

随机推荐

  1. mr程序无法输出日志进行调试的解决方法

    mr程序无法输出日志进行调试的解决方法 @(Hadoop) yarn开启日志输出设置 在yarn-site.xml文件中添加如下配置: <property> <name>yar ...

  2. in_array() 和array_search的区别

    在判断字符串是否在某个数组里面的时候,我们会经常用到in_array()和array_search这两个函数. 他们的用法都是在数组中搜索给定的值,但是不同的是, in_array()给定的值 val ...

  3. Caused by: org.apache.ibatis.reflection.ReflectionException我碰到的情况,原因不唯一

    映射文件: <select id="selectKeyByUserId"  resultMap="Xxx">        <![CDATA[ ...

  4. 【转】C语言中结构体的位域(bit-fields)

    有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语言又提供了一种数据结构 ...

  5. asp 按钮 调用ajax时 会出现返回错误,尽量使用html按钮进行调用

    asp 按钮 调用ajax时 会出现返回错误,尽量使用html按钮进行调用

  6. Adb分析及获取root权限

    Adb的全称为Android Debug Bridge,起到通过PC对Android系统的调试桥的作用,是一个多用途的工具,它能够执行多种命令,还能提供一个shell.这儿简单介绍一下Adb的代码结构 ...

  7. Android:singleTask + onActivityResult

    解决2个Activity互相跳转,并且栈中只保留每个Activity一个对象的存在. 在2个Activity中分别都要用到onActivityResult,所以就不能用launchMode=" ...

  8. RandomForest&ROC

    # -*- coding: utf-8 -*- # __author__ = 'JieYao' from biocluster.agent import Agent from biocluster.t ...

  9. SSI整合 示例

    sql语句 create table user_c (id varchar(10) primary key,name varchar(20),age int ,address varchar(30); ...

  10. 网络中常见的ping命令协议

    ICMP是"Internet Control Message Ptotocol"(Internet控制消息协议)的缩写.它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之 ...