Swift培训
本篇是Swift内部培训整理的PPT材料,主要内容来源于苹果Swift编程语言官方教程,参考了网上的一些视频课程内容。在教程介绍完之后,本人附带实现了一个项目开发中的常用场景的Demo:基于导航栏和Tab栏的应用。
1.Swift概述
我们先来看一篇文章:《苹果新贵 Swift之前世今生》
Swift是用于设计iOS及Mac OS X应用的一门新语言。
1.1.Swift特点
- Swift保留了C与Objective-C的优点,并摒弃其为了兼容C语言所受的限制;
- Swift吸纳了安全编程模式,并新增了一些现代化功能,使其更易使用、更为灵活、更具乐趣。
- Swift的简洁风格与广受欢迎的成熟框架Cocoa/Cocoa Touch相结合,将为重新构思软件的开发过程带来新机遇;
- Swift内存管理采用ARC风格。
1.2.Swift代码的文件扩展名
*.swift
2.第一个Swift程序
2.1.使用Xcode Project编写
2.2.使用Playground编写
我们可以基于 Playground 做这些事情:
- 学习:通过 Playground 学习 Swift,制作 Swift 教程实现交互式学习,同时还可以培训其他初学者。
- 代码开发:执行算法程序,迅速看到算法结果,跟踪变量;执行绘图程序,即时看到图像结果,及时调整。执行通用代码,查看变量的改变情况。
- 实验性代码:无需创建项目,直接打开一个独立的Playground文件即可编写代码,尝试调用新的 API。
3.常量与变量
let关键词声明常量,var关键词声明变量。
let maximumNumberOfLoginAttempts = 10 // 常量只有在初始化的时候可以赋值 var currentLoginAttempt = 0
4.运算符和表达式
4.1.运算符
- 算术运算符:*、/、+、—、%、++、——
- 关系运算符:>、<、>=、<=、==、!=
- 布尔逻辑运算符:!、&&、||
- 三元运算符:?:
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;
- 在32位平台,Int与Int32宽度一致;
- 在64位平台,Int与Int64宽度一致;
Swift还提供了无符号整数类型UInt。
5.2.浮点型
- 单精度浮点(32位) Float
- 双精度浮点(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.使用可选类型
我们在如下情况下使用可选类型:
- 它有值但不确定;
- 没有任何值。
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.跳转语句
- continue:终止当次循环,接着进入下一次循环
- break:终止循环;
- 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.类与结构体
类和结构体有很多共性:
- 定义属性存储数据;
- 定义方法执行功能处理;
- 定义下标,通过下标访问它们的值;
- 初始化它们的状态;
- 通过扩展(Extension)扩展其功能;
- 遵守协议(Protocol),协议提供一种特定的标准功能。
类比结构体多出的功能:
- 能够继承另外一个类;
- 能够核对运行期对象的类型;
- 析构对象释放资源;
- 引用计数允许一个类实例有多个引用。
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通过了属性观察者。
- willset观察者是在存储之前调用;
- 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.项目结构说明
主要文件说明:
- AppDelegate:系统委托类;
- TabBarViewController:Tab栏管理类;
- CustomNavigationController:自定义的导航栏类,在这个类里面,做了4英寸屏和3.5英寸屏的处理;
- ViewController文件夹:具体的页面控制器;
- NSStringExt:对String类型的扩展,主要是IOS7的判断、根据字符串长度返回在控件中显示的高度(常用于UITableViewCell中自适应调整Cell的高度使用);
- .......
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 } }