×

Swift

96
smile丽语
2015.05.29 19:44* 字数 13229

Swift



Day01



1.MySwift

import UIKit





println("Hello Swift!")

var str = "Hello, playground"



//常量

let const = 10

//const = 20 常量有初始值后就不可以再次赋值

//变量

var variable = 10

variable = 20



//整型字面值(十进制)

var x = 5

x = 0015 //前导0是无效的,为了对齐

x = 1_000_000// _无效,为了提高可读性 //1,000,000



//二进制

x = 0b00001111 //二进制前加上0b

//八进制

x = 0o17 //八进制前加上0o

//十六进制

x = 0xF //十六进制前加上0x



//浮点型字面值(默认十进制)

var y = 3.14

y = 1.25E-2 //1.25 X 10^(-2)



//浮点型的十六进制

y = 0xF

y = 0xFp2 //15 X 2^2

y = 0xFp-2 //15 X 2^(-2)







2.基本数据类型

import UIKit



//Swift语言是强类型语言,变量需要明确的类型

//常量和变量必须在使用前声明,用let来声明常量,用var来声明变量

//类型推断

var x = 10

let 🐶🐮 = "dogcow"



//可以在一行中声明多个常量或者多个变量,用逗号隔开

var a = 0.0, b = 1.0, c = 1 //a,b,c



//类型标注

var y : Int //int y

y = 20

var welcomeMessage :String

//welcomeMessage = 10

welcomeMessage = "Welcome to Swift."



//类型转换

var label = "This width is"

var width = "100"

let widthLabel = label + width

var height = 200

let heightLabel = label + String(height)



let apples = 3

let oranges = 5

let appleSummary = "我有\(apples)个苹果,\(oranges)个桔子"



//基本数据类型

var i : Int

i = 100

Int.max

Int.min





var ui : UInt//无符号整型

ui = 10

//ui = -10 无符号整形不能是负数,不可加负号

UInt.max

UInt.min



var i8 : Int8 //8位整数类型

i8 = 127



//Int16,UInt16,Int32,UInt32,Int64,UInt64



var f1 : Float

var f2 : Double



var f3 : Float32 //Float

var f4 : Float64 //Double



//类型别名

typealias MyFloat = Float32

var f5 : MyFloat



//布尔类型,只有两个值true或false,不能是0和1

var isGirl : Bool

var isBoy : Bool

//isGirl = 0

isGirl = 100 > 80





//获取一种类型在内存中的空间大小

sizeof(Int)

sizeof(Int8)

sizeof(Bool)

sizeof(Float)

sizeof(Double)





3.运算符

import UIKit



//赋值运算符

var a, b, c, d, e, f : Int

//a = b = c = d = e = 10 //ERROR

a = 10

b = 20

c = 30



//算术运算符

1 + 2

5 - 3

2 * 3

10 / 3

10.0 / 3



"Hello" + "world"

9 % 4

9 % -4

-9 % 4

-9 % -4 //结果正负就看%左边的值除数本身正负

//支持浮点数

//%左边的值 = 右边的值 X 倍数 + 余数

// 余数 = 左边的值 - 右边的值 X 倍数

3.14 % 2.99 //3.14 - 2.99 X 1

8.15 % 2.34 //8.15 - 2.34 X 3



//单目 ++,--和C语言相同



//比较 >, >=, <, <=, ==, !=和C语言相同



//三目运算符 ? : 和C语言一样



//瑞吉运算符 && || ! & | 和C语言一样



//以下是不同

//1.Swift支持===运算符,专门用于比较两个引用是否指向了同一个对象(在对象部分讲)



//2.新的运算符 ??

var x : Int?

x = nil



let r = (x != nil ? x : 0)

let r2 = x ?? 0 //如果想不为空,结果为想本身;如果为空,结果为0



//3.新运算符 ...(闭区间运算符)

for index in 1...5 {

   println("\(index)")

}



//4.半闭区间运算符 ..<包括前者不包括后者

for index in 1 ..< 5 {//包括1但不包括5

   println("\(index)")

}




4.字符串和字符
import UIKit



//创建空串

var emptyString = ""

var anotherEmptyString = String()

//是否是空串的属性

emptyString.isEmpty



//可变性

let constString = "abc" //不可变

//constString = "def"

var variableString = "hello"//可变

variableString = "hi"



//值类型特征

//在Swift语言中,所有的类型都分为值类型和引用类型两种,比如:Int, Float, Double, String 都是值类型的,而后面要学的对象变量是引用类型的

var str1 = "abc"

var str2 = str1

str1 = "def"

str2//值复制,拷贝了一份,则str2不改变值



//OC中的字符串是引用类型

var str3 = NSMutableString(string: "abc");

var str4 = str3

str3.appendString("def")

str4//引用,地址赋值,则str4会改变值



//SWift中的String类型完全兼容OC中的NSString类的所有方法

var str5 = "HelloWorld.java"

//判断开头hasPrefix

if str5.hasPrefix("Hello") {

   println("字符串以Hello开头")

}

//判断结尾hasSuffix

str5.hasSuffix(".java")

str5.stringByAppendingString("...")

//字符串支持 +加号运算进行连接

str1 + str2 + str5



//以下是字符语法

var ch : Character

ch = "A"

//ch = "AB"

//ch = ""

ch = " "//一个空格也是一个字符,但两个就是错的



//注意类型推断,推断出的类型默认是String

var ch2 = "T"

ch2 = "ABCDEF"//String

var tiger : Character = "🐯"

let dog : Character = "🐶"

//Swift使用Unicode编码,对全世界的字符都进行了编码,汉字也是字符

var ch3 : Character = "中"

var 中国 = "China" //变量名也可以是中文





//特殊字符 \n \t

let wiseWords = "\"我是要成为海贼王的男人\"-路飞"

//使用字符特殊字符

let dollarSign = "\u{24}"

let blackHeart = "\u{2665}"

let sparklingHeart = "\u{1F496}”





5.if语句

import UIKit



var a = 10

//if中条件不需要括号,{}是必须的

if a > 0 {

   println("a是正数")

} else if a < 0 {

   println("a是负数")

}else{

   println("a是0")

}



//条件的结果必须是true或false

//if a {} //ERROR

var x : Int? = nil

if x != nil { //不能写成!x

   println("x不为空")

}



6.Switch语言中的Switch语句,功能强大,语法不同于C
import UIKit



/**

1.完备性(exhaustive),不论表达式的值是多少,switch都应该有一个分支来处理,如果缺少分支,语法错误

2.没有隐式贯穿(NO Implicit Fallthrough),如果一个分支结束,switch语句就结束,(而OC中必须看见break才跳出分支)不会继续向下一个分支执行,除非特殊申请

3.一个case可以有多个匹配模式

4.在case中也可以使用break提前结束switch语句

*/



let x = 6

switch x {

case 1:

   println("x==1")

case 2:

   println("x==2")

case 3, 4, 5, 6, 7, 8:

   if x == 5 {

       println("x==5")

       break;

   }

   println("x>=3 && x<=8")



default:

   println("default")

}



//5.可以显式贯穿

let integerToDescribe = 5

var description = "数值\(integerToDescribe)是"

switch integerToDescribe {

case 2, 3, 5, 7, 11, 13, 19:description += "一个素数,并且是"

   fallthrough //继续向下执行

default:description += "一个整数"

}





//6.可以在case中使用范围 fallthrough

let count = 3_000_000_000_000

let countedThings = "宇宙中的星星数量"

var naturalCount : String

switch count {

case 0:

   naturalCount = "没有"

case 1...9:

   naturalCount = "极少"

case 10...99:

   naturalCount = "成百上千"

case 1000..<1_000_000:

   naturalCount = "成千上万"

default:

   naturalCount = "亿万"

}

println("\(countedThings)有\(naturalCount)个")





//7.数据类型没有限制

let vegetable = "红辣椒"

switch vegetable {

case "芹菜":

   let comment = "加点葡萄干拌到蚂蚁上树"

case "黄瓜", "豆瓣菜":

   let commment = "制作抹茶三明治"

case let x where x.hasSuffix("辣椒"):

   let comment = "是狠辣狠辣的那种\(x)吗?"

default:

   let comment = "来个乱炖得了"

}



7.Swift语言中的循环:For、While
import UIKit



//for in

for index in 1...5 {

   println("\(index) times 10 is \(index * 10)")

}



for x in 1 ..< 5 {

   println("\(x)")

}



