Swift基础:2-Swift常用关键字

var、let

var声明变量,表示变量可修改,如var a = 3,可以对a进行修改,a=4

let声明变量,表示变量不可修改,如let a = 3,那么就不可以对a进行修改(a=4报错)

简单来说,var表示这个变量,可以指向新的内存地址,而let,则不能指向新的内存地址

staic、class、final

static修饰的方法,变量,表示静态方法、变量,可以用于结构体、协议、类中,而在类中使用时,它和它的子类共享,但是不能被子类重写

class修饰的方法,变量,表示类方法、变量,只能用在类中,子类可以重写;

需要注意的是,class通常修饰方法,如果修饰变量的话,只能是计算型变量。

final关键字在大多数的编程语言中都存在,表示不允许对其修饰的内容进行继承或者重新操作。Swift中,final关键字可以在class、func和var前修饰。

defer

1、defer语句在代码块(方法、闭包等,可以理解为大括号包装起来的代码)作用域退出之前执行,也就是代码块中其他应该执行的代码都执行完了,才执行defer中的代码

2、一个代码块允许多个defer,多个defer执行的顺序 从后到前

3、defer 语句块中的代码, 会在当前作用域结束前调用, 常用场景如异常退出后, 关闭数据库连接

4、需要注意的是, 如果有多个 defer, 那么后加入的先执行

func someQuery() -> ([Result], [Result]){
   let db = DBOpen("xxx")
   defer {
       db.close()
   }
   guard results1 = db.query("query1") else {
       return nil
   }
   guard results2 = db.query("query2") else {
       return nil
   }
   return (results1, results2)
}</pre>

//需要注意的是, 如果有多个 defer, 那么后加入的先执行

func someDeferFunction() {
   defer {
       print("\(#function)-end-1-1")
       print("\(#function)-end-1-2")
  }
   defer {
       print("\(#function)-end-2-1")
       print("\(#function)-end-2-2")
  }
   if true {
       defer {
           print("if defer")
      }
       print("if end")
  }
   print("function end")
}
someDeferFunction()
// 输出
// if end
// if defer
// function end
// someDeferFunction()-end-2-1
// someDeferFunction()-end-2-2
// someDeferFunction()-end-1-1
// someDeferFunction()-end-1-2</pre>

dynamic

由于 swift 是一个静态语言, 所以没有 Objective-C 中的消息发送这些动态机制, dynamic 的作用就是让 swift 代码也能有 Objective-C 中的动态机制, 常用的地方就是 KVO 了, 如果要监控一个属性, 则必须要标记为 dynamic

typealias

给一个类型取别名,例

public typealias RxTime = Date

用于协议中定义了泛型时,在实际使用的时候,需要给这个泛型确定一个真实类型

associatedtype

简单来说就是 protocol 使用的泛型,一般联合typealias使用

protocol ListProtcol {
   associatedtype Element
   func push(_ element:Element)
   func pop(_ element:Element) -> Element?
}

实现协议的时候, 可以使用 typealias 指定为特定的类型, 也可以自动推断, 如

class IntList: ListProtcol {
   typealias Element = Int // 使用 typealias 指定为 Int
   var list = [Element]()
   func push(_ element: Element) {
       self.list.append(element)
   }
   func pop(_ element: Element) -> Element? {
       return self.list.popLast()
   }
}
class DoubleList: ListProtcol {
   var list = [Double]()
   func push(_ element: Double) {// 自动推断
       self.list.append(element)
   }
   func pop(_ element: Double) -> Double? {
       return self.list.popLast()
   }
}

where

可以限定泛型的类

where语句在if中使用时,在swift4及以后,被,代替

extension ListProtcol where Element == Int {
  func isInt() ->Bool {
      return true
  }
}

case

case可在if、switch语句中使用

//case 不只是在switch中使用
//注意,where语句在if中使用时,在swift4及以后,被,代替
/*
if 中使用case,where
*/
let tempInt = 23
if case 10...30 = tempInt{
  print("if case")
}

if case 10...30 = tempInt, tempInt<25{
  print("if case where")
}

if tempInt<30,tempInt>20{
  print("if where")
}

/*
switch 中使用where
*/
let pointTemp = (10,20)
switch pointTemp {
case (let x,let y) where x == y/2 :
  print ("switch中使用where")
default:
  print("default")
}

/*
for in中使用where、case
*/
for i in 1..<20 where I>10{
  print("for in中使用where,i = \(i)")
}

for case let i in 1..<20 where I>10{
  print("for in中使用case where,i = \(i)")
}

guard

guard,保证符合条件,否则怎样(guard关键字,需要return或者throw配合使用,所以一般必须在函数体中使用)

func testGuard(x:Int?)->(){
  guard let testGuardTemp = x,testGuardTemp>20 else {
      print("guard的用法")
      return
  }
  print("guard的用法:",testGuardTemp)
  return
}
testGuard(x:nil)
testGuard(x: 23)

//guard与if的区别,在于guard中进行可选型解包而声明的变量,能在方法体内下继续使用,if则只能在if体内使用

guard 和 if 类似, 不同的是, guard 总是有一个 else 语句, 如果表达式是假或者值绑定失败的时候, 会执行 else 语句, 且在 else 语句中一定要停止函数调用 例如

guard 1 + 1 == 2 else {
   fatalError("something wrong")
}

常用使用场景为, 用户登录的时候, 验证用户是否有输入用户名密码等

guard let userName = self.userNameTextField.text,
 let password = self.passwordTextField.text else {
   return
}

inout

输入输出参数, 如:

func swap( a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}
var a = 1
var b = 2
print(a, b)// 1 2
swap(a: &a, b: &b)
print(a, b)// 2 1</pre>

weak、unowned

