Swift 4.0 新特征汇总及演示附 Demo(下)

简介: Swift 4.0 新特征汇总及演示附 Demo(下)

四、Codable 序列化


如果要将一个对象持久化,需要把这个对象序列化。过去的做法是实现 NSCoding 协议,但实现 NSCoding 协议的代码写起来很繁琐,尤其是当属性非常多的时候。 Swift 4 中引入了 Codable 协议,可以大大减轻了我们的工作量。我们只需要让需要序列化的对象符合 Codable 协议即可,不用再写任何其他的代码。


struct Language: Codable {
    var name: String
    var version: Int
}


1.Encode 操作 我们可以直接把符合了 Codable 协议的对象 encode 成 JSON 或者 PropertyList。


let swift = Language(name: "Swift", version: 4)
//encoded对象
let encodedData = try JSONEncoder().encode(swift)
//从encoded对象获取String
let jsonString = String(data: encodedData, encoding: .utf8)
print(jsonString)


image.png


2.Decode 操作

let decodedData = try JSONDecoder().decode(Language.self, from: encodedData)
print(decodedData.name, decodedData.version)


image.png


五、Subtring


Swift 4 中有一个很大的变化就是 String 可以当做 Collection 来用,并不是因为 String 实现了 Collection 协议,而是 String 本身增加了很多 Collection 协议中的方法,使得 String 在使用时看上去就是个 Collection。


let str = "hangge.com"
print(str.prefix(5)) // "hangg"
print(str.suffix(5)) // "e.com"
print(str.dropFirst()) // "angge.com"
print(str.dropLast()) // "hangge.co"


比如上面的样例,我们使用一些 Collection 协议的方法对字符串进行截取,只不过它们的返回结果不是 String 类型,而是 Swift 4 新增的 Substring 类型。

1.为何要引入 Substring? 既然我们想要的到的就是字符串,那么直接返回 String 就好了,为什么还要多此一举返回 Substring。原因只有一个:性能。具体可以参考下图: 当我们用一些 Collection 的方式得到 String 里的一部分时,创建的都是 Substring。Substring 与原 String 是共享一个 Storage。这意味我们在操作这个部分的时候,是不需要频繁的去创建内存,从而使得 Swift 4 的 String 相关操作可以获取比较高的性能。 而当我们显式地将 Substring 转成 String 的时候,才会 Copy 一份 String 到新的内存空间来,这时新的 String 和之前的 String 就没有关系了。


2.使用 Substring 的注意事项 由于 Substring 与原 String 是共享存储空间的,只要我们使用了 Substring,原 String 就会存在内存空间中。只有 Substring 被释放以后,整个 String 才会被释放。 而且 Substring 类型无法直接赋值给需要 String 类型的地方,我们必须用 String() 包一层。当然这时系统就会通过复制创建出一个新的字符串对象,之后原字符串就会被释放。


3.使用样例 这里对 String 进行扩展,新增一个 subString 方法。直接可以根据起始位置(Int 类型)和需要的长度(Int 类型),来截取出子字符串。

extension String {
    //根据开始位置和长度截取字符串
    func subString(start:Int, length:Int = -1) -> String {
        var len = length
        if len == -1 {
            len = self.count - start
        }
        let st = self.index(startIndex, offsetBy:start)
        let en = self.index(st, offsetBy:len)
        return String(self[st ..< en])
    }
}


使用样例:

let str1 = "欢迎访问hangge.com"
let str2 = str1.subString(start: 4, length: 6)
print("原字符串:\(str1)")
print("截取出的字符串:\(str2)")

运行结果如下:


image.png


注意:这个方法最后我们会将 Substring 显式地转成 String 再返回。


六、废除 swap 方法


(1)过去我们会使用 swap(::) 来将两个变量的值进行交换:

var a = 1
var b = 2
swap(&a, &b)
print(a, b)

(2)后面 swap() 方法将会被废弃,建议使用 tuple(元组)特性来实现值交换,也只需要一句话就能实现:

var a = 1
var b = 2
(b, a) = (a, b)
print(a, b)

使用 tuple 方式的好处是,多个变量值也可以一起进行交换:

var a = 1
var b = 2
var c = 3
(a, b, c) = (b, c, a)
print(a, b, c)

(3)补充一下:现在数组增加了个 swapAt 方法可以实现两个元素的位置交换。

var fruits = ["apple", "pear", "grape", "banana"]
//交换元素位置(第2个和第3个元素位置进行交换)
fruits.swapAt(1, 2)
print(fruits)


image.png


七、减少隐式 @objc 自动推断


1.过去的情况(Swift 3) (1)在项目中如果想把 Swift 写的 API 暴露给 Objective-C 调用,需要增加 @objc。在 Swift 3 中,编译器会在很多地方为我们隐式的加上 @objc。 (2)比如当一个类继承于 NSObject,那么这个类的所有方法都会被隐式的加上 @objc。