for c in "abcdefg" {

   println("\(c)")

}





//3的10次方

let base = 3

let power = 10

var answer = 1

for _ in 1 ... power {// _是占位符

   answer *= base

}

answer



//传统的for循环

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

   println("\(i) ")

}

println()



var i : Int

for i = 0; i < 10; i++ {}

i



//while

//统计1~100的奇数的和

var x = 1

var oddSum = 0

while x < 100 {

   if x%2 != 0 {

       oddSum += x

   }

   x++

}

oddSum







8.可选值(Optionals) 可能值

import UIKit



var x : Int

//变量在没有初始值前,不可使用

//println("\(x)")

//x += 100

x = 0 //有了初始值才可以使用

println("x = \(x)")

//非可选值变量不可以为空

//x = nil



//if x == nil {} //ERROR



//可选值

var y : Int? //可选值默认为nil

println("y = \(y)")

y = 10

//let z = x + y

//可选值和非可选值是两种类型,类型不同,不能在一起参与运算

let z = x + y!





var a : Int = 10

var b : Double = 20

//Int和Double不是一个类型,Swift不会自动将a提升为一个Double,所以编译错误,不能一起运算,而oc中会自动将int(小)提升为Double(大)类型,临时进行运算

//let c = a + b

let c = Double(a) + b







//1.强制解包

let possibleNumber = "123"

//convertedNumber被自动推断为Int?类型(可选值类型)

let convertedNumber : Int? = possibleNumber.toInt()//String -> Int

println("\(convertedNumber)")



if convertedNumber != nil {

   convertedNumber! + 10

}else{

   println("字符串转换整数失败")

}

//对空强制解包依然是空

convertedNumber!

//对空强制解包不会发生任何事(Swift新的规定?),Swift1.2之前对空进行强制解包会蹦

let r = convertedNumber!



//2.可选值绑定

if let actualNumber = possibleNumber.toInt() {

   actualNumber + 10

   println("actualNumber已经不是可选值了")

}else{

   println("转换失败")

}



//3. 隐式解包

var i1 : Int!//拥有隐式解包功能的可选值

i1 = 10

var i2 : Int = 20

let i3 = i1 + i2//i1自动解包了



//4. 可选值的本质

var op1 :Int?

var op2 : Optional//同上面一行







9.元组(Tuples)

import UIKit



//元组

let http404Error = (404, "NotFound")



let onePerson : (Int, String, Double) = (001, "Daniel", 50000.0)

var http200Status = (200, "OK")



//访问

let (status, description) = http404Error

status

description



let (statusCode, _) = http200Status

statusCode



http404Error.0

http404Error.1



onePerson.0

onePerson.1

onePerson.2

//onePerson.3



//onePerson.0 = 002

http200Status.1 = "OKOKOK"



//可读性好

let http500Error = (code:500, description:"Unknown")

http500Error.code

http500Error.description



var anotherPerson = (id:003, name:"Guodh", salary:5000.0)

anotherPerson.name = "Guodenghong"

anotherPerson.salary += 20000.0

anotherPerson.salary





10.//在Switch语句中的元组

import UIKit



let onePoint = (2,3)

switch onePoint {

case (0,0):

   println("在原点")

case (_,0):

   println("在x轴上")

case (0,_):

   println("在y轴上")

case (-2...2, -2...2):

   println("在方框里")

default:

   println("在方框外的任意点")

}





//绑定值

let anotherPoint = (2,3)

switch anotherPoint {

case (let x, 0):

   println("点在y轴上,其值为\(x)")

case (0, let y):

   println("点在x轴上,其值为\(y)")

case let (x, y): //(let x, let y):

   println("点所在的位置为\(x),\(y)")

}





//where子句

let yetPoint = (1, 1)

switch yetPoint {

case let(x, y) where x == y:

   println("点(\(x),\(y))在x==y这条线上")

case let(x, y) where x == -y:

   println("点(\(x),\(y))在x==-y这条线上")

case let(x, y):

   println("点(\(x),\(y))不在这两条斜线上")

}






11.//断言

import UIKit



//C语言语法,用于判断一个条件是否成立,如果条件不成立,则程序直接终止。

//通常用在调试程序时,或者是用于保护一段关键代码



var x = 10

assert(x > 10, "x的值不可以为负数")

println("一段关键代码”)







12.数组

import UIKit



let a = [1, 2, 3]//a是Int数组



var shoppingList : [String] = ["Watch", "iPhone6+", "牙刷", "牙膏"]



//1.查

shoppingList.count

shoppingList.isEmpty



//遍历数组

for shopping in shoppingList {

   println("\(shopping)")

}

//遍历数组并获取每个元素的下标

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

   println("\(index) : \(shopping)")

}

//使用下标运算获取元素

for var i = 0; i < shoppingList.count; i++ {

   println("\(i) : \(shoppingList[i])")

}



//2.增

shoppingList.append("面包")

shoppingList.count

shoppingList += ["牛奶"]

shoppingList.count

shoppingList += ["笔", "纸"]

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





//3.删

shoppingList.removeAtIndex(0)

shoppingList.removeLast()

//shoppingList.removeAll(keepCapacity: true)

println(shoppingList)

//包括2但不包括4,删除2不删除4

shoppingList.removeRange(Range(start:2, end:4))

println(shoppingList)





//4.改

shoppingList[0] = "Apple Watch"

println(shoppingList)

shoppingList[1 ..< 3] = ["饺子", "馄饨"]

println(shoppingList)





//5.空数组的创建

//空数组

var someInts = [Int]()//Array()

var otherInts : [Int] = []//[]相当于空数组

someInts.append(1)

otherInts.append(1)



var anotherInts = Array() //本质

//有初始值的数组

var threeDoubles = [Double](count: 3, repeatedValue: 0.0)

//类型推断出数组是[Double]类型的

var anotherDoubles = Array(count: 3, repeatedValue: 0.0)

let sixDoubles = threeDoubles + anotherDoubles



//6.数组是值类型的

var arr1  = [100, 200, 300]

var arr2 = arr1

arr1[0] = 1111

arr1[1] = 2222

println("\(arr2)")



//OC中的数组是引用类型的

var arr3 : NSMutableArray = ["aaa", "bbb", "ccc"]

var arr4 = arr3

arr3[0] = "AAA"

arr3[1] = "BBB"

println(arr4)





13.//集合Set
import UIKit



var names = Set()

names.count

names.insert("Daniel")

names.insert("ShaSha")

names.insert("ShanShan")

names.insert("Daniel")

//集合无序,元素不可重复

println("\(names)")



//清空set

names = []



//使用数组字面值构建一个set

var favoriteGenres: Set = ["Rock", "Classical", "Hip hop", "Hip hop", "Rock"]

println("\(favoriteGenres)")



//类型推断

var favoriteGenres2: Set = ["Rock", "Classical", "Hip hop", "Rock"]

println("\(favoriteGenres2)")



//访问和修改

favoriteGenres.count

favoriteGenres.isEmpty

//遍历

for genres in favoriteGenres {

   println("\(genres)")

}

//不要在程序中依赖set的顺序

for (index, genres) in enumerate(favoriteGenres){

   println("\(index) : \(genres)")

}







//删除

if let removeGenre = favoriteGenres.remove("Hip hop") {

   println("成功删除:\(removeGenre)")

}else{

   println("Set中没有你要删除的元素")

}

println("\(favoriteGenres)")





//判断某一个元素是否存在

if favoriteGenres.contains("Rock") {

   println("有这种风格")

}else{

   println("没有这种风格")

}



//遍历

for genres in favoriteGenres {

   println("\(genres)")

}

//排序遍历

var genres : Set = ["Jazz", "Classes", "Rock", "Funk"]

for genre in sorted(genres) {

   println("\(genre)")

}



//集合运算

let oddDigits : Set = [1, 3, 5, 7, 9]//奇数

let evenDigits : Set = [0, 2, 4, 6, 8]//偶数

//并集

sorted(oddDigits.union(evenDigits))

//交集

oddDigits.intersect(evenDigits)

let primes : Set = [2,3,5,7]//素数

//把交集去掉,只留下oddDigits剩余的

oddDigits.subtract(primes)

//把交集去掉,留下两类中所有剩下的

oddDigits.exclusiveOr(primes)



let hourseAnimals : Set = ["🐶", "🐱"]

let farmAnimals: Set = ["🐷", "🐔", "🐑", "🐱", "🐶"]

let cityAnimals :Set = ["🐨", "🐭"]

