巩固—Swift 4.0 基础知识(一)

元组

  • 定义: 可以将多个不同类型的值合成单个复合值。(可以是任意类型的)
  • 使用:
    • 可以将内容分为常量或变量进行常规访问:

       let https = (404,"Not Found") 
       let (statusCode, statusMessage) = https
       print("The status code is \(statusCode)") //输出:The status code is 404
      
    • 如只需某些元组的值,可以用“_”来忽略元组的部分值

       let (value , _ ) = https
       print("The status code is \(value)") //输出:The status code is 404
      
    • 使用从0开始索引访问元组各个元素值或给元组各个元素命名来访问

        let examples = (a:200,b:"OK")
        print("The value is \(examples.0)") //输出:The value is 200
        print("The value is \(examples.a)") //输出:The value is 200
      
    • 适用:

      • 作为函数的返回值特别有用
      • 互换值:(a,b)= (b,a) 等

可选类型

  • 定义:可能不存在值的数据类型。两种可能:要么是有一个值,你可以解开可选的访问值,或者是没有价值可言,为nil。
    • 注意: Object-C和swift中的nil不同:OC中是一个指向不存在对象的指针,只适用于对象(引用)类型,不适用与值类型。swift中nil不是一个指针,它是没有某种类型的值,任何类型的可选项都可以设置为nil,而不仅仅是对象类型。
  • 使用:
    • 如果你的代码中的常量或者变量在某些情况下缺少值时使用,则始终将其声明为适当类型的可选值。(可选类型默认值:nil)

    • 一般展开可选类型的写法

        if 可选类型名 != nil {
            print("It must have a value \(可选类型名!) ")
        } 
      
    • 安全展开可选类型的写法(可选绑定:来确定可选项是否包含值,如果是,则将值用作临时常量或变量。否则走else)

        if let newValue = 可选类型名 {
            print("It must have a value \(newValue) ")
        } 
        重点:可以包含多个(let newValue = 可选类型名),中间用“,”隔开,只要其中一个为nil则整个表达式都为否。
      
    • 可以使用感叹号来访问其基础值(注:一旦使用!访问,必须保证一定存在值,否则将error)

    • ??:进行解包,如果包含值则返回本身,否则返回默认值。a ?? b <==> a != nil ? a! : b

  • 隐式解析可选类型
    • 定义后缀!作为标准库中命名类型Optional的语法糖,来实现自动解包的功能

        var implicitlyUnwrappedString: String!
        var explicitlyUnwrappedString: Optional
      
    • 注意:由于隐式解包修改了包含器类型的声明语义,嵌套在元组类型或泛型的可选类型(比如字典元素类型或数组元素类型),不能被标记为隐式解包。

        let tupleOfImplicitlyUnwrappedElements: (Int!, Int!)  // 错误
        let implicitlyUnwrappedTuple: (Int, Int)!             // 正确
        
        let arrayOfImplicitlyUnwrappedElements: [Int!]        // 错误
        let implicitlyUnwrappedArray: [Int]!                  // 正确
      

元类型

  • 定义: 元类型是指类型的类型,包括类类型、结构体类型、枚举类型和协议类型。
  • 获取元类型:类、结构体或枚举类型的元类型是相应的类型名紧跟.Type。协议类型的元类型——并不是运行时符合该协议的具体类型——而是该协议名字紧跟.Protocol。比如,类SomeClass的元类型就是SomeClass.Type,协议SomeProtocol的元类型就是SomeProtocal.Protocol
  • 类型名.self来获取类型。也可以使用type(of:)来获取该实例在运行期的类型。

