Ios开发SwiftSwift

Swift4相对于Swift3的改变

2017-09-05  本文已影响104人  狂奔的胖蜗牛

1.字符串Strings

swift3中,我们要遍历字符串,需要这样做:

let string = "abcd"
for char in string.characters {
    print(char)
}

到了Swift4,我们可以直接使用:

let string = "abcd"
for char in string {
    print(char)
}

swift3中,需要对字符串中的字符进行操作时,需要这样做:

string.characters.count
string.characters.dropFirst()
string.characters.reversed()
let result = string.characters.filter { char in
    return char != "c"
}
result

swift4中:

string.count
string.dropFirst()
string.reversed()
let result = string.filter { char in
    return char != "c"
}
result

2.字典dic和集合set

swift4增加了从数组创建出字典的能力

let nearestStarNames = [ “Proxima Centauri”,“Alpha Centauri A”,“Alpha Centauri B”,“Barnard's Star”,“Wolf 359”)
let nearestStarDistances = [4.24,4.37,4.37,5.96,7.78]

let starDistanceDict = Dictionary(uniqueKeysWithValues:zip(nearestStarNames,nearestStarDistances))
// [ “Wolf 359”:7.78,“Alpha Centauri B”:4.37,“Proxima Centauri”:4.24,“Alpha Centauri A”:4.37,“Barnard's Star”:5.96]

可以利用具有重复的key的数组去创建字典,并不会有什么问题。

let favoriteStarVotes = ["Alpha Centauri A", "Wolf 359", "Alpha Centauri A", "Barnard's Star"]
let mergedKeysAndValues = Dictionary(zip(favoriteStarVotes, repeatElement(1, count: favoriteStarVotes.count)), uniquingKeysWith: +)
 // ["Barnard's Star": 1, "Alpha Centauri A": 2, "Wolf 359": 1]

字典和集合现在具有了过滤的功能

closeStars = starDistanceDict.filter { $0.value < 5.0 }
closeStars // Dictionary: ["Proxima Centauri": 4.24, "Alpha Centauri A": 4.37, "Alpha Centauri B": 4.37]

字典有了一个新的方法,可以直接映射他的值

//将closeStars的value转换成字符串
let mappedCloseStars = closeStars.mapValues { “\($ 0)” }
mappedCloseStars // [ “Proxima Centauri”:“4.24”,“Alpha Centauri A”:“4.37”,“Alpha Centauri B”:“4.37” ]

字典有了新的方法给与取值时返回默认值

let siriusDistance = mappedCloseStars["Wolf 359", default: "unknown"] // "unknown"

var starWordsCount: [String: Int] = [:]
for starName in nearestStarNames {
  let numWords = starName.split(separator: " ").count
  starWordsCount[starName, default: 0] += numWords // Amazing 
}
starWordsCount // ["Wolf 359": 2, "Alpha Centauri B": 3, "Proxima Centauri": 2, "Alpha Centauri A": 3, "Barnard's Star": 2]

字典有了一个分组功能,能够根据指定的方式进行分组

//按照首字母进行分组
let starsByFirstLetter = Dictionary(grouping: nearestStarNames) { $0.first! }

// ["B": ["Barnard's Star"], "A": ["Alpha Centauri A", "Alpha Centauri B"], "W": ["Wolf 359"], "P": ["Proxima Centauri"]]

字典和集合有了预留容量的功能,当了解自己需要多大的容量时,可以指定

starWordsCount.capacity  // 6
starWordsCount.reserveCapacity(20) //预留了20的空间
starWordsCount.capacity // 24

3.修饰符

private在swift3中,表示该成员在类中可以使用,在开发过程中,我们经常需要给类写扩展,而在swift3中,在扩展里面,我们是无法访问到private修饰的成员的。虽说可以用fileprivate来解决。这个问题在swift4中得到了修改,在扩展中可以使用private修饰的成员。

struct SpaceCraft {
  private let warpCode: String

  init(warpCode: String) {
    self.warpCode = warpCode
  }
}

extension SpaceCraft {
  func goToWarpSpeed(warpCode: String) {
    if warpCode == self.warpCode { //在swift3中会报错
      print("Do it Scotty!")
    }
  }
}

let enterprise = SpaceCraft(warpCode: "KirkIsCool")
//enterprise.warpCode  // 这里使用依然会报错,想要在这里也能访问,需要修改为fileprivate
enterprise.goToWarpSpeed(warpCode: "KirkIsCool") 

4.新增API


序列化和归档

swift4中,对一个class、struct、enum进行序列化和归档,会变得非常容易

//遵循该协议
struct CuriosityLog: Codable {
  enum Discovery: String, Codable {
    case rock, water, martian
  }

  var sol: Int
  var discoveries: [Discovery]
}

let logSol42 = CuriosityLog(sol: 42, discoveries: [.rock, .rock, .rock, .rock])

let jsonEncoder = JSONEncoder() // 指定解释器

// 开始将数据编码成字符串
let jsonData = try jsonEncoder.encode(logSol42)
// 创建出jsonstring
let jsonString = String(data: jsonData, encoding: .utf8) // "{"sol":42,"discoveries":["rock","rock","rock","rock"]}"

//通过字符串生成需要的类型或者对象
let jsonDecoder = JSONDecoder() // 指定解码器
let decodedLog = try jsonDecoder.decode(CuriosityLog.self, from: jsonData)
decodedLog.sol         // 42
decodedLog.discoveries // [rock, rock, rock, rock]


通过类型的关键路径来或者/设置实例的基础值

struct Lightsaber {
  enum Color {
    case blue, green, red
  }
  let color: Color
}

class ForceUser {
  var name: String
  var lightsaber: Lightsaber
  var master: ForceUser?

  init(name: String, lightsaber: Lightsaber, master: ForceUser? = nil) {
    self.name = name
    self.lightsaber = lightsaber
    self.master = master
  }
}

let sidious = ForceUser(name: "Darth Sidious", lightsaber: Lightsaber(color: .red))
let obiwan = ForceUser(name: "Obi-Wan Kenobi", lightsaber: Lightsaber(color: .blue))
let anakin = ForceUser(name: "Anakin Skywalker", lightsaber: Lightsaber(color: .blue), master: obi wan)

//通过路径获取
let nameKeyPath = \ForceUser.name
let obiwanName = obiwan[keyPath: nameKeyPath]  // "Obi-Wan Kenobi"

let anakinSaberColor = anakin[keyPath: \ForceUser.lightsaber.color]  // blue

//返回对象的引用
let masterKeyPath = \ForceUser.master
let anakinMasterName = anakin[keyPath: masterKeyPath]?.name  // "Obi-Wan Kenobi"

//设置
anakin[keyPath: masterKeyPath] = sidious
anakin.master?.name // Darth Sidious


多行字符串

增加了多行字符串,而不必使用\n来实现。

let star = "⭐️"
let introString = """
  A long time ago in a galaxy far,
  far away....

  You could write multi-lined strings
  without "escaping" single quotes.

  The indentation of the closing quotes
       below deside where the text line
  begins.

  You can even dynamically add values
  from properties: \(star)
  """
print(introString)

增加单面范围

var planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
let outsideAsteroidBelt = planets[4...] // swift3: planets[4..<planets.endIndex]
let firstThree = planets[..<4]          // swift3: planets[planets.startIndex..<4]

无限序列

var numberedPlanets = Array(zip(1..., planets))
print(numberedPlanets) // [(1, "Mercury"), (2, "Venus"), ..., (8, "Neptune")]

planets.append("Pluto")
numberedPlanets = Array(zip(1..., planets))
print(numberedPlanets) // [(1, "Mercury"), (2, "Venus"), ..., (9, "Pluto")]

模式匹配

func temperature(planetNumber: Int) {
  switch planetNumber {
  case ...2: // 小于等于2的值
    print("Too hot")
  case 4...: // 大于等于4的值
    print("Too cold")
  default:
    print("Justtttt right")
  }
}

temperature(planetNumber: 3) // Justtttt right

通用下标

struct GenericDictionary<Key: Hashable, Value> {
  private var data: [Key: Value]

  init(data: [Key: Value]) {
    self.data = data
  }

  subscript<T>(key: Key) -> T? {
    return data[key] as? T
  }
}

//字典类型  [String: Any]
var earthData = GenericDictionary(data: ["name": "Earth", "population": 7500000000, "moons": 1])

// 自动推断类型有没有 "as? String"
let name: String? = earthData["name"]

// 自动推断类型有没有 "as? Int"
let population: Int? = earthData["population"]

extension GenericDictionary {
  subscript<Keys: Sequence>(keys: Keys) -> [Value] where Keys.Iterator.Element == Key {
    var values: [Value] = []
    for key in keys {
      if let value = data[key] {
        values.append(value)
      }
    }
    return values
  }
}

let nameAndMoons = earthData[["moons", "name"]]        // [1, "Earth"]
let nameAndMoons2 = earthData[Set(["moons", "name"])]  // [1, "Earth"]

交换索引值swapAt(::)

func bubbleSort<T: Comparable>(_ array: [T]) -> [T] {
  var sortedArray = array
  for i in 0..<sortedArray.count - 1 {
    for j in 1..<sortedArray.count {
      if sortedArray[j-1] > sortedArray[j] {
        sortedArray.swapAt(j-1, j) 
      }
    }
  }
  return sortedArray
}

bubbleSort([4, 3, 2, 1, 0]) // [0, 1, 2, 3, 4]

限制关联类型

protocol MyProtocol {
  associatedtype Element
  associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
}

类和协议共存

protocol MyProtocol { }
class View { }
class ViewSubclass: View, MyProtocol { }

class MyClass {
  var delegate: (View & MyProtocol)?
}

let myClass = MyClass()
//myClass.delegate = View() // 会报错,需要的是该类型: '(View & MyProtocol)?'
myClass.delegate = ViewSubclass()

NSNumber桥接

let n = NSNumber(value: 999)
let v = n as? UInt8 // Swift 4: nil, Swift 3: 231
上一篇下一篇

猜你喜欢

热点阅读