//是不是子集

hourseAnimals.isSubsetOf(farmAnimals)

//是不是超集

farmAnimals.isSupersetOf(hourseAnimals)

//不相交的集合

hourseAnimals.isDisjointWith(cityAnimals)





14.数组

import UIKit



let a = [1, 2, 3]//a是Int数组

var shoppingList : [String] = ["Watch", "iPhone6+", "牙刷", "牙膏"]



//1.查

shoppingList.count

shoppingList.isEmpty



//遍历数组

for shopping in shoppingList {

   println("\(shopping)")

}

//遍历数组并获取每个元素的下标

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

   println("\(index) : \(shopping)")

}

//使用下标运算获取元素

for var i = 0; i < shoppingList.count; i++ {

   println("\(i) : \(shoppingList[i])")

}



//2.增

shoppingList.append("面包")

shoppingList.count

shoppingList += ["牛奶"]

shoppingList.count

shoppingList += ["笔", "纸"]

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



//3.删

shoppingList.removeAtIndex(0)

shoppingList.removeLast()

//shoppingList.removeAll(keepCapacity: true)

println(shoppingList)

//包括2但不包括4,删除2不删除4

shoppingList.removeRange(Range(start:2, end:4))

println(shoppingList)



//4.改

shoppingList[0] = "Apple Watch"

println(shoppingList)

shoppingList[1 ..< 3] = ["饺子", "馄饨"]

println(shoppingList)



//5.数组的创建

//空数组

var someInts = [Int]()//Array()

var otherInts : [Int] = []//[]相当于空数组

someInts.append(1)

otherInts.append(1)



var anotherInts = Array() //本质

//有初始值的数组

var threeDoubles = [Double](count: 3, repeatedValue: 0.0)

//类型推断出数组是[Double]类型的

var anotherDoubles = Array(count: 3, repeatedValue: 0.0)

let sixDoubles = threeDoubles + anotherDoubles



//6.数组是值类型的

var arr1  = [100, 200, 300]

var arr2 = arr1

arr1[0] = 1111

arr1[1] = 2222

println("\(arr2)")



//OC中的数组是引用类型的

var arr3 : NSMutableArray = ["aaa", "bbb", "ccc"]

var arr4 = arr3

arr3[0] = "AAA"

arr3[1] = "BBB"

println(arr4)



//常量数组

let constArr = [1,2,3,4,5]

//constArr[0] = 10







15.二维数组

import UIKit



//n行n列

let n = 3

assert(n % 2 != 0, "n只能是奇数")

var nine = [[Int]](count: n, repeatedValue: [Int](count: n, repeatedValue: 0))



var row = 0 //行

var col = n / 2 //列



for var i = 1; i <= n*n; i++ {

   nine[row][col] = i

   //计算下一个数的位置

   row--

   col++

   if (row<0 && col>=n) {

       row += 2

       col--

   }else if(row < 0){

       row = n - 1

   }else if(col >= n){

       col = 0

   }else if(nine[row][col] != 0){

       row += 2

       col--

   }

}

for row in nine{

   println("\(row)")

}






//票箱

let ballot = ["Daniel", "ShaSha", "ShanShan", "Daniel", "Daniel", "ShaSha", "Lily", "ShaSha", "Daniel", "Daniel"]

//统计每个人的票数

var vote = [String:Int]()//结果



for name in ballot{

   if let value = vote[name] {

       vote[name] = value + 1

   }else{

       vote[name] = 1

   }

}

println("\(vote)")






Day02



1.函数

import UIKit



func sayHello() {

   println("Hello")

}



sayHello()



//一个参数,一个返回值

func sayHello(name:String)->String {

   let res = "Hello" + name

   return res

}

let result = sayHello("Daniel")



//两个参数,没有返回值

func sayHello(name:String, otherName:String)->Void {

   println("Hello\(name) and \(otherName)")

}

sayHello("Daniel", "ShaSha")







//返回多个值(其实就是返回一个元组)

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

   //多少个元音,多少个辅音,多少个其他字符

   var v = 0, c = 0, o = 0

   for ch in string.lowercaseString {

       switch ch  {

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

               v++

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

               c++

           default:

               o++

       }

   }

   return (v, c, o)

}

let cntRes = count("Hello, Nice to meet you!")

cntRes.vowels

cntRes.consonants

cntRes.others




2.函数的形参,内部名和外部名

import UIKit



//name 是内部名,也叫局部名,只能在函数的内部使用

func fa(name:String){

   println("\(name)")

}



fa("Daniel")



//一个参数两个名字:username是外部名,name是内部名

func fb(username name:String){

   println("使用内部名:\(name)")

}

//外部名的主要功能是提高程序的可读性

fb(username: "ShaSha")



func initWithName(name:String, age a:Int, salary s:Double){}

initWithName("Daniel", age: 32, salary: 80000)



func initWithX(x:Int, andY y:Int){}

initWithX(10, andY:20)



//有时需要内部名和外部名一样,x和y即是内部名,也是外部名

func point(#x:Int, #y:Int){}

point(x: 10, y: 20)







3.函数参数的默认值

import UIKit



//参数的默认值,函数功能更加灵活

func getString(a:[Int], s:String=" ", f:Bool = false)->String{

   var str = ""

   if f {

       str += "["

   }

   for var i=0; i
   {

       str += String(a[i]) + s

   }

   str += String(a[a.count - 1])

   if f {

       return str + "]"

   }

   return str

}

let a = [1,2,3,4,5]

getString(a)

//带默认值的参数名自动是外部名

getString(a, s: "-")

getString(a, s:"-", f: true)

getString(a, f: true)





4.常量形参和变量形参

import UIKit



//Swift中函数参数默认为常量,不可改变

func fa(x:Int){

   //x += 10

   println("x")

}



//形参是变量

func fb(var x:Int){

   x += 10

   println("x=\(x)")

}



/*

   将字符串按指定宽度右对齐

   alignRight("Hello", 8, "#")->

   ###Hello

*/



func alignRight(var string:String, cnt:Int, pad:Character)->String{

   //count(string)获取一个字符串的长度

   let amountToPad = cnt - count(string)

   for _ in 1...amountToPad {

       string = String(pad) + string

   }

   return string

}

alignRight("Hello", 10, "#")





5.输入输出参数(In out parameter)

import UIKit



//输入输出参数相当于直接操作实参

func swap(inout a:Int, inout b:Int) {

   let t = a

   a = b

   b = t

}



var x = 10

var y = 20

swap(&x, &y)

x

y



func fa(var x:Int){

   x++

}

var a = 10

fa(a)

a



func fb(inout x:Int){

   x++

}

fb(&a)

a






6.函数的类型(Function Types)

import UIKit



//类型为:(Int,Int)->Int

func addTwoInts(a:Int, b:Int)->Int{

   return a + b

}

//类型为:(Int,Int)->Int

func mulTwoInts(a:Int, b:Int)->Int{

   return a * b

}



var f : (Int, Int)->Int

f = addTwoInts

f = mulTwoInts

//将函数变量直接当函数来调用

f(10, 20)

//类型:()->()

func sayHello(){

   println("Hello")

}

//f = sayHello



//可以将函数当做另一个函数的参数来传递

func printMathResult(a:Int, b:Int, f:(Int,Int)->Int){

   println("result:\(f(a,b))")

}

printMathResult(10, 20, addTwoInts)

printMathResult(10, 20, mulTwoInts)



var fs :[(Int,Int)->Int] = [addTwoInts, mulTwoInts]

fs[0](10, 20)

fs[1](20, 30)





7.函数作为参数传递

import UIKit



//冒泡排序,记住!!!

func rule1(a:Int, b:Int)->Bool {

   return a > b

}



func rule2(a:Int, b:Int)->Bool {

   return a < b

}



func rule3(a:Int, b:Int)->Bool {

   return a%3 > b%3

}





func sortInts(inout data:[Int], f:(Int,Int)->Bool = rule1){

   for var i = 0; i
   {

       for var j = 0; j
       {

           if f(data[j] , data[j+1])

           {

               swap(&data[j], &data[j+1])

           }

       }

       println("\(data)")

   }

}



var arr = [9,2,3,7,5,6,1,8,4,0]

sortInts(&arr, f:rule1)

println("\(arr)")



//Swift语言提供的排序函数

sort(&arr, rule3)

println("\(arr)")

let res = sorted(arr)

println("\(res)")



C语言中的冒泡排序!!!

#include

void sort(int *a, int n)

{

//printf("sizeof(a)=%ld\n", sizeof(a));

for(int i=0; i
for(int j=0; j
if(a[j]>a[j+1]){

int t = a[j];

a[j] = a[j+1];

a[j+1] = t;

}

}

}

}

void print(int *a, int n)

{

for(int i=0; i
printf("%d ", a[i]);

}

printf("\n");

}



int main()

{

int a[] = {1,2,3,4,5,6,7,8,9,0};

sort(a, 10);

print(a, 10);

return 0;

}




8.函数的嵌套

import UIKit



func chooseStep(backward:Bool)->(Int)->Int {

   //向前走一步

   func stepForward(input:Int)->Int {

       return input + 1

   }

   //向后走一步

   func stepBackward(input:Int)->Int {

       return input - 1

   }

   return backward ? stepBackward : stepForward

}



var currentValue = 3

let moveNearerToZero = chooseStep(currentValue > 0)

while currentValue != 0 {

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

   currentValue = moveNearerToZero(currentValue)

}

println("Zero!")







Day03



闭包:

Swift ==> Closures

Smalltalk   Ruby  OC   ==> Block

Python C++(11) Lisp  ==> Lambda

Javascript (JS) ==>  Anonymous Function(匿名函数)



Swift中的闭包本质上是一个函数,一般将闭包函数称为闭包表达式。

闭包表达式的语法如下:

{

(parameters)->returnType    in

语句...

return xxx

}



OC中的Block:

^returnType(parameters){

//…

return xxx;

}



1.闭包1

import UIKit



func rule(a:Int, b:Int)->Bool {

   return a > b

}



func sortInts(inout data:[Int], f:(Int,Int)->Bool = rule ){

   for var i=0; i
       for var j=0; j
           if f(data[j],data[j+1]) {

               swap(&data[j], &data[j+1])

           }

       }

       println("\(data)")

   }

}



