热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[WWDC]What'sNewinSwift4?

前言本文主要是笔者小结WWDC2017中《WhatsNewinSwift》的Session,其中也掺杂了些《What’sNewinFoundation》,

前言

本文主要是笔者小结 WWDC2017 中 《What's New in Swift》的 Session ,其中也掺杂了些《What’s New in Foundation》,仅作记录。

下面步入主题。

私有访问控制("Private" Access Control)

SE-0169

在 Swift 4 中,private 修饰的属性可以在 Extension 中访问了,再也不要用 fileprivate 修饰属性了?。

下面我们来区分 Swift 3 与 Swift 4 中的区别。

Swift 3:

access-control0

Swift 4:

类与协议(Class and Subtype Existentials)

SE-0156

在 Swift 3 中,有些童鞋使用代理时,无法同时继承类和协议

class-protocol-composition

Swift 4 中,针对此处进行了改进,直接上 WWDC17 示例代码:


func shareEm(control: UIControl & Shakeable) {control.share()
}protocol Shakeable {func share()
}extension Shakeable {func share() {print("starting share!")}
}extension UIButton: Shakeable { }extension UISlider: Shakeable { }

Smart KeyPaths

SE-0161

在 Swift 4 中新增了一种 Key-Path 表达式,该表达式可用于 KVC & KVO 中的 APIs,格式如下:


\[Type Name].[Property Name]

示例代码如下:


struct SomeStructure {var someProperty: Int
}func smartKeyPath() {let s = SomeStructure(someProperty: 12)let keyPath = \SomeStructure.somePropertylet value = s[keyPath: keyPath]print(value)// value is 12
}

如果在上下文中,能隐含的推断出其类型,那么 Key-Path 表达式中的 Type Name 可以省略,即


\.[Property Name]

如:

@objcMembers class SomeClass: NSObject {dynamic var someProperty: Intinit(someProperty: Int) {self.someProperty = someProperty}
}var observe: NSKeyValueObservation?
let c = SomeClass(someProperty: 10)func smarkKVO() {observe = c.observe(\.someProperty) { object, change in// ...print(object.someProperty, change)}c.someProperty = 10
}

Archival & Serialization

SE-0166

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 4 beta).

我们以下面这段 JSON 为例,来看 Swift 4 中针对 JSON 进行解析的新方法


{"name": "Banana","points": 200,"description": "A banana grown in Ecuador.","varieties": ["yellow","green","brown"]
}

首先,我们要遵循 Codable 协议:


struct GroceryProduct: Codable {let name: Stringlet points: Intlet description: Stringlet varieties: [String]
}

使用 JSONDecoder 进行解析:


let json = """{"name": "Banana","points": 200,"description": "A banana grown in Ecuador.","varieties": ["yellow","green","brown"]}
""".data(using: .utf8)!let decoder = JSONDecoder()
let banana = try! decoder.decode(GroceryProduct.self, from: json)print("\(banana.name) (\(banana.points) points): \(banana.description)")
// Prints "Banana (200 points): A banana grown in Ecuador.

Encoders

SE-0167

本节主要展示 JSONEncoder 编码,直接上代码:


struct University: Codable {enum Level: String, Codable {case one, two, three}var name: Stringvar founds: Intvar type: Level
}func codableTest (_ obj: University) {let encoder = JSONEncoder()let decoder = JSONDecoder()guard let data = try? encoder.encode(obj) else { return }guard let jsonData = try? decoder.decode(University.self, from: data) else { return }print("jsonData:", jsonData)
}

关于字符串(String)

字形群集(Grapheme Cluster)

在 Swift 4 中,修复了字形群集长度计算的一些问题,如 emoji 表情。关于字形群集或者 Unicode 编码概念生疏的童鞋可以看笔者之前写的两篇文章 《字符编码(一)》、《Swift3.0 中 Strings/Characters 闲聊》。下面我们来看看 WWDC17 上的的示例:


var family = "?"
family += "\u{200D}?"
family += "\u{200D}?"
family += "\u{200D}?"print("\(family):\(family.count)")
// result --> ?‍?‍?‍?:1

在之前 family.count 会等于 4(u{200D} 是一个零宽度的 joiner)。

笔者在 Xcode 9 beta1 上运行,选择 Swift 编译语言版本时,测试结果无效,只有在 Xcode 8 测试时 family.count = 4。

swift-compiler-language

字符串改版(String Revision)

SE-0163

