Swift扩展

时间:2020-02-23 14:44:01  来源:igfitidea点击:

我们将在本教程中讨论和使用Swift Extension。

Swift扩展

Swift扩展是一项有用的功能,有助于为现有的类,结构,枚举或者协议类型添加更多功能。
这包括为您也没有原始源代码的类型(Int,Bool等类型的扩展名)添加功能。

以下是Swift Extension为我们提供的基本功能:

  • 添加计算实例属性和计算类型属性
  • 定义实例方法和类型方法
  • 提供新的初始化器
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使现有类型符合协议

注意:无法将存储的属性添加到扩展程序中。
Swift扩展程序不支持替代属性和方法实现。

Swift扩展语法

以下是用于创建快速扩展的语法。

extension ClassStructEnumOrProtocolNameGoesHere {
  //add functionality to the above type
}

Swift类扩展示例

让我们打开Xcode游乐场,开始使用Extensions。

extension Int {
  
  var square : Int{
      return self*self
  }
  
  func cube()->Int{
      return self*self*self
  }
  
  mutating func incrementBy5() {
      self = self + 5
  }
}

var x : Int = 5
print(x.square) //prints "25\n"
print(x.cube()) //prints "125\n"
x.incrementBy5() //10

在上面的代码中,我们创建了一个只读的计算属性以计算数字的平方。
因此,省略了get。

为了修改类型本身的值,使用了一个变异函数。

extension String {
  
  var length: Int {
      get {
          return self.characters.count
      }
  }
  
  mutating func addString(str: String) {
      self = self + str
  }
}

var stringA = "Hello"
stringA.length  //5
stringA.addString(str: "World") //HelloWorld
stringA.length //10

在Swift扩展中实现初始化程序

  • Swift扩展可以向现有类型添加新的初始化程序。

  • 类的扩展可以添加新的便利初始化程序。
    类的指定初始化程序只能存在于类实现中。

  • 扩展程序中无法使用反初始化器。

注意:指定的初始化程序是类的主要初始化程序。
它必须完全初始化其类引入的所有属性。
一个类可以具有多个指定的初始化程序。

下面给出了带有类的示例实现。

class A {
  
  var name : String
  var age : Int
  
  init(name: String, age: Int) {
      self.age = age
      self.name = name
  }
}

extension A {

  convenience init() {
      self.init(name: "No name yet", age: 0)
  }
}

var a = A()
print(a.name) //prints "No name yet"
print(a.age) //prints 0

我们知道结构会为我们创建所有属性的默认初始化器,如下所示:

struct S {
  
  var name : String
  var age : Int
  
}
var s = S(name: "Anupam", age: 23)

一旦定义了自己的初始化程序,Swift就会禁止我们使用上述默认初始化程序:

struct S {
  
  var name : String
  var age : Int
  
  init(age : Int) {
      self.age = age
      self.name = "A boy has no name"
  }
  
}

var s = S(age: 16)
s.name //A boy has no name
s.age //16

使用扩展功能,我们还可以保留结构提供的默认初始化器,如下所示。

struct S {
  
  var name : String
  var age : Int
}

extension S {
  
  init(age : Int) {
      self.age = age
      self.name = "A boy has no name"
  }
}

var s = S(age: 16)
var s1 = S(name: "Anupam", age: 23)

Swift扩展下标

Swift扩展可以将新的下标添加到现有类型,如下所示。

extension String {
  
  var length: Int {
      return self.characters.count
  }
  
  subscript (i: Int) -> String {
      return self[i ..< i + 1]
  }
  
  subscript (r: Range) -> String {
      let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                          upper: min(length, max(0, r.upperBound))))
      let start = index(startIndex, offsetBy: range.lowerBound)
      let end = index(start, offsetBy: range.upperBound - range.lowerBound)
      return String(self[start ..< end])
  }
}
var sa : String = "hello"
sa[2] //l
sa[0..<4] //hell

我们为字符串创建了扩展名,通过该扩展名,我们可以访问一个字符或者一系列字符,就像数组一样。

Swift协议扩展

我们采用了TableView协议。
不过,还有另一种选择。
我们可以编写一个扩展并使其符合协议,从而使代码的组织和结构比以前更好,如下所示。

//Earlier approach.
class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
  
  //All the functions of both the protocols must be implemented here.
  
}

//Newer and Better Approach
class ViewController : UIViewController {
  
  //Keep class specific code here
  
}

extension ViewController : UITableViewDataSource {
  
  //Implement the methods of DataSource protocol only.
}

extension ViewController : UITableViewDelegate{
  
  //Implement the methods of Delegate protocol only.
}

当扩展中采用协议时,浏览代码结构变得更加容易。

class C : Name
{
  var name: String
  
  init(name: String) {
      self.name = name
  }
}

extension C : Greet {

  func greet() -> String{
      return "Hello, \(name)"
  }
}

var c = C(name: "Anupam")
c.greet() //prints "Hello, Anupam"

使用Swift扩展的嵌套类型

扩展对于创建嵌套类型的类,结构或者枚举很有用。
让我们通过一个例子对此进行解释。

extension String{
  
  var length: Int {
      get {
          return self.characters.count
      }
  }    

  enum Length{
      case Zero, NotZero
  }
  
  var isZero : Length{
      switch self.length{
      case 0 : return .Zero
      default : return .NotZero
      }
  }
}

func checkLength(s: String){
  switch  s.isZero {
  case .Zero:
      print("The length of your string is zero")
  case .NotZero:
      print("The length of your string is NOT zero")
  }
}
var myString = ""
checkLength(s: myString) //prints "The length of your string is zero\n"
myString = "Hi"
checkLength(s: myString) //prints "The length of your string is NOT zero\n"

我们可以使用扩展程序内的枚举根据字符串的长度对字符串进行分组。