var a = [4,1,2,5,3,9,0,6,8,7];

//闭包的本质是函数,凡是要函数的地方都可以给闭包

sortInts(&a, f: {(a:Int,b:Int)->Bool in

   return a > b

})

println("\(a)")



//Swift的类型推断功能可以推断出闭包中的参数和返回值类型,所以可以不用提供

sortInts(&a, f: {(a,b) in return a > b})



//当闭包中只是一条语句时,return可以省略不写

sortInts(&a, f: {(a,b) in a > b})

//闭包中的参数可以直接使用$0,$1,$2...来代替

sortInts(&a, f: {$0 > $1})

//如果只有两个参数,可以将参数直接省略

sortInts(&a, f: <)

println("\(a)")





2.闭包2

import UIKit



var a = [3,2,1,4,9,8,0,5,7,6]

sort(&a, {(x, y) in return x%3 < y%3})

println("\(a)")



sort(&a, {$0 < $1})

println("\(a)")



sort(&a, >)

println("\(a)")



let r1 = sorted(a, {$0 < $1})

println("\(r1)")



var names = ["aaa","bbb","ccc"]

sort(&names, <)

println("\(names)")



//拖尾闭包(Trailing Closures)

//最后一个参数

sort(&a) {

   (x, y)->Bool in return x%3 < y%3

}



//123==》壹贰叁

let digitNames = [0:"零",1:"壹",2:"贰",3:"叁",4:"肆",5:"伍",6:"陆",7:"柒",8:"捌",9:"玖"];

let numbers = [15, 56, 520]

let result = numbers.map({(var number:Int)->String in var output = ""

   while number > 0 {

       output = digitNames[number % 10]! + output

       number /= 10

   }

   return output//壹伍, 伍陆, 伍贰零

})

println("\(result)”)







3.枚举:Enumerations

import UIKit



enum CompassPoint {

   case North

   case South

   case East

   case West

}

//定义枚举类型的变量

var p : CompassPoint

p = CompassPoint.North

//自动类型推断

p = .East

//不能推断时需要写全

var q = CompassPoint.North



//在Switch语句中

switch p {

case .North:

   println("北")

case .South:

   println("南")

case .East:

   println("东")

case .West:

   println("西")

}



//时机开发中使用枚举, .System是一个枚举值

var button: UIButton = UIButton.buttonWithType(.System) as! UIButton





//原始值(Raw Value),裸值

enum Week : Int {

   case SUN = 0

   case MON = 1, TUE, WED, THU, FRI, SAT

}



var w : Week

w = .SUN

//枚举值==>原始值

let sunValue : Int = w.rawValue

w = .WED

w.rawValue



//原始值==>枚举

let week = Week(rawValue: 5)//可选值

if week == .FRI {

   println("是星期五")

}



let week2 = Week(rawValue: 7)//nil









4.类和结构体屏幕快照 2015-05-20 下午6.19.24.png

import UIKit

//以下都是结构体类型(当然都就是值类型)

var i : Int

var f : Float

var s : String

var a : Array

var d : Dictionary

var set : Set



//结构体

struct Resolution {

   var width = 0 //属性

   var height = 0 //属性

}



//类,类中的所有属性都必须在使用前初始化

class VideoMode {

   var resolution = Resolution() //属性

   var interloaced = false //逐行扫描

   var frameRate = 0.0 //帧率

   var name:String? //可选值属性

}



//创建实例(Create instance)

var someResolution = Resolution()

var someVideoMode = VideoMode()



//访问属性

someResolution.width = 1024

someResolution.height = 768

someVideoMode.resolution = someResolution

someVideoMode.interloaced = true

someVideoMode.name = "虎妈猫爸"

someVideoMode.frameRate = 60



//结构体是值类型

var otherResolution = someResolution

someResolution.width = 2048

someResolution.height = 1536

println("\(otherResolution.width),\(otherResolution.height)")

//类是引用类型

var otherVideoMode = someVideoMode

someVideoMode.frameRate = 100

someVideoMode.name = "Breaking Bad"

println("\(otherVideoMode.frameRate), \(otherVideoMode.name!)");



//专门用于判断两个引用是否指向了同一个对象的运算符:===

//不可以使用==来判断两个引用是否指向同一个对象

//==是用来判断两个对象的内容是否相等(相当于OC中的isEqual方法),要使用==,必须重写==运算符函数

if someVideoMode === otherVideoMode {

   println("这两引用指向了同一个对象")

}

//不能使用===比较结构体

//someResolution === otherResolution



//结构体的逐一构造器

struct Point {

   var x : Float

   var y : Float

}

//Swift要确保实例中的属性都有初始值

let point = Point(x:10, y:20)



struct Size {

   var width : Float

   var height : Float

}



struct Rect {

   var origin : Point

   var size : Size

}

let rect = Rect(origin:Point(x:0, y:0), size:Size(width:200, height:120))



var cgRect : CGRect

cgRect = CGRect(origin: CGPoint(x: 10, y: 20), size: CGSize(width: 100, height: 80))

cgRect = CGRectMake(8, 8, 100, 60)

cgRect = CGRect(x: 10, y: 10, width: 120, height: 40)







5.存储属性和计算属性(Properties)

import UIKit



struct FixedLengthRange {

   // 存储属性,在内存中有空间保存值

   var firstValue : Int // 存储属性

   let length : Int // 常量属性

}



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

three.firstValue = 2

//three.length = 5   ERROR x  因为是常量let



// 计算属性

struct Point {

var x = 0.0 , y = 0.0

}



struct Size {

   var width = 0.0 , height =  0.0

}



struct Rect {

   var origin = Point()

   var size = Size()

   // center属性是计算属性

   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 (p) {

       let originX = p.x - size.width / 2

           let originY = p.y - size.height / 2

           origin = Point(x: originX, y: originY)

       }

   }

}



func printPoint(p:Point){

   println("\(p.x),\(p.y)")

}



var r = Rect()

r.origin = Point(x: 2, y: 2)

r.size = Size(width: 3, height: 2)

r.center

r.origin.x += 10

r.origin.y += 20

printPoint(r.center)



r.center = Point(x: 40, y: 60)

printPoint(r.origin)







6.延迟属性

import UIKit



//此类用于导入一个数据文件,当创建此类的对象时,数据被加载,由于文件比较大,所以加载数据需要一段时间

class DataImporter {

   //这是一个内容非常多的文件

   var filename = "data.txt"

   //....

}



class DataManager {

   //这是一个延迟加载属性,只有当读取这个属性的值时才会加载到内存。这个属性加载时太慢了,且会占用大量的内存,所以,能不加载就不加载