在 Swift 2 中,String 的集合这一特性被遗弃,在 Swift 3 中,String 也没有遵守集合的相关协议(如:RangeReplaceableCollection, BidirectionalCollection),因此自 Swift 2 起,String 不是一个集合,而是把这一特性赋予给了 String 的一个属性 --> characters (A view of the string’s contents as a collection of characters.),该属性是 String.CharacterView 类型,并且遵守 RangeReplaceableCollection 协议。


extension String.CharacterView : RangeReplaceableCollection {···}

因此我们在遍历或者操作 String 时,经常会这么写:

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 3.1).” iBooks. https://itunes.apple.com/us/b...


for character in "Dog!?".characters {print(character)
}
// D
// o
// g
// !
// ?

.characters.····。

但,直至 Swift 4,String 又开始遵循集合相关协议,从此可以这么写了:


for character in "Dog!?" {print(character)
}
// D
// o
// g
// !
// ?

当然在 Swift 4 中又出现了一个新的结构体 Substring,Substring 无法直接赋值给 String 的。

sub-strings-error

关于 Substring 与 String 之间的转换可以这么写:


let label = UILabel()
let superStr = "tingxins"
let subStr = superStr.prefix(4)
label.text = String(subStr)
print(subStr)

字符串跨行写法(Multi-Line String Literals)

SE-0168

如果字符串需要跨多行,可以这么写:

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).”.


let quotation = """
The White Rabbit put on his spectacles.
"Where shall I begin, please your Majesty?" he asked."Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""

没错,三对引号。

如果字符串本身包含三个连续的 ‘"""‘ 引号时,可以采用反斜杠进行转义处理(),如:


let threeDoubleQuotes = """
Escaping the first quote \"""
Escaping all three quotes \"\"\"
"""

单面区间语法(One-Sided Ranges)

SE-0172

在 Swift 3 中,区间运算符只有两种:闭区间运算符(Closed Range Operator)、半闭区间运算符(Half-Open Range Operator)。在 Swift 4 中,又新增了一种更加简单方便的区间运算符-->单面区间(One-Sided Ranges)。

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).

你可以这样写:


let names = ["Anna", "Alex", "Brian", "Jack"]for name in names[2...] {print(name)
}
// Brian
// Jackfor name in names[...2] {print(name)
}
// Anna
// Alex
// Brian

当然也和结合半闭区间运算符,可以这么写:


for name in names[..<2] {print(name)
}
// Anna
// Alex

判断区间是否包含&#xff0c;可以这么写&#xff1a;&#xff08;for语句中要注意死循环哈&#xff09;

let range &#61; ...5
range.contains(7) // false
range.contains(4) // true
range.contains(-1) // true”

WWDC17 示例代码&#xff1a;

one-sided-slicing

序列协议&#xff08;Sequence&#xff09;

SE-0142

在 Swift 3 中&#xff0c;假设我们要为 Sequence 扩展一个方法&#xff0c;要这么写&#xff1a;


extension Sequence where Iterator.Element: Equatable {func containsOnly(_ value: Iterator.Element) -> Bool {return contains { (element) -> Bool inreturn element &#61;&#61; value}}
}

但在 Swift 4 中&#xff0c; 针对 Sequence 做了一些小改进&#xff0c;使我们代码更加轻便&#xff0c;看起来更加清爽&#xff1a;

extension Sequence where Element: Equatable {func containsOnly(_ value: Element) -> Bool {return contains { (element) -> Bool inreturn element &#61;&#61; value}}
}

这是怎么实现的呢&#xff1f;因为在 Swift 4 中&#xff0c;我们在声明一个 associatedtype 的 placeholder 时&#xff0c;我们可以使用 where 语句了。

下面我们来对比一下 Swift 3 与 Swift 4 中 Sequence 的区别&#xff1a;

在 Swift 3 中 Sequence 协议是这么写的&#xff1a;

sequence-in-swift3

在 Swift 4 中进行改进后&#xff0c;是这么写的&#xff1a;

sequence-in-swift4

对比看完后&#xff0c;想必读者一目了然。

下面针对 associatedtype 中使用 where 语句&#xff0c;我们再来看个例子&#xff1a;

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).


protocol Container {associatedtype Itemmutating func append(_ item: Item)var count: Int { get }subscript(i: Int) -> Item { get }associatedtype Iterator: IteratorProtocol where Iterator.Element &#61;&#61; Itemfunc makeIterator() -> Iterator
}

如果在 Swift 3 下写&#xff0c;Xcode 会出现这样的编译错误:

associated-type-error-swift3

有了上面这些特性后&#xff0c;我们在使用 Swift 4 时&#xff0c;可以省略一些冗余约束&#xff0c;这里直接上 WWDC17 的示例代码&#xff1a;

在 Swift 3 中&#xff0c;是这样写的&#xff1a;

redundant-constraints-b1

redundant-constraints-b2

在 Swift 4 中&#xff0c;现在我们可以这么写&#xff1a;

redundant-constraints-a1

redundant-constraints-a2

泛型下标&#xff08;Generic Subscripts&#xff09;

SE-0148

在 Swift 4 中&#xff0c;现在支持泛型下标了&#xff0c;直接上代码&#xff1a;

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).


extension Container {subscript(indices: Indices) -> [Item]where Indices.Iterator.Element &#61;&#61; Int {var result &#61; [Item]()for index in indices {result.append(self[index])}return result}
}

上述代码我们为 Container 添加了下标取值能力&#xff0c;在这个泛型下标中有 3 个约束&#xff1a;