使用goard的正确姿势

  • 可以用goard:在验证入口条件时

      func refreshData() {
          let session = Int("12")
          goard let value = session else {reture}
          print("\(session!)")
      } 
      好处:
          1.一眼看出,这个条件检查并不是函数本身的功用,而是函数执行的先决条件。
          2.如果有人不小心将提前退出的语句从 else 表达式中移除了,编译器会及时告诉你这个错误。
    
  • 使用场景:方法中存在非常长的执行路径,在最终结果得到之前,中间会有多个需要被满足的条件,这些条件都应该为真,否则应该直接 return 或者抛出异常。(这些条件可以用guard抛出)

  • 可以用 guard:在可选值解包时(拍扁 if let..else 金字塔):使用 guard 的方式来解包可选值是非常推荐的。if let 的方式需要在大括号内使用解包之后的值,而 guard 语句将解包之后的值添加到了之后的作用域之中——所以你可以在使用 guard 解包之后直接使用它,不用包裹在大括号内。

       guard let id = json["id"] as? Int,
        let name = json["name"] as? String,
        let userId = json["user_id"] as? Int,
        let position = json["pos"] as? Double
      else {
          throw ParsingError.MissingData
      }
      return Task(id: id, name: name, userId: userId, position: position)
    

错误处理

  • 可以使用值得存在或不存在来传达函数的成功或失败,错误处理允许您确定故障的根本原因,如有必要,将错误传播到程序的一部分。

      如:throws关键字来引发错误
      func canThrowAnError() throws {
          
      }
      使用:当调用此函数时,需要使用如下方式,并加上try关键字,catch可以是多个
      do {
          try canThrowAnError()
      } catch {
      
      }
    

断言和前提条件

  • 定义:断言和前提条件是在运行时发生的检查。在执行任何其他代码之前,您可以使用它们确保满足基本条件。如果断言或前提条件中的布尔条件评估为true,则代码执行情况依然如常。如果条件求值false,程序的当前状态无效; 代码执行结束,您的应用程序已终止
  • 使用:
    • assert(age >= 0, "A person's age can't be less than zero."): 当条件为false就会抛出error错误信息,
    • precondition(index > 0, "Index must be greater than zero.") :同上
    • assertionFailure("A person's age can't be less than zero."):当已经检查了某条件时,可以直接吃用此方法抛出错误
    • preconditionFailure("A person's age can't be less than zero."):同上