   lazy var importer = DataImporter()

}



let manager = DataManager()

manager.importer//此时必须加载属性的内容





7.属性监视器(Property Observer), 观察器

import UIKit



var indicator : Int = -10000



class StepCounter {

   //一个属性最多可以有两个监视器,一个willSet,一个是didSet

   var totalSteps : Int = 0 {

       willSet {//在属性值变化前调用

           println("属性马上会变成:\(newValue)")

           indicator = newValue

       }

       didSet {//属性值发生变化后调用

           println("属性的值已发生变化,变化前是:\(oldValue)")

           indicator = oldValue

       }

   }

}



var counter = StepCounter()

counter.totalSteps = 5

counter.totalSteps = 10



//全局变量也可以加监视器

var globle : Int = 0 {

willSet {

   println("全局变量将要变成:\(newValue)")

   indicator = newValue

}

}

globle = 100





if true {

   //局部变量其实也可以加监视器

   var localVariable = 0 {

       willSet {

           println("局部变量将要变成:\(newValue)")

           indicator = newValue

       }

   }

   localVariable = 100

}





8.实例属性(instance property)和类型属性(type property)

//总结:

//不加static的是实例属性,加static的是类型属性。实例属性只能通过实例来访问,不能通过类型来访问。同样,类型属性只能通过类型来访问,不能通过实例来访问

import UIKit



struct SomeStruct {

   //实例属性:只能通过实例访问的属性

   var instanceProp : Int = 0

   //类型属性:只能通过类型来访问的属性

   static var typeProp:Int = 0

   //计算类型属性

   static var calTypeProp:Int {

       return 100

   }

}

var ss = SomeStruct()

ss.instanceProp = 10

//SomeStruct.instanceProp //ERROR

SomeStruct.typeProp = 10 //OK

//ss.typeProp = 20 //ERROR



class SomeClass {

   //实例属性

   var instanceProp:Int = 0

   //类型属性

   static var typeProp:Int = 0

   //计算类型属性

   static var calTypeProp:Int {

       return 100

   }

}





Day04



1.方法1

import UIKit



class Counter {

   var count = 0

   //实例方法 instance method

   //实例方法中可以直接访问属性

   func increment() {

       count++

   }

   func incrementBy(amount: Int) {

       count += amount

   }

   //重载(overload)

   //类型中的方法的第二个参数开始,参数名默认即是内部名,也是外部名.也就是说,默认从第二个参数开始加#号

   func incrementBy(amount:Int, numberOfTimes: Int) {

       count += amount * numberOfTimes

   }

}



let counter = Counter()

counter.increment()

counter.count

//Counter.increment  ERROR ×

counter.incrementBy(10)

counter.count



counter.incrementBy(10, numberOfTimes: 5)





2.方法参数的外部名

import UIKit



class Point {

   var x = 0.0, y = 0.0

   //可以给每个参数起外部名

   func set(x _x:Double, y _y:Double) {

       x = _x

       y = _y

   }

   //可以将第二个参数的默认外部名改掉

   func setX(x:Double, andY y:Double) {

       self.x = x

       self.y = y

   }

   //可以使用占位符取消第二个参数的默认外部名

   func set1(_x:Double, _ _y:Double) {

       x = _x

       y = _y

   }

   //可以将第一个参数名用#也变成外部名

   func set2(#x:Double, y:Double) {

       self.x = x

       self.y = y

   }

}

let p = Point()

p.set(x: 10, y: 20)

p.setX(10, andY: 20)

p.set1(10, 20)

p.set2(x: 10, y: 20)




3.变异方法(mutating method)

import UIKit



struct Point {

   var x = 0.0, y = 0.0

   //struct中的方法默认为只读方法,只能读取当前实例的属性的值,不能修改属性的值

   //但是,如果方法前加了关键字mutating,那么方法就可以修改属性的值了,加了mutating method的方法就是变异方法

   mutating func moveByX(_x:Double, y _y:Double) {

       x += _x

       y += _y

   }

}

var p = Point()

p.moveByX(10, y: 20)



//变异方法只存于值类型(struct, enum)

//枚举类型中的mutating方法

enum TriStateSwitch {

   case Off, Low, High

   mutating func next() {

       switch self {

       case .Off:

           self = .Low

       case .Low:

           self = .High

       case .High:

           self = .Off

       }

   }

}

var mySwitch = TriStateSwitch.Off

mySwitch.next()//.Low

mySwitch.next()//.High

mySwitch.next()//.Off





4.类型方法,类似于OC中的类方法(+)

import UIKit



class SomeClass {

   //类型方法

   class func someTypeMethod() {}

}

//只能通过类型来调用实例方法

SomeClass.someTypeMethod()

let some = SomeClass()

//不能通过实例来调用类型方法

//some.someTypeMethod()



struct SomeStruct {

   static func typeMethod(){}

}

SomeStruct.typeMethod()

//buttonWithType就是类型方法

let button = UIButton.buttonWithType(.System)





5.下标运算subscript

import UIKit



class MyArray {

   var array = [Int]()

   func add(x:Int){

       array.append(x)

   }

   var size : Int {

       return array.count

   }

   //类就支持下标运算了

   subscript(index:Int)->Int {

       get {

           return array[index]

       }

       set {

           array[index] = newValue

       }

   }

}



var arr = MyArray()

arr.add(100)

arr.add(200)

arr.add(300)

arr.size

arr[0] = 111

arr[1] = 222

for var i=0; i
   println("\(arr[i])")

}



//矩阵类, 多少行, 多少列

struct Metrix {

   var grid: [Double]//保存矩阵的数据

   let rows: Int //总行数

   let cols: Int //总列数

   //初始化方法,创建实例时自动调用

   init(rows:Int, cols:Int){

       self.rows = rows

       self.cols = cols

       self.grid = [Double](count: rows*cols, repeatedValue: 0.0)

   }

   //判断行和列是否越界

   func indexIsValidForRow(row:Int, column:Int)->Bool {

       return row >= 0 && row < self.rows && column >= 0 && column < self.cols

   }

   subscript(row:Int, col:Int)->Double {

       set {

           assert(indexIsValidForRow(row, column: col), "下标越界")

          grid[row * cols + col] = newValue

       }

       get {

           assert(indexIsValidForRow(row, column: col), "下标越界")

           return grid[row*cols+col]

       }

   }

}

var m = Metrix(rows: 3, cols: 4)

m[0, 0] = 10

m[0, 1] = 20

m[0, 2] = 30

m[0, 3] = 40

m[1, 0] = 50

m[1, 1] = 60 //1 x 4 + 1

m[1, 2] = 70 //1 x 4 + 2 = 6



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

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

       print("\(m[i, j])")

   }

   println()

}







6.访问控制

import UIKit



//访问控制修饰符

//internal是默认的,在本模块范围内可访问

/*internal*/ class ClassA{}

//private 私有类

private class ClassC{}

//public 在任何位置都可访问

public class ClassB {

   //可以任何位置访问的属性

   public var propA:Int = 0

   //在本模块(本项目)内部访问

   /*internal*/ var propB:Int = 0

   //私有属性,只能在本类内部访问

   private var propC:Int = 0

   

   public func methodA() {}

   func methodB(){}

   //私有方法,只能在本类内部调用

   private func methodC(){}

   

   //新语法:

   //属性count的set是私有的,而get是公开的(这个属性只有我自己能改,但大家不能修改,只可读)

   public private(set) var count : Int = 0

   

}







7.继承(Inheritance)

import UIKit



//基类(Base class),没有父类的类

class Vehicle {

   var currentSpeed = 0.0

   var description : String {

       return "当前的速度是每小时\(currentSpeed)公里"

   }

   func makeNoise(){

       //...

   }

}

//子类,派生类,继承了父类Vehicle

class Bicycle : Vehicle {

   var hasBasket = false

}

class Tandem : Bicycle {

   var currentNumberOfPassengers = 0

}



let bi = Bicycle()

bi.currentSpeed = 25

bi.hasBasket = true

bi.makeNoise()



let tandem = Tandem()

tandem.currentSpeed = 20

tandem.hasBasket = false

tandem.currentNumberOfPassengers = 2

tandem.description

tandem.makeNoise()



//方法重写(method override)  覆盖

class Train : Vehicle {

   override func makeNoise() {

       println("咣当咣当...")

   }

   

   func takePassenger(){

       println("火车拉了很多人")

   }

}



let t = Train()