  • 泛型参数 Indices 遵守 Sequence 协议

  • indices 是 Indices 类型的一个实例

  • 泛型 where 语句筛选 Indices.Iterator.Element 为 Int 类型

关于整型&#xff08;Protocol-oriented integers&#xff09;

SE-0104

字典与集合&#xff08;Dictionary & Set enhancements&#xff09;

SE-0165

Number 对象桥接&#xff08;NSNumber bridging and Numeric types&#xff09;

SE-0170

Swift 3 中&#xff0c;NSNumber 转换有个 Bug&#xff0c;如&#xff1a;


let n &#61; NSNumber(value: UInt32(543))
let v &#61; n as? Int8
// v is 31

Swift 4 中已修复&#xff1a;

可变集合&#xff08;MutableCollection&#xff09;

SE-0173

现在可变集合增加了一个方法&#xff0c;我们可以直接使用 swapAt 方法&#xff0c;而非 swap 。


let university0 &#61; University(name: "Qsting", founds: 1870, type: .one)
let university1 &#61; University(name: "tingxins", founds: 1870, type: .one)
var mutableCollection &#61; [university0, university1]print(mutableCollection)
mutableCollection.swapAt(0, 1) //交换数组中0、1元素的位置
print(mutableCollection)

Change filter to return Self for RangeReplaceableCollection

SE-0174

参考链接

  • https://developer.apple.com/v...

  • https://github.com/apple/swif...

  • https://github.com/ole/whats-...

  • https://developer.apple.com/l...

  • https://developer.apple.com/l...

广告

欢迎关注微信公众号

wechat-qrcode



推荐阅读
  • 我的iOS开发入门自学路径
    我有一个清单,列着希望在大学里完成的事。比如,学一门乐器,和朋友去旅游,搭建自己的博客,去滑翔,看各主题的书籍。其中一项是,写自己的App并且上架。去年开始,我准备完成这一项,所以 ... [详细]
  • jsappsugar,基于,js,语法,定义 ... [详细]
  • ObjectiveC与Swift之间的互相调用和跳转
    Objective-C与Swift之间的互相调用和跳转-一、OC和Swift互相跳转首先在需要引入Swift的文件中导入头文件#import工程名-Swift.hOC跳转Swift ... [详细]
  • UIView视图,表示屏幕上的一块矩形区域,同时处理该区域的绘制和触屏事件。一个视图也可以作为其他视图的父视图,同时决定着这些子视图的位置和大小.UIView类做了大量的工作去管理 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • Objective C接入Sonar代码扫描
    目录技术方案环境准备扫描器配置项目配置SonarQube配置jenkins接入一些坑技术方案Sonar本身有对OC的代码扫描插件——SonarCFamily,但是是收费的。出于成本 ... [详细]
  • iOS安全攻防(二十四):敏感逻辑的保护方案(1)Objective-C代码容易被hook,暴露信息太赤裸裸,为了安全,改用C来写吧!当然不是全部代码都要C来写,我指的是敏感业务逻 ... [详细]
  • IvebeentryingforadayortwototryandgetashadowtodrawinsidethetextofanNSTextField ... [详细]
  • 闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。Swift中的闭包与C和Objective-C中的代码块(blocks)以及其他一些编程语言中的 ... [详细]
  • 多态性这个词表示有许多形式。通常,当存在类的层次结构并且通过继承相关时,会发生多态性。Objective-C多态表示对成员函数的调用将导致执行不同的函数,具体取决于调用该函数的对 ... [详细]
  • 运行就报对我有效的解决方法是:把真机和模拟器需要的文件手动加入其中,具体请参考网络上提供的其他解决方 ... [详细]
  • 概述UIStackView是iOS9中新增的API,类似于Android中的线性布局。UIStackView相当于一个容器,根据向UIStackView中添加视图的顺序,UIStack ... [详细]
author-avatar
手机用户2502882045
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有