1.常量变量
let
var
2.数据类型
- 整型,浮点型,对象类型,结构体类型(swift中大部分类改为了结构体)
- 整型
-
Int8
有符号8位整型 -
Int16
有符号16位整型 -
Int 32
有符号32位整型 -
Int 64
有符号64位整型 -
Int
与平台有关,默认相当于OC中NSInteger -
UInt8
无符号8位整型 -
UInt16,UInt32,UInt64
-
浮点型
-
Float
32位浮点型Double
64位浮点型 -
基本运算
-
相同运算符之间才能参与运算,因为swift中没有隐式转换
3.逻辑分支
-
if
switch
三目运算符
等判断语句
-
guard
运算符(守护) -
当条件表达式位true的时候跳过else语句,继续向下执行
-
当条件表达式为false的时候进入else语句中,break,continue,return,throw等跳出
guard 条件表达式 else { // 条换语句 break } 语句组 复制代码
-
switch
语句 -
switch 的case之后不必须加break case不在只是Int,可以是浮点,字符串,区间(0..<10,0...10)
-
一个case 可以判断多个值,用,隔开
4.循环
for循环
- 开区间(0..<10),闭区间(0...10)
- for循环打印字典时可以使用元组
while
,do-while
循环- 使用
repeat while
循环代替do-while循环 - i++已经被弃用,使用i=i+1;
5.字符串
-
String
是结构体,性能比NSString 高 -
String的长度,astring.characters.count 字符串长度
-
str1 + str2 两个字符串相加
-
字符串的格式化输出
String(format: "%02d:%02d", arguments: [min, second]) 复制代码
-
字符串的截取 暂时先转为NSString 进行截取
let myStr = "www.520it.com" var subStr = (myStr as NSString).substringFromIndex(4) subStr = (myStr as NSString).substringToIndex(3) subStr = (myStr as NSString).substringWithRange(NSRange(location: 4, length: 5)) 复制代码
6数组
-
Array
一个范型数组 -
数组声明方法
var stuArray1:Array<String> var stuArray2: [String] 复制代码
-
数组的 增- 删- 改- 查
// 添加数据 array.append("yz") // 删除元素 array.removeFirst() // 修改元素 array[0] = "why" // 取值 array[1] 复制代码
-
数组的合并 同类型的两个数组可以直接相加
// 数组合并 // 注意:只有相同类型的数组才能合并 var array = ["why", "lmj","lnj"] var array1 = ["yz", "wsz"] var array2 = array + array1; // 不建议一个数组中存放多种类型的数据 var array3 = [2, 3, "why"] var array4 = ["yz", 23] array3 + array4 复制代码
7.字典
-
Dictionary 是个范型集合
-
声明方式
var dict1: Dictionary<Int, String> var dict2: [Int: String] 复制代码
-
字典的增 -删- 改- 查
// 添加数据 dict["height"] = 1.88 dict["weight"] = 70.0 // 删除字段 dict.removeValueForKey("height") // 修改字典 dict["name"] = "lmj" // 查询字典 dict["name"] 复制代码
-
字典的遍历 使用元组
-
字典的合并
// 字典的合并 var dict1 = ["name" : "yz", "age" : 20] var dict2 = ["height" : 1.87, "phoneNum" : "+86 110"] // 字典不可以相加合并 for (key, value) in dict1 { dict2[key] = value } 复制代码
8.元组
- 是swift中特有的定义一组数据,类型可相同可不相同
// 元组:HTTP错误 // let array = [404, "Not Found"] // 写法一: let error = (404, "Not Found") print(error.0) print(error.1) // 写法二: let error = (errorCode : 404, errorInfo : "Not Found") print(error.errorCode) print(error.errorInfo) // 写法三: let (errorCode, errorIno) = (404, "Not Found") print(errorCode) print(errorIno) 复制代码
9.可选类型
-
可选类型的取值,有值或者是空值
-
可选类型的使用
-
使用场景
// 该方式利用类型推导 let url = NSURL(string: "www.520it.com") // 通过url来创建request对象:在使用可选类型前要先进行判断是否有值 // 该语法成为可选绑定(如果url有值就解包赋值给tempURL,并且执行{}) if let tempUrl = url { let request = NSURLRequest(URL: tempUrl) } 复制代码
10.函数
-
函数的格式
func 函数名(参数列表) -> 返回值类型 { 代码块 return 返回值 } func 函数名(参数1:参数1类型,参数2:参数2类型) -> 返回值类型 { 代码块 return 返回值 } 复制代码
-
函数 外部参数和内部参数
-
变量名前加标签就是外部参数
-
方法重写 子类重新调用父类方法是重写,override
-
方法重载 方法名相同但是参数不同,称为方法重载
// num1和a是外部参数的名称 func ride(num1 num1 : Int, a num2 : Int, b num3 : Int) -> Int { return num1 * num2 * num3 } var result1 = ride(num1: 20, a: 4, b: 5) // 方法的重载:方法名称相同,但是参数不同,可以称之为方法的重载(了解) func ride(num1: Int, _ num2 :Int) -> Int { return num1 * num2 } var result2 = ride(20, 20) 复制代码
-
函数的默认参数
-
不传的话有个默认值
func makecoffee(type :String = "卡布奇诺") -> String { return "制作一杯\(type)咖啡。" } 复制代码
-
可变参数
-
可以接受不确定数量的输入类型参数,但必须是相同类型,在参数类型后面拼接**...** 来实现
func sum(numbers:Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total } sum(100.0, 20, 30) sum(30, 80) 复制代码
-
函数引用类型-指针传递
-
默认是值传递,不改变外部变量的值,如果想改变,需要传地址
-
传入的地址必须是变量
-
swift提供inout 关键字实现
11.swift中类的使用
-
定义类的时候可以没有父类,需要父类的话大多可以使用NSObject 作为父类,非OC的NSObject
-
类的属性 分为 储值属性,算值属性,类属性
-
储值属性
-
计算型属性 不存储实际值,提供getter 和可选的setter间接获取或设置其他属性,
- 一般只提供getter 方法,如果只实现了getter 方法,则为只读属性,可以省略get{},直接return
-
类属性 所有的类和类的实例都有一份类属性,如果在某一处更新后,该类属性就会被修改
-
类属性使用static 关键字修改,
-
监听属性的修改
-
在oc中使用set 方法监听
-
在swift中,使用属性观察者监听和相应属性值的变化
-
使用属性的will set 方法监测新值,在didset中监测旧值
-
willSet (new){ }
didSet(old){}
-
在didset中生成计算型属性的值
-
didSet 属性直接赋值不会调用didSet方法,而是在初始化之后再赋值才能调用
var expires_in: NSTimeInterval = 0 { didSet { expiresDate = NSDate(timeIntervalSinceNow: expires_in) } } 复制代码
12.类的构造函数
-
构造函数的基本使用
-
类的属性必须有值,如果不是在初始化的时候复制,在构造方法中给类属性赋值,
class Person: NSObject { var name : String var age : Int // 重写了NSObject(父类)的构造方法 override init() { name = "" age = 0 } } // 创建一个Person对象 let p = Person() 复制代码
-
初始化的时候给属性赋值
-
如果在自定义对象的时候给属性赋值,自定义init方法,会覆盖init方法,不会有默认的初始化方法
class Person: NSObject { var name : String var age : Int // 自定义构造函数,会覆盖init()函数 init(name : String, age : Int) { self.name = name self.age = age } } // 创建一个Person对象 let p = Person(name: "why", age: 18) 复制代码
13 字典转模型 (初始化时传入字典)
- 字典取值是NSObject 是任意类型
- 可以通过as转换之后再赋值,不同类型不能直接赋值
class Person: NSObject { var name : String var age : Int // 自定义构造函数,会覆盖init()函数 init(dict : [String : NSObject]) { name = dict["name"] as! String age = dict["age"] as! Int } } // 创建一个Person对象 let dict = ["name" : "why", "age" : 18] let p = Person(dict: dict) 复制代码
14 字典转模型 (KVC 转化)
- kvc 不能保证全部复制,所以属性要有默认值,基本数据类型默认值是0,对象结构体定义为可选即可
class Person: NSObject { // 结构体或者类的类型,必须是可选类型.因为不能保证一定会赋值 var name : String? // 基本数据类型不能是可选类型,否则KVC无法转化 var age : Int = 0 // 自定义构造函数,会覆盖init()函数 init(dict : [String : NSObject]) { // 必须先初始化对象 super.init() // 调用对象的KVC方法字典转模型 setValuesForKeysWithDictionary(dict) } } // 创建一个Person对象 let dict = ["name" : "why", "age" : 18] let p = Person(dict: dict) 复制代码
15闭包的介绍
-
闭包就是匿名函数
-
block
的写法类型: 返回值(^block的名称)(block的参数列表) ------ 值: ^(参数列表){ // 执行的代码 } 复制代码
-
swift的写法
-
定义网络请求的类
func loadRequest(callBack:()->()){ callBack() } 复制代码
-
使用闭包
httpTool.loadRequest( { ( )->( ) in tableView.reloadData }) 复制代码
-
闭包总结
闭包的写法: 类型: (型参列表)->( 返回值 ) 值: { ( 型参列表 ) -> 返回值类型 in // 执行代码 } 复制代码
-
尾随闭包
-
如果闭包没有参数没有返回值,
( ) -> ( ) in
可以省略 -
如果闭包是作为函数的最后一个参数,则可以将闭包写在()后面
-
如果函数只有一个参数,且最后一个参数是闭包,那么()也可以不写,直接在方法名后面拼接{}
省略前 httpTool.loadRequest({ ( ) -> ( ) in print(完全不省略) }) 省略1 httpTool.loadRequest({ print(省略括号 in) }) 省略2 httpTool.loadRequest( ){ print(小括号前置) } 省略3 httpTool.loadRequest{ print(终结版尾随闭包) } 复制代码
-
16.闭包的循环引用
-
deinit{}
实现deinit 函数,检测一个对象是否销毁 -
swift 循环引用的三种方式
- 使用
weak
,使用【weak self】
,使用unowned
关键字
- 使用
-
使用weak
关键字对控制器持有,weakself是可选类型,使用时强行解包,因为一定有值weak var weakSelf = self httpTool.loadData { print("加载数据完成,更新界面:", NSThread.currentThread()) weakSelf!.view.backgroundColor = UIColor.redColor() } 复制代码
-
使用 【weak self】
【weak self 】写在闭包中,在闭包中使用的self 都是weak的httpTool.loadData {[weak self] () -> () in print("加载数据完成,更新界面:", NSThread.currentThread()) self!.view.backgroundColor = UIColor.redColor() } 复制代码
-
unowned 类似oc的unretain
,即使原来引用的对象释放了,也会对释放的对象,持有一个无效的引用,不是可选的,不可能指向nilhttpTool.loadData {[unowned self] () -> () in print("加载数据完成,更新界面:", NSThread.currentThread()) self.view.backgroundColor = UIColor.redColor() } 复制代码
17.懒加载
-
希望所有的对象,只有加载的时候才能加入到内存中,
-
lazy
关键字,是专门修饰懒加载属性的 -
格式
lazy var 变量名 = { 创建变量代码 }() 复制代码
-
使用
// 懒加载的本质是,在第一次使用的时候执行闭包,将闭包的返回值赋值给属性 // lazy的作用是只会赋值一次 lazy var array : [String] = { () -> [String] in return ["why", "lmj", "lnj"] }() 复制代码
18.便利构造函数
-
convenience : 便利,使用convenience修饰的构造函数叫做便利构造函数
-
便利构造函数通常用在对系统的类进行构造函数的扩充时使用
-
便利构造函数的特点
-
便利构造函数,一般写在extension中
-
便利构造函数,在init前面添加convenience 关键字
-
在便利构造器中需要明确调用
self.init()
, 而且是先调用。 -
在继承中,重写父类的方法中,初始化自己的方法中,先初始化自己的属性,之后调用父类的super.init()
19 #Selector()
事件监听
-
事件监听本质发送消息.但是发送消息是OC的特性
-
将方法包装成@SEL --> 类中查找方法列表 --> 根据@SEL找到imp指针(函数指针) --> 执行函数
-
如果swift中将一个函数声明称private,那么该函数不会被添加到方法列表中
-
如果在private前面加上@objc,那么该方法依然会被添加到方法列表中
20.类型转换
-
类型转换在 Swift 中使用
is
和as
操作符实现 ,你也可以用它来检查一个类型是否实现了某个协议,就像在检验协议的一致性部分讲述的一样。 -
定一个类
MediaItem
,name 属性,init(name:) 方法 -
其2个子类
Movie
,Song
-
检查类型
-
is
判断是一个实例,是否属于特定子类 if item is Movie -
向下转型
-
使用子类特有的属性和方法,使用
as
转化为子类 as?和as!
21.Any 和 AnyObject
的类型转换
- Any 表示任何类型,包括函数类型
- AnyObject表示任何类型的实例
for thing in things { switch thing { case 0 as Int: print("zero as an Int") case 0 as Double: print("zero as a Double") case let someInt as Int: print("an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: print("a positive double value of \(someDouble)") case is Double: print("some other double value that I don't want to print") case let someString as String: print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("an (x, y) point at \(x), \(y)") case let movie as Movie: print("a movie called '\(movie.name)', dir. \(movie.director)") case let stringConverter as String -> String: print(stringConverter("Michael")) default: print("something else") } } // zero as an Int // zero as a Double // an integer value of 42 // a positive double value of 3.14159 // a string value of "hello" // an (x, y) point at 3.0, 5.0 // a movie called 'Ghostbusters', dir. Ivan Reitman // Hello, Michael 复制代码
22.在一个类型中嵌套另外一个类型
-
BlackjackCard
(二十一点),结构体中,嵌套Suit
,Rank
两个枚举struct BlackjackCard { // 嵌套的 Suit 枚举 enum Suit: Character { case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣" } // 嵌套的 Rank 枚举 enum Rank: Int { case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King, Ace struct Values { let first: Int, second: Int? } var values: Values { switch self { case .Ace: return Values(first: 1, second: 11) case .Jack, .Queen, .King: return Values(first: 10, second: nil) default: return Values(first: self.rawValue, second: nil) } } } // BlackjackCard 的属性和方法 let rank: Rank, suit: Suit var description: String { var output = "suit is \(suit.rawValue)," output += " value is \(rank.values.first)" if let second = rank.values.second { output += " or \(second)" } return output } } 复制代码
-
初始化
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
-
使用:
let heartsSymbol = BlackjackCard.Suit.Hearts.rawValue