t.makeNoise()

t.takePassenger()



//多态

var r : Vehicle = Train()

r.makeNoise()

//r.takePassenger()





//属性的重写

class Car : Vehicle {

   var gear = 1 //档位

   //重写了计算属性

   override var description : String {

       return super.description + "在\(gear)档"

   }

   //存储属性不能重写

   //override var currentSpeed = 0.0

}



let car = Car()

car.gear = 3

car.currentSpeed = 50

car.description



//给继承来的存储属性增加监视器

class AutomaticCar : Car {

   //加监视器,必须加override

   override var currentSpeed : Double {

       willSet {

           gear = Int(newValue / 10.0) + 1

       }

   }

}



let autoCar = AutomaticCar()

autoCar.currentSpeed = 60

autoCar.gear

autoCar.currentSpeed = 30

autoCar.gear


instance method  实例方法

type method 类型方法       class method 类方法  +

type (class, struct, enum)



面向对象的三大特性: 封装,继承,多态



1. 封装

将具体的实现隐藏起来,只给外界公开访问接口

@interface Sample : NSObject

@property(nonatomic, strong, readonly) NSString *name;

@end



@interface Sample ()

//在.m中,将属性name重新声明为可读可写

@property(nonatomic, strong, readwrite) NSString *name;

@end

@implementation Sample

- (void)modify

{

self.name = “Daniel”;

}

@end



2. 继承

子类(Sub class)  父类(Super class)  基类(Base class)

Swift中,继承是单继承的。但是,Swift中的类并不一定非得有父类。Swift没有类似NSObject的根类,没有父类的类叫基类。





8.构造器(Initializer)

构造器

构造器(initializer)是特殊的方法

构造器没有返回值

构造器的主要目的是让实例(对象或结构体变量)在使用前完成初始化(构造器就是为初始化实例的)

import UIKit



struct Fahrenheit {

   var temperature : Double

   //构造器(Initializer),构造方法,构造函数,初始化器

   init() {

       println("init()")

       temperature = 32.0

   }

}



let f = Fahrenheit()



/*语法:

1.当创建一个实例时,实例的构造器一定会被调用

2.一个类型中至少会有一个构造器,如果没有,编译器会帮我们自动生成一个

3.构造器方法中的每一个参数名都默认为既是内部名,也是外部名

4. 一个类型的构造器可以有多个,多个构造器之间形成重载(overload)关系

5. 构造器是自动调用的,不允许程序员主动调用

*/



struct Celsius {

   var temperaturInCelsius = 0.0

   init(fahrenheit:Double) {

       temperaturInCelsius = (fahrenheit - 32) / 1.8

   }

   init(fromKelvin kelvin:Double){

       temperaturInCelsius = kelvin - 273.15

   }

}

//方法参数的外部名

let c = Celsius(fahrenheit: 39.0)

let c2 = Celsius(fromKelvin: 290)



struct Color {

   let red, green, blue :Double

   //逐一构造器(自动生成)

   init(red:Double, green:Double, blue:Double)

   {

       println("init(red,green,blue)")

       self.red = red

       self.green = green

       self.blue = blue

   }

   //取消所有参数的外部名

   init(_ red:Double, _ green:Double, _ blue:Double)

   {

       println("init(red,green,blue)")

       self.red = red

       self.green = green

       self.blue = blue

   }

   //专门用于创建灰色的构造器

   init(white:Double)

   {

       println("init(red,green,blue)")

       self.red = white

       self.green = white

       self.blue = white

   }

}

let color = Color(red: 0.5, green: 0.9, blue: 0.3)

let color2 = Color(0.9, 0.8, 1.0)

let gray = Color(white: 0.5)



//类中的属性要么都是默认值

class ShoppingListItem1 {

   var name : String = ""

   var quantity : Int = 1

   var purchased : Bool = false

}

//要么是可选值属性

class ShoppingListItem2 {

   var name : String? //可选值

   var quantity : Int = 1

   var purchased : Bool = false

}

//要么就在init中对其进行初始化

class ShoppingListItem3 {

   var name : String

   var quantity : Int

   var purchased : Bool

   

   init(name:String, quantity:Int, purchased:Bool) {

       self.name = name

       self.quantity = quantity

       self.purchased = purchased

   }

}





9.结构体的构造器代理Initializer Delegation

构造器代理:

在构造器中调用另外一个构造器来完成初始化工作

为了方便构造实例

import UIKit



struct Point {

   var x = 0.0, y = 0.0

}



struct Size {

   var width = 0.0, height = 0.0

}



struct Rect {

   var origin = Point()

   var size = Size()

   init(){}

   init(origin:Point, size:Size) {

       self.origin = origin

       self.size = size

   }

   // Initializer Delegation(构造器代理)

   //通过调用另一个构造器实现初始化效果

   init(center:Point, size:Size) {

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

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

       let origin = Point(x: originX, y: originY)

       //可以在构造器中调研另一个构造器

       self.init(origin: origin, size: size)

   }

   //构造器代理

   init(x:Double, y:Double, width:Double, height:Double)

   {

       let origin = Point(x: x, y: y)

       let size = Size(width: width, height: height)

       self.init(origin: origin, size: size)

   }

}



let r = Rect()

//构造器代理的主要目的是为了创建实例的方便性

let r2 = Rect(x: 10, y: 20, width: 100, height: 80)

//这个不太方便

let r3 = Rect(origin: Point(x: 10, y: 20), size: Size(width: 100, height: 80))







10.指定构造器

有两种:

指定构造器(Designated Initializer)

便利构造器(Convenience Initializer)



一:指定构造器:

1)  最重要的构造器

2)  初始化所有的属性,并且向上调用父类的指定构造器来初始从父类中继承的属性

3) 类中至少有一个指定构造器(可以是自己写的,也可以是从父类中继承来的)



import UIKit



class Vehicle {

   var numberOfWheels = 0

   var description : String {

       return "有\(numberOfWheels)个车轮"

   }

   //1.一个类中一定有一个构造器,如果没有,编译器帮我们写一个

   init(){

   println("Vehicle init()")

   }

   //2.如果一个类中提供了一个构造器,那么编译器就不再提供默认的空参构造器

   init(wheels:Int){

       self.numberOfWheels = wheels

       println("Vehicle init(wheels)")

   }

}



class Bicycle : Vehicle {

   var numberOfPassengers : Int

   //编译器写的构造器

   override init(){

       //在调用父类的指定构造器之前,必须相处是否本类中的所有属性

       numberOfPassengers = 1

       super.init()

       //必须先调用父类的指定构造器,再给从父类继承来的属性赋值,否则有可能导致你赋的值无效(被覆盖)

       numberOfWheels = 2

   }

   

   init(numberOfWheels:Int , numberOfPassengers:Int)

   {

       self.numberOfPassengers = numberOfPassengers

       //无法在调用父类的构造器之前调用本类的实例方法

       //self.show()

       super.init(wheels: numberOfWheels)

       self.numberOfWheels = numberOfWheels //可以省略

       //可以在调用父类的指定构造器之后调用本类中的实例方法

       self.show()

   }

   func show(){}

}

let bi = Bicycle()

let bi2 = Bicycle(numberOfWheels: 2, numberOfPassengers: 3)

bi2.numberOfWheels

bi2.numberOfPassengers





二:便利构造器:

1) 是次要的,辅助性的构造器.

2) 一个类可能没有便利构造器,但不能没有指定构造器

3) 便利构造器不会调用父类的构造器,而会调用同类中的构造器



三原则 四检查:

三大原则:  1)指定向上调, 2)便利调自己,  3)便利最终会调用到指定

安全检查:

1. 必须先初始本类的所有属性之后,才能向上调用父类的指定构造器(初始化父类中的属性)

2. 必须调用完了父类的指定构造器后,才能给继承下来的属性赋值(如果需要的话)

3. 在便利构造器中,如果需要直接给属性赋值,则赋值语句一定要写在调用另一个构造器的语句之后

4. 构造器中要调用其他构造器之前,不能调用任何实例方法。只有在调用其他构造器之后才可以调用实例方法。



构造器的继承问题:

一般情况下,构造器是不能被子类继承的,子类中如果需要父类的构造器,可以重写(覆盖)父类中已有构造器。但有如下特殊规则:

1. 如果子类没有任何指定构造器,那么子类就继承所有的指定构造器

2. 如果子类提供了父类中所有的指定构造器(可以是继承来的或都是覆盖的),那么,父类中所有的便利构造器也会被子类继承







