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开始,应用想发通知,必须经过用户允许,否则通知无法发送。
Swift
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...