美文网首页
Swift基础:2-Swift常用关键字

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

作者: 黑色幽默_0d96 | 来源:发表于2024-02-26 16:16 被阅读0次

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: 当前作用域内访问

其他关键字

相关文章

  • swift学习笔记 - swift中常用关键字

    swift中常用关键字 **用作声明的关键字: ** class、deinit、enum、extension、fu...

  • swift常用的关键字

    swift常用的关键字 首先我们看上图,我们不难发现extension,@objc等关键字。 extension ...

  • Swift基础-init详解

    前言 在讲解Swift的init之前,默认都有Swift开发基础,了解关键字designated,Optional...

  • Swift常用关键字

    参考文章:跳跳丶[/u/3a5225162222]的文章Swift中常用关键字[https://www.jians...

  • Swift常用关键字

    关键字 mutating(表示可在结构体,枚举的实例方法中修改属性) static(类型方法,类型属性) clas...

  • Swift学习

    Swift学习 基础部分 变量声明方式不同,使用let, var关键字,类型推断非常多,需要注意 基础类型的使用,...

  • swift基础_关键字

    一.inout 我给函数传入一个参数,想在方法内部修改它,它报错了Cannot assign to value: ...

  • Swift-Private/FilePrivate/Public

    原来 Swift 中有2种常用访问控制关键字(访问控制修饰符),分别为 private 和 public。而在 S...

  • Swift中常用关键字

    用作声明的关键字: let:声明静态变量,类似于const,用let声明的变量不可以再赋值,不然会报错; var:...

  • swift常用关键字汇总

    https://note.youdao.com/s/SerR5ysU

网友评论

      本文标题:Swift基础:2-Swift常用关键字

      本文链接:https://www.haomeiwen.com/subject/jecaudtx.html