11.便利构造器ConvenienceInitializer

import UIKit



class Food {

   var name:String

   var number: Int

   //指定构造器

   init(name:String){

       self.name = name

       self.number = 1

   }

   //便利构造器

   convenience init(){

       //便利一定会调用自己的另一个构造器

       self.init(name:"无名食物")

       //必须先调用了自己的另一个构造器之后,才能给一些属性赋值

       number = 0

   }

}



let f = Food()

f.name

let f2 = Food(name: "清江烤鱼")

f2.name



//食谱原材料

class RecipeIngredient : Food {

   var quantity : Int

   init(name:String, quantity:Int){

       self.quantity = quantity

       super.init(name: name)

       number = 0

   }

   //便利构造器覆盖(重写)了父类中的指定构造器

   override convenience init(name:String){

       self.init(name:name, quantity:1)

   }

}

//构造器被继承

let r1 = RecipeIngredient()

let r2 = RecipeIngredient(name: "辣椒")

let r3 = RecipeIngredient(name: "大蒜", quantity: 1)



class ShoppingListItem : RecipeIngredient {

   //init(num:Int){}

}



let s1 = ShoppingListItem()

let s2 = ShoppingListItem(name: "", quantity: 1)

let s3 = ShoppingListItem(name: "")





class Parent {

   init(name:String){}

}

class Child : Parent {

   init(age:Int){

       super.init(name: "")

   }

}

let c = Child(age: 30)

//构造没有继承

//let c2 = Child(name: "abc”)









Day05



1.可失败的构造器

失败的情况

函数:有返回值,但无法返回值时会返回nil

对象:构造器(构造方法,构造函数) 没有返回值

那么构造器中如果构造失败?

1. 可失败的构造器(Failable Initializer)

当构造器构造失败时,可以用返回nil方式告诉调用者

import UIKit



class Animal {

   let species : String

   //可失败的构造器

   init?(species:String){

       self.species = species;

       if species.isEmpty { return nil }

   }

}



let a = Animal(species: "")

let b = Animal(species: "狼")

b!.species



if let c = Animal(species: "猫") {

   c.species

}else{

   //c是nil

}



//枚举中使用可失败的构造器

enum TemperatureUnit {

   case Kelvin, Celsius, Fahrenheit

   init?(symbol:Character){

       switch symbol {

       case "K":

           self = .Kelvin

       case "F":

           self = .Fahrenheit

       case "C":

           self = .Celsius

       default:

           return nil

       }

   }

}



let tempUnit = TemperatureUnit(symbol: "K")

let tempUnit2 = TemperatureUnit(symbol: "C")

let tempUnit3 = TemperatureUnit(symbol: "A")



//可自动解包的可失败构造器

class SomeClass {

   var name = "abc"

   //构造成功的对象可自动解包

   init!(){}

}



let s = SomeClass()

s.name //可以直接访问属性,因为自动解包





//必须构造器(required initializer)

class SuperClass {

   //子类必须有此构造器

   required init(number:Int){}

   init(){}

}

class SubClass : SuperClass {

   init(name:String){

       super.init()

   }

   //子类必须重写父类的这个构造器,因为这是父类要求的

   required init(number:Int){

       //子类构造器必须调用父类的构造器(三大原则)

       super.init(number: number)

   }

}




2.函数返回为空的处理
import UIKit



//如果一个函数的返回值可能为空,那么函数的返回值类型一定是可选值类型

func getResult(flag:Bool)->Int? {

   if flag {

       return 100

   }

   return nil

}



if let res = getResult(true) {

   //返回了一个整数

} else {

   //返回空

}





3.可选链(Optional Chaining)

主要是为了解决可选值的问题

import UIKit



class Person {

   var residence : Residence?

}



class Residence {

   var numberOfRooms = 1

}



let p = Person()

//对可选值直接进行强制解包会有可能会导致程序崩溃

//p.residence!.numberOfRooms



//考虑使用可选绑定

if let resi = p.residence {

   println("此人有房\(resi.numberOfRooms)间")

}else{

   println("无房户")

}

//可选链

//这个值为空吗?如果不为空,则读取属性numberOfRooms,如果为空,则直接返回nil,不再继承,程序也不会崩溃

p.residence?.numberOfRooms





4.可选链的使用

isKindOf:

isMemberOf:

共同点:在运行时来判断一个引用指向的对象是否是某种类型

不同点:

isKindOfClass:   是否是指定的类型或子类型

isMemberOfClass: 是否是指定的类型

import UIKit



class Person {

   var residence : Residence?

}

class Residence {

   var rooms = [Room]()

   var numberOfRooms : Int {

       return rooms.count

   }

   var address : Address?

   

   subscript(index:Int)->Room? {

       if index < 0 || index >= numberOfRooms {

           return nil

       }

       return rooms[index]

   }

   func printNumberOfRooms(){

       println("房间的个数是\(numberOfRooms)个")

   }

}



class Room {

   let name : String?

   init(name:String){

       self.name = name

   }

}



class Address {

   var buildingName : String?

   var buildingNumber : String?

   var street : String?

   func buildingIdentfier()->String? {

       if buildingName != nil {

           return buildingName

       }else if buildingNumber != nil{

           return buildingNumber

       }else if street != nil {

           return street

       }

       return nil

   }

}



let p = Person()

if let name = p.residence?.address?.buildingName {

   println("您真住在\(name)啊!!!")

}else{

   println("可选链已经断了")

}



p.residence = Residence()

p.residence?.rooms.append(Room(name:"补月台"))



p.residence?.numberOfRooms

p.residence?.printNumberOfRooms()



//利用可选链访问下标

p.residence?[0]?.name

p.residence?[1]?.name



p.residence?.address = Address()

p.residence?.address?.buildingName = "viva square"

if let name = p.residence?.address?.buildingIdentfier()?.uppercaseString {

   println("大写:\(name)")

}else{

   println("断了")

}



5.类型转换
import UIKit

//以前学过的类型转换

var d : Double = 3.14

var i : Int = Int(d)

var i2 = Int()

var s : String = "\(d)"

s = String(stringInterpolationSegment: d)



//is, as 进行类型转换

class MediaItem {

   var name: String

   init(name:String){

       self.name = name

   }

}

class Movie : MediaItem {

   var director : String

   init(name:String, director:String){

       self.director = director

       super.init(name: name)

   }

}

class Song : MediaItem {

   var artist : String

   init(name: String, artist: String) {

       self.artist = artist

       super.init(name: name)

   }

}



let mediaLibrary/*: [MediaItem]*/ = [

   Movie(name: "复仇者联盟2", director: "Daniel"),

   Song(name: "旭日酒店", artist: "韩磊"),

   Movie(name: "虎妈猫爸", director: "Guodh"),

   Song(name: "Lemon Tree", artist: "Shasha")

]



//电影有多少部,歌曲有多少个

var movieCnt = 0

var songCnt = 0

for item in mediaLibrary {

   //判断引用指向的对象是否是某种类型

   if item is Movie { //isKindOfClass

       movieCnt++

   }else if item is Song {

       songCnt++

   }

}

movieCnt

songCnt



//打印每个媒体的详细信息

for item in mediaLibrary {

   if item is Movie {

       //as!是强制类型转换运算符,as!如果转换失败,程序崩溃

       let movie = item as! Movie

       println("电影:\(movie.name),导演:\(movie.director)")

   }else if item is Song {

       let song = item as! Song

        println("歌曲:\(song.name),演唱者:\(song.artist)")

   }

}

for item in mediaLibrary {

   //as?进行类型转换时,如果成功,返回转换后的结果,如果失败则返回nil.不会导致程序崩溃

   if let movie = item as? Movie {

       println("电影:\(movie.name),导演:\(movie.director)")

   }else if let song = item as? Song {

       println("歌曲:\(song.name),演唱者:\(song.artist)")

   }

}



var objs : [AnyObject] = [

   Movie(name: "复仇者联盟2", director: "Daniel"),

   Movie(name: "虎妈猫爸", director: "Guodh")

]



let movies = objs as? [Movie]

//OC中的数组

var strs = NSArray(objects: "aaa", "bbb", "ccc", "ddd")

let strs2 = strs as? [String]

strs as! [AnyObject]



struct A{

   struct B{

       struct C{}

   }

}

let c = A.B.C()





6.2. 在扩展中增加构造器

扩展(Extension)就是OC中的Category

struct Point {

   var x = 0.0, y = 0.0

}

