2017年3月30日第一次更新
一.用作声明的关键字:
class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias、var
1.typealias 定义新类型
typealias TFInt = Int // 将系统的Int写法改为自定的TFInt
var distance: TFInt = 100
2.subscript 下标脚本
subscript可以使用在类,结构体,枚举中提供一种类似于数组或者字典通过下标来访问对象的方式,subscript可以重载,就是一个类可以定义多个下标脚本,并且可以设置为只读和读写.
var className :String? =nil
subscript(str:String) -> Any {
set{
self.className= (newValue as? String)?.appending(str)
}
get{
return self.className ?? "没有名字"
}
}
print("第一次打印------\(self["有名字了吗"])")
self["哈哈哈"] = "这回有名字了"
print("第二次打印------\(self[""])")
打印结果: 第一次打印------没有名字
第二次打印------这回有名字了哈哈哈
3.deinit 类反初始化方法(析构方法)
var count =1
class TFModel:NSObject{
deini { // 类似于OC中的dealloc
count-=1
}
}
二.用作语句的关键字
break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where、while、guard
1.fallthrough 语句
let index =10
switch index {
case1...10:print("1-10之间的数") fallthrough
case5...10:print("5-10之间的数");
case7...10:print("7-10之间的数")
case8...10:print("8-10之间的数")
default:break
}
// 打印出来的结果是 1-10之间的数 5-10之间的数
// 如果你想在 Swift 中让 case 之后的语句会按顺序继续运行,则需要使用 fallthrough 语句
2.throws do try catch 捕获异常
// 1.定义枚举异常值.首先我们可以创建自己的异常枚举值,这要实现Error协议,只不过这个协议是空的,我们加上就好
public enum GuardError :Error {
caseone
casetwo
casethree
casefour
}
// 2.抛出异常.我们可以在方法中抛出异常,定义抛出异常的方法很简单,只需要在返回值的 -> 前面加上throws就好了,示例如下
func checkObject (isYoung:Bool, isAnimal:Bool, sex:Bool) throws {
guard isYoung else {
throw GuardError.one
}
guard isAnimal else {
throw GuardError.two
}
guard sex else {
throw GuardError.three
}
}
// 3.捕获异常.我们可以在调用可能抛出异常的方法后面加上catch关键字来捕获异常
func setObject (isYoung:Bool, isAnimal:Bool, sex:Bool) {
do{
try self.checkObject(isYoung: isYoung, isAnimal: isAnimal, sex: sex)
}catch GuardError.one{
print("one")
}catch GuardError.two{
print("two")
}catch GuardError.three{
print("three")
}
catch{ // 其他异常
print("哈哈")
}
3.repeat...while 循环
swift repeat...while相当于 OC中的 do while
var index=15
repeat {
print("index 的值为 \(index)")
index=index+1
} while index<20
4.guard语句
guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句.相对于if语句,guard语句的优点是可读性更强!
if语句和guard语句的区别:使用 if let解绑optional变量,在if作用域外,解绑的值是不可用的;使用 guard let解绑optional变量后,在包含guard的作用域内,解绑后的值是可用的!
func guardTest() {
guard Astr=="1" else{
print("呵呵呵")
return
}
guard Astr=="1" && Bstr=="2" else {
print("噢噢噢噢")
return
}
print("哈哈哈哈哈")
}
三.用作表达和类型的关键字
as、dynamicType、is、new、super、self、Self、Type、COLUMN、FILE、FUNCTION、LINE
1.as?和as! 类型转换
// 使用as?转换类型,失败时,可选的值为 'nil'
let array = [UIButton(), UIView(), UILabel(), UIImageView()]
let obj = array[1] as? UIButton
obj?.titleLabel?.text = "aaa"
// 使用as!转换类型,失败时抛出异常(程序崩溃)
let array = [UIButton(), UIView(), UILabel(), UIImageView()]
let obj = array[1] as! UIButton
obj!.titleLabel?.text = "aaa"
2.is 检查值的类型
let array = [UIButton(), UIView(), UILabel(), UIImageView()]
for index in 0 ..< array.count { // forin 循环
if array[index] is UIButton { // 相当于iskindof
print("是button")
}else{
print("不是button")
}
}
// 输出 是button 不是button 不是button 不是button
四.其他关键字
1.override 重写父类方法
override func viewDidLoad() {
super.viewDidLoad()
}
2.Optionals 定义可选类型
var tfString :Optional
// 声明一个nil 的变量 var tfString : String? // 声明一个nil 的变量(两种写法意义相同)
tfString = "我是String"
print(tfString) // 打印结果 (Optional("我是String"))
print(tfString!) // 打印结果我是String 使用!来获取一个不存在的可选值会导致运行时错误。使用!来强制解析值之前,一定要确定可选包含一个非nil的值
3.final 禁止重写父类方法
final func method(){
print("method----")
}
// 子类不允许重写这个方法
4.internal 访问级别
可以访问当前模块中的其他任何实体,但是在模块外无法访问,这是所有实体的默认访问级别(通常在一个单目标Application中不需要自行设置访问级别)。
internal class ViewController:UIViewController { // 默认访问级别,可以省略不写
}
5.convenience 类构造器
所有的convenience初始化方法都必须调用同一个类中的designated 初始化完成设置,另外convenience的初始化方法是不能被子类重写或者是从子类中以super的方式被调用的.例:
class ATest : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(_num:Int, frame:CGRect) {
self.init(frame: frame)
}
required init?(coder aDecoder:NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class BTest:ATest {
// 不可重写父类convenience的构造方法
override init(frame:CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder:NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class OtherClass: NSObject {
override init() {
// 只要子类重写了父类的构造方法就可使用父类的convenience let BTest = BTest.init(20, frame:CGRect.init(x:10,y:20,width:20,height:30))
}
}
6.@discardableResult
Swift 3.0 中方法的返回值必须有接收否则会报警告,当然其实主要目的是为了避免开发人员忘记接收返回值的情况,但是有些情况下确实不需要使用返回值可以使用"_"接收来忽略返回值。当然你也可以增加@discardableResult声明,告诉编译器此方法可以不用接收返回值。
func resultTest1() -> String {
print("打印一下resultTest1")
return "返回值resultTest1"
}
@discardableResult
func resultTest2() -> String {
print("打印一下resultTest2")
return "返回值resultTest2"
}
override init() {
super.init()
self.resultTest1() // 此处没有方法有返回值但是没有接受,会有警告
_ = self.resultTest1() // 使用"_"接收无用返回值
self.resultTest2() // 由于resultTest2添加了@discardableResult声明,即使不接收返回值也不会警告
}
7.@escaping逃逸闭包
当闭包作为函数的参数传入时,很有可能这个闭包在函数返回之后才会被执行,这就是逃逸闭包。一般情况下,一些异步函数会使用逃逸闭包。这类函数会在异步操作开始之后立刻返回,但是闭包直到异步操作结束后才会被调用。比如网络请求中处理服务器返回请求的闭包
// swift3中的改变:所有的闭包都默认为非逃逸闭包,不再需要@noescape;如果是逃逸闭包,就用@escaping表示。
func startRequest(callBack: @escaping() -> Void) {
DispatchQueue.global().asyncAfter(deadline:DispatchTime.now() + 1) {
callBack() // callBack在函数执行完后1秒才执行,所以是逃逸闭包
}
}
8.defer 推迟执行
defer延缓推迟,相当于把操作放入栈中后加入的先执行
以往我们在写网络请求时候,无论数据为空 或是 网络失败,都要隐藏HUD,所以隐藏HUD的代码要反复写几次,如下例:(如下代码为伪代码)
func requestMethod () {
showHUD() // 显示HUD
if success {
if array.count == 0 { // 空数据
showEmptyView()
hideHUD() // 隐藏HUD
return
}else{
// 字典转模型.......处理数据
}
// 刷新页面
hideHUD()
self.tableView.reloadData()
}else{
hideHUD()
//网络失败代码
}
}
// defer就可以在这个时候管了大用,如下重写(如下代码为伪代码)
func requestMethod () {
showHUD()//显示HUD
defer { // 写在return之前
hideHUD()//隐藏HUD
}
if success {
//处理数据逻辑
if array.count == 0 {
showEmptyView()
return
}else{
//字典转模型
}
//处理页面逻辑
self.tableView.reloadData()
}else{
//网络失败代码
}
}
// 我们将hideHUD()/放在defer代码块里,在执行return前会先执行defer里的代码,这样就保证了不管发生什么,最后都会隐藏HUD