两者都是弱引用,都只能使用在类实例上面

weak修饰的变量,对象释放后自动置为nil(因此被标记为 @weak 的变量一定需要是 Optional 值)

weak弱引用多用于通常的解决循环引用问题场景。

unowned修饰的变量,对象释放后不会自动置为nil,仍然保留释放对象的地址,所以可能发生野指针问题

unowned无主引用用于一个属性允许设置为 nil,而另一个属性不允许设置为 nil,并会造成潜在的强引用循环的场景。

从安全角度来说,weak优于unowned,但是从性能上说,unowned优于weak(weak的实质是对unowned的封装,包裹了一个可选值)

1、Unowned和Weak的使用时机

Unowned一般使用在其所修饰的对象和所处的block环境的生命周期一致的时候。 简单来说,Unowned修饰的对象,在整个block的使用期间都应该是有效的,即不可为nil。

Weak则可以使用为block 的生命周期超出其对象进行修饰。 意思是可以修饰可能变成nil的对象。用Swift中的话语来说就是Optional对象。

相比之下,weak的使用范围更加广泛,如果不考虑性能的话,我们大可以无论什么情况都使用weak将会更加安全。然而,既然Unowned存在,必将有他的意义 —— 出于性能考虑,我们应该在可以使用Unowned的时候尽可能的使用Unowned,具体原因请往下看。

2、Unowned 比Weak的开销更小

Swift 中的每个对象保持了两个引用计数器,一个是强引用计数器,用来决定 ARC 什么时候可以安全地析构这个对象,另外一个附加的弱引用计数器,用来计算创建了多少个指向这个对象的 unowned 或者 weak 引用,当这个计数器为零时,这个对象将被析构 。

弱引用计数器在增加之前(这是一个原子操作),会事先检查一个对象的强引用计数器的值,当值大于0的时候,才确保这是有效的。不然我们访问一个无效的值将会引起程序运行时报错从而导致崩溃。

Unowned 在编译的时候,进行了优化,它不会对有效只进行辨别:如果其引用的对象是一个有效值,它将会顺利在弱引用计数器原本的基础之上加1。如果是一个无效的值,那它将指向一个垃圾内存中的地址,在运行的时候,这将会产生错误,这就是为什么我们需要在使用Unowned时候,要保证对象生命周期的有效性。

Weak针对Unowned 进行了包装(光凭这一点,Unowned 在性能上优于Weak)。Swift 的 weak 引用添加了附加层,间接地把 unowned 引用包裹到了一个可选容器里面,会对可选值进行相应的处理,这将带来一定的开销。所以尽管我们给一个nil对象添加Weak 修饰,程序运行中,依旧不会报错。

这里的性能对比,验证了上面所说的,我们应该在对象的生命周期允许的情况下,尽量使用Unowned 。

_

"_"在swift中有特殊的意义,一般使用来,用于占位进行忽略.

(1)函数参数名忽略;

(2)10_000(跟10000一样,但是加_后更易读)

mutating :

struct 和 class 的差別是 struct 的 function 要去改变 property 的值的时候要加上 mutating,而 class 不用。

throws 、 rethrows

throws 用在函数上, 表示这个函数会抛出错误. 有两种情况会抛出错误, 一种是直接使用 throw 抛出, 另一种是调用其他抛出异常的函数时, 直接使用 try xx 没有处理异常. 如

enum DivideError: Error {
   case EqualZeroError;
}
func divide(_ a: Double, _ b: Double) throws -> Double {
   guard b != Double(0) else {
       throw DivideError.EqualZeroError
   }
   return a / b
}
func split(pieces: Int) throws -> Double {
   return try divide(1, Double(pieces))
}

rethrows 与 throws 类似, 不过只适用于参数中有函数, 且函数会抛出异常的情况, rethrows 可以用 throws 替换, 反过来不行 如

 rethrows -> Double {
   return try function(a, b)
}

try? 、 try!、try

用于处理可抛出异常的函数。
try需要配合do catch使用。
try? 、 try!, 使用这两个关键字可以不用写 do catch.
区别在于, try? 在用于处理可抛出异常函数时, 如果函数抛出异常, 则返回 nil, 否则返回函数返回值的可选值, 如:

print(try? divide(2, 1))
// Optional(2.0)
print(try? divide(2, 0))
// nil

而 try! 则在函数抛出异常的时候崩溃, 否则则返会函数返回值, 相当于(try? xxx)!, 如:

print(try! divide(2, 1))
// 2.0
print(try! divide(2, 0))
// 崩溃

访问控制相关关键字(public等)

open > public > internal > fileprivate > private
open:在其他模块(命名空间)内使用可被访问、继承、重写
public:在其他模块内只能被访问,不能被继承
internal:仅在自身模块中能访问、继承、重写
fileprivate:当前文件内访问
private: 当前作用域内访问

其他关键字

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • Swift中有多少关键字?在Swift官方文档的词汇结构中, 有非常多的关键字, 它们被用于声明中、语句中、表达式...
    云涌海啸阅读 553评论 2 0
  • Swift官方文档的词汇结构中, 有非常多的关键字, 它们被用于声明中、语句中、表达式中、类中、模式中, 还有以数...
    小宇宙_fly阅读 751评论 0 3
  • swift中常用关键字 **用作声明的关键字: ** class、deinit、enum、extension、fu...
    花前月下阅读 7,608评论 5 32
  • Swift关键字汇总如下: 一: 常见使用频繁的关键字: 1,访问修饰符:在swift中,访问修饰符有五种,分别是...
    物非0人非阅读 3,373评论 2 15
  • 用作声明的关键字: let:声明静态变量,类似于const,用let声明的变量不可以再赋值,不然会报错; var:...
    跳跳丶阅读 6,758评论 4 27