基本运算符

  • a...b :全封闭区间,相当于[a,b];

  • a..

  • 单面范围: [a...],[...b],[..

      for name in names[2...] { //从下标2开始到最后
          print(name)
      }
      for name in names[...2] { //从下标0到下标2的所有元素
          print(name)
      }
    

字符串与字符

  • 如果需要一个跨多行的字符串,请使用多行字符串文字 - 由三个双引号包围的一系列字符。

      如:let example = """
      The first row 
      
      The sencond Row 
      ...
      """
    
  • 使用”+“来拼接两个字符串。

      //实例
      let badStart = """
      one
      two
      """
      let end = """
      three
      """
      print(badStart + end)
      // Prints two lines:
      // one
      // twothree
       
      let goodStart = """
      one
      two
       
      """
      print(goodStart + end)
      // Prints three lines:
      // one
      // two
      // three
    
  • 可以使用”()“进行插入值。

  • 使用index(before:)and index(after:)方法访问给定索引之前和之后的索引String。要访问远离给定索引的索引,您可以使用该index(_:offsetBy:)方法,而不是多次调用其中一个方法。

      let greeting = "Guten Tag!"
      greeting[greeting.startIndex]
      // G
      greeting[greeting.index(before: greeting.endIndex)]
      // !
      greeting[greeting.index(after: greeting.startIndex)]
      // u
      let index = greeting.index(greeting.startIndex, offsetBy: 7)
      greeting[index]
      // a
      注意:endIndex是最后一个字符的下一个字符的索引,greeting[greeting.endIndex] // Error
    
  • 使用该indices属性访问字符串中单个字符的所有索引。

      for index in greeting.indices {
          print("\(greeting[index]) ", terminator: "")
      }
      // Prints "G u t e n   T a g ! "
      注意: terminator:关键字表示不换行。
    
  • 插入和删除(都是索引值,切记不是整数):

    • 要将单个字符插入到指定索引的字符串中,请使用该insert(_:at:)方法,并在指定的索引处插入另一个字符串的内容,然后使用该insert(contentsOf:at:)方法。
    • 要从指定索引的字符串中删除单个字符,请使用该remove(at:)方法,并删除指定范围内的子字符串,请使用以下removeSubrange(_:)方法:
  • 比较字符串: ”==“,(Swift中的字符串和字符比较不区分大小写。)

  • 前缀和后缀:要检查字符串是否具有特定的字符串前缀或后缀,请调用字符串hasPrefix("字符串")和 hasSuffix("字符串")方法

  • UTF-8、UTF-16和Unicode表示字符串

      for codeUnit in dogString.utf8 {
          print("\(codeUnit) ", terminator: "")
      }
      print("")
      // Prints "68 111 103 226 128 188 240 159 144 182 "
      
      for codeUnit in dogString.utf16 {
          print("\(codeUnit) ", terminator: "")
      }
      print("")
      // Prints "68 111 103 8252 55357 56374 "
      
      for scalar in dogString.unicodeScalars {
          print("\(scalar.value) ", terminator: "")
      }
      print("")
      // Prints "68 111 103 8252 128054 "
      for scalar in dogString.unicodeScalars {
          print("\(scalar) ", terminator: "")
      }
      //Prints "D o g !! "
    

集合类型

  • 数组遍历:
    定义:

      var someInts = [Int]()
      var threeDoubles = Array(repeating: 0.0, count: 3)
      // threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
      var shoppingList: [String] = ["Eggs", "Milk"]
      
      for (index, value) in shoppingList.enumerated() {
          print("Item \(index + 1): \(value)")
      }
      // Item 1: Six eggs
      // Item 2: Milk
      // Item 3: Flour
      // Item 4: Baking Powder
      // Item 5: Bananas
    
  • 集合:

  • 定义:

      var letters = Set()
      or
      var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
    
    • 使用该intersection(_:)方法创建一个仅具有两个集合通用值的新集合。
    • 使用该symmetricDifference(_:)方法创建一个新集合,其中的值可以是任一集,但不能同时使用。
    • 使用该union(_:)方法创建一个新集合,其中所有值都在两个集合中。
    • 使用该subtracting(_:)方法创建一个新集合,其值不在指定的集合中。
    • 使用“等于”运算符(==)来确定两个集合是否包含所有相同的值。
    • 使用该isSubset(of:)方法确定集合的所有值是否包含在指定的集合中。
    • 使用该isSuperset(of:)方法来确定集合是否包含指定集合中的所有值。
    • 使用isStrictSubset(of:)或isStrictSuperset(of:)方法来确定集合是子集还是超集,但不等于指定集。
    • 使用该isDisjoint(with:)方法来确定两个集合是否没有共同的值。
  • 字典:

  • 定义:

      var namesOfIntegers = [Int: String]()
      // namesOfIntegers is an empty [Int: String] dictionary
      var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
    
  • 遍历

      for (airportCode, airportName) in airports {
          print("\(airportCode): \(airportName)")
      }
      // YYZ: Toronto Pearson
      // LHR: London Heathrow
      
      等价于下面:
      for airportCode in airports.keys {
          print("Airport code: \(airportCode)")
      }
      // Airport code: YYZ
      // Airport code: LHR
       
      for airportName in airports.values {
          print("Airport name: \(airportName)")
      }
      // Airport name: Toronto Pearson
      // Airport name: London Heathrow
    
  • 新的遍历方式:

      使用该stride(from:to:by:)功能跳过不需要的标记。
      let minuteInterval = 5
      for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
          // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
      }
      
      也可以使用闭合范围stride(from:through:by:):
      let hours = 12
      let hourInterval = 3
      for tickMark in stride(from: 3, through: hours, by: hourInterval) {
          // render the tick mark every 3 hours (3, 6, 9, 12)
      }

你可能感兴趣的:(巩固—Swift 4.0 基础知识(一))