class MyClass: NSObject {
    func print() { } // 包含隐式的 @objc
    func show() { } // 包含隐式的 @objc
}

(3)但这样做很多并不需要暴露给 Objective-C 也被加上了 @objc。而大量 @objc 会导致二进制文件大小的增加。

2.现在的情况(Swift 4) (1)在 Swift 4 中隐式 @objc 自动推断只会发生在下面这种必须要使用 @objc 的情况:

  • 覆盖父类的 Objective-C 方法
  • 符合一个 Objective-C 的协议

(2)大多数地方必须手工显示地加上 @objc。

class MyClass: NSObject {
    @objc func print() { } //显示的加上 @objc
    @objc func show() { } //显示的加上 @objc
}

(3)如果在类前加上 @objcMembers,那么它、它的子类、扩展里的方法都会隐式的加上 @objc。

@objcMembers
class MyClass: NSObject {
    func print() { } //包含隐式的 @objc
    func show() { } //包含隐式的 @objc
}
extension MyClass {
    func baz() { } //包含隐式的 @objc
}

(4)如果在扩展(extension)前加上 @objc,那么该扩展里的方法都会隐式的加上 @objc。

class SwiftClass { }
@objc extension SwiftClass {
    func foo() { } //包含隐式的 @objc
    func bar() { } //包含隐式的 @objc
}


(5)如果在扩展(extension)前加上 @nonobjc,那么该扩展里的方法都不会隐式的加上 @objc。

@objcMembers
class MyClass : NSObject {
    func wibble() { } //包含隐式的 @objc
}
@nonobjc extension MyClass {
    func wobble() { } //不会包含隐式的 @objc
}


目录
相关文章
|
安全 Swift 容器
Swift 4.0 新特征汇总及演示附 Demo(上)
Swift 4.0 新特征汇总及演示附 Demo(上)
110 0
Swift 4.0 新特征汇总及演示附 Demo(上)
|
存储 Swift
Swift Core Data 图片存储与读取Demo
实体的模型定义: 实体的class定义: @objc(ImageEntity) class ImageEntity: NSManagedObject { @NSManaged...
1045 0
|
6月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
381 2
|
4月前
|
Unix 调度 Swift
苹果iOS新手开发之Swift 中获取时间戳有哪些方式?
在Swift中获取时间戳有四种常见方式:1) 使用`Date`对象获取秒级或毫秒级时间戳;2) 通过`CFAbsoluteTimeGetCurrent`获取Core Foundation的秒数,需转换为Unix时间戳;3) 使用`DispatchTime.now()`获取纳秒级精度的调度时间点;4) `ProcessInfo`提供设备启动后的秒数,不表示绝对时间。不同方法适用于不同的精度和场景需求。
131 3
|
10天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
24 1
|
19天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
【10月更文挑战第18天】本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户按下按钮时,按钮将从圆形变为椭圆形并从蓝色渐变为绿色;释放按钮时,动画恢复原状。通过UIView的动画方法和弹簧动画效果,实现平滑自然的动画过渡。
43 5
|
3月前
|
存储 移动开发 Swift
使用Swift进行iOS应用开发:探索现代移动开发的魅力
【8月更文挑战第12天】使用Swift进行iOS应用开发,不仅能够享受到Swift语言带来的简洁、快速、安全的编程体验,还能够充分利用iOS平台提供的丰富资源和强大功能。然而,iOS应用开发并非易事,需要开发者具备扎实的编程基础、丰富的实践经验和不断学习的精神。希望本文能够为您的iOS应用开发之旅提供一些有益的参考和帮助。
|
4月前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
70 7
|
4月前
|
调度 Swift Android开发
苹果iOS新手开发之Swift中的并发任务和消息机制
Swift的消息机制类似Android的Handler,实现任务调度有三种方式: 1. **Grand Central Dispatch (GCD)**:使用`DispatchQueue`在主线程或后台线程执行任务。 2. **OperationQueue**:提供高级接口管理`Operation`对象。 3. **RunLoop**:处理事件如输入源、计时器,类似Android的`Looper`和`Handler`。 **示例**: - GCD:在不同线程执行代码块。 - OperationQueue:创建操作并执行。 - RunLoop:用Timer添加到RunLoop中。
97 2
|
4月前
|
安全 编译器 Swift
探索iOS开发:Swift语言的现代魔法
【7月更文挑战第11天】本文深入探讨了Swift编程语言,它如何革新iOS开发领域,以及它为开发者带来的独特优势。我们将从Swift的基础语法出发,通过实际案例分析其性能优化技巧,最后讨论Swift在跨平台开发中的潜力。文章旨在为读者提供一个全面而深入的视角,了解Swift不仅仅是一门语言,更是一种推动创新的力量。