struct Size {

   var width = 0.0, height = 0.0

}

struct Rect {

   var origin = Point()

   var size = Size()

}



let r = Rect()

let r2 = Rect(origin:Point(x:0, y:0), size:Size(width:10, height:8))



extension Rect {

   //增加构造器

   init(x:Double, y:Double, width:Double,height:Double){

       self.origin = Point(x:x, y:y)

       self.size = Size(width:width, height:height)

   }

}



let r3 = Rect(x:10, y:20, width:100, height:80)



//3. 在扩展中给已有类型增加方法

extension Int {

   func repeatitions(task:()->()){

       for _ in 0..
           task()

       }

   }

   mutating func squre() {

       self = self * self

   }

}

5.repeatitions({ println("OK") })//打印5个OK

var x = 10

x.squre()




7.协议和OC中的协议差不多
import UIKit



protocol MyProtocol {

   //可读可写属性

   var prop : Int { get set}

   //只读属性

   var readOnlyProp : Int {get}

   //类型属性

   static var typeProp : Int { get set}

   

   //实例方法

   func instanceMethod()->Int

   //类型方法

   static func typeMethod()

}



//结构体遵守协议

struct SomeStruct : MyProtocol {

   var prop : Int = 0

   var readOnlyProp : Int = 0

   func instanceMethod() -> Int {

       return 0

   }

   static var typeProp = 0

   static func typeMethod() {

       

   }

}



//类遵守协议

class Parent {}

class SomeClass : Parent,MyProtocol {

   var prop : Int = 0

   //只读属性

   private(set) var readOnlyProp : Int = 0

   func instanceMethod() -> Int {

       return 0

   }

   static var typeProp = 0

   static func typeMethod() {

       

   }

}





//使用协议



//id ref = ...;

//1. 协议可以直接声明变量

var ref : MyProtocol = SomeStruct()

var ref2 : MyProtocol = SomeClass()

//2. 协议可以直接做为参数的类型

func show(param:MyProtocol){}

//3. 协议可以直接做为返回值类型

func get()-> MyProtocol {

   return SomeStruct()

}

//4. 协议可以做为数组的类型

var arr : [MyProtocol] = []

//.....

//凡是类型能做的事,协议都可以,除了创建实例

//var obj = MyProtocol()



//兼容OC语言中的协议

@objc protocol ObjcProtocol {

   //必须实现的方法

   func requiredMethod()

   //可选实现的方法

   optional func optionalMethod()

}



class ObjcClass : ObjcProtocol {

   @objc func requiredMethod() {

       

   }

//    func optionalMethod() {

//        

//    }

}





8.泛型Generics

import UIKit

func swapTwoInts(inout a:Int, inout b:Int){

   let t = a

   a = b

   b = t

}

func swapTwoDoubles(inout a:Double, inout b:Double){

   let t = a

   a = b

   b = t

}





var x = 10

var y = 20

swapTwoInts(&x, &y)

x

y

var d1 = 3.13

var d2 = 2.36

swapTwoDoubles(&d1, &d2)





//泛型函数

func swapTwoValues(inout a:T, inout b:T) {

   let t = a

   a = b

   b = t

}

//类型推断得出T是Int类型

swapTwoValues(&x, &y)

x

y

swapTwoValues(&d1, &d2)



//泛型类

struct Stack {

   var items = [T]()

   //入栈

   mutating func push(item:T){

       items.append(item)

   }

   //出栈

   mutating func pop()->T {

       return items.removeLast()

   }

   //查看栈顶元素

   func top()->T {

       return items.last!

   }

   //判断栈是否为空

   func isEmpty()->Bool {

       return items.count == 0

   }

   //栈的大小

   func size()->Int {

       return items.count

   }

}



var stack = Stack()

stack.push(1)

stack.push(2)

stack.push(3)

stack.push(4)



while !stack.isEmpty() {

   println("\(stack.pop())")

}



var stack2 = Stack()

stack2.push("abc")

stack2.push("def")

stack2.push("hij")



var stack3 = Stack()







//var arr = [Int]()

var arr = Array()

var dict = Dictionary()

var set = Set()



var opt:Optional //var opt:Int?



opt = 100

opt! + 200



var opt2 : Optional//var opt2:Double?







9.泛型2

import UIKit

//从数组中找到我要的字符串,返回该串的下标

//T:Equatable的意思是说:T可以是任意类型,但必须遵守Equatable协议才行

func findValueIndex(array:[T], valueToFind:T)->Int? {

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

       if value == valueToFind {

           return index

       }

   }

   return nil

}



let arr = ["aaa", "ccc", "bbb", "ddd"]

findValueIndex(arr , "bbb")



let arr2 = [1,2,3,4,5,6,7,8,9,0]

findValueIndex(arr2, 8)

let arr3 = [1.1, 2.2, 3.3, 4.4]

findValueIndex(arr3, 3.3)





struct Point {

   var x = 0

   var y = 0

}



let p1 = Point()

let p2 = Point()

let points = [p1, p2]



//findValueIndex(points, p1)



//由于Point类型没有遵守协议Equatable,所以无法进行==运算

//if p1 == p2 {

//    println("哈哈哈")

//}



let s1 = String("abc")

let s2 = String("abc")

//String类已经遵守了Equatable协议,所以可以使用==来比较

if s1 == s2 {

   println("终于笑了")

}



let set = Set()

//由于p1对象没有遵守Hashable协议,所以不能放入Set中

//set.insert(p1)

var dict = [Point, String]()

//由于p1对象没有遵守Hashable协议,所以不能做为字典的Key

//dict[p1] = "这是一个点"



10.运算符重载OperationFunction

import UIKit



var x = 10

var y = 20

//func +(x:Int, y:Int)->Int{}

x + y //+ (x, y)

//运算符函数

// infix 运算符在中间

// prefix 运算符在前面 ++x

// postfix 运算符在后面 x++



struct Vector {

   var x = 0, y = 0

}

func +(v1:Vector, v2:Vector)->Vector {

   return Vector(x: v1.x + v2.x, y: v1.y + v2.y)

}



prefix func ++(var v:Vector)

{

   v.x++

   v.y++

}

var v1 = Vector(x: 10, y: 20)

var v2 = Vector(x: 20, y: 30)



var v3 = v1 + v2 //+ (v1, v2)

++v1



struct Vector2D : Hashable

{

   var x = 0.0, y = 0.0

   var hashValue : Int {

       return Int(x + y)

   }

}

func ==(left:Vector2D, right:Vector2D)->Bool {

   return left.x == right.x && left.y == right.y

}

let v5 = Vector2D(x: 1.0, y: 2.0)

let v6 = Vector2D(x: 1.0, y: 2.0)

if v5 == v6 {

   println("两个向量值相等")

}


//放入Set中的元素类型必须遵守Hashable协议,否则编译错误

//为什么?和OC中的NSSet一样一样的

var set = Set()

set.insert(v5)

set.insert(v6)



//只有遵守Hashable协议的类型,才可以做为字典的Key的类型

//为什么?Key不能重复

var dict = Dictionary()





Day06




[Demo1_SwiftApp]:

@IBOutlet weak var tfUserName: UITextField!

   

   @IBOutlet weak var tfPassword: UITextField!

   

   @IBOutlet weak var labelDisplay: UILabel!

   

   @IBAction func tap(sender: UIButton)

   {

       if tfUserName.text == "zl" && tfPassword.text == "123" {

           labelDisplay.text = "当前状态:登录成功,欢迎光临!"

       } else {

           labelDisplay.text = "当前状态:用户名或密码错误,请重新输入!"

       }

       

   }



[Demo2_TimeCounter]:

1.  UIAlertController

iOS8中的一个新的类,用于代替UIAlertView和UIActionSheet

2. 通知

通知中心:

NSNotification/NSNotificationCenter

给用户的通知:

本地通知

由本地应用程序发起的通知,一般是在应用程序处于后台或退出后,让iOS系统在指定时间通知用户的一种方式。

1. 创建本地通知对象(UILocalNotification)

2. 设置处理通知的时间(fireDate属性)

3. 配置通知的内容:通知主体,通知声音,图标数字

4. 调用通知:

按计划调度: scheduleLocalNotification

一般情况都是按计划调用

立即调用: presentLocalNotification

通知一般不会立即调用



关于iOS8中的通知:

从iOS8开始,应用想发通知,必须经过用户允许,否则通知无法发送。

iOS
Web note ad 1