Swift4相对于Swift3的改变

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

推荐阅读更多精彩内容

  • 因为要结局swift3.0中引用snapKit的问题,看到一篇介绍Xcode8,swift3变化的文章,觉得很详细...
    uniapp阅读 4,385评论 0 12
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,771评论 1 10
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,591评论 18 139
  • 今天是父亲节。 提起父亲,相信很多人和我一样,既有满满的温暖和感动,也有遗憾和不解。父亲,在很多国人心中,是一个沉...
    朱若霞阅读 1,042评论 0 1
  • 最近对单位的一位同事发生了不同的认识。 他最早是二老板的司机,没多久就调去开叉车。每天平常而普通。 上个月,偶尔跟...
    徐徐道来阅读 242评论 0 0