Swift 5.2 发布以及 5.3 规划

最近 Swift 5.2 正式发布了,该版本主要提升了开发体验:

  • 强化了 compiler diagnostics(包括错误和警告),以及 code completion
  • 强化了 debug 的可靠性。
  • 强化了 Swift Package Manager 的依赖处理。
  • 强化了 LSPSwiftSyntax 工具链。

还有一些其它方面的优化。

Language Updates

Swift 5.2 实现了如下 proposals

继续阅读“Swift 5.2 发布以及 5.3 规划”

Class-only Protocols – class or AnyObject

iOS 系统中广泛使用了 delegate 模式,如果有 Swift 开发经验的话,你将会发现如下代码无法正常通过编译。

class MyClass {
  weak var delegate: MyDelegate?
}

protocol MyDelegate {
}

报错信息如下:

‘weak’ must not be applied to non-class-bound ‘MyDelegate’; consider adding a protocol conformance that has a class bound

因为使用了 weak 关键字,必须让该 protocol 满足 class 类型。

protocol MyDelegate: class {

}

继续阅读“Class-only Protocols – class or AnyObject”

LeetCode题 – 两数相加

LeetCode:两数相加

题目

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

链接:https://leetcode-cn.com/problems/add-two-numbers

解决方案

继续阅读“LeetCode题 – 两数相加”

介绍 Swift ArgumentParser 库

Apple 最近新开源了一个库,叫 ArgumentParser,它是由 Swift 实现的,用于解析命令行参数(command-line arguments)的。

构建命令行工具

为了演示如何使用 ArgumentParser 库,我们将以一个生成随机数为示例。

> random 20
17
> random 100
89
> random
Error: Missing expected argument '<high-value>'
Usage: random <high-value>

定义了一个 Random 类型,并且需要一个整数类型的参数(highValue),然后会生成一个介于 1 和 highValue 之间的随机数。

源码如下:

import ArgumentParser

struct Random: ParsableCommand {
    @Argument() var highValue: Int

    func run() {
        print(Int.random(in: 1...highValue))
    }
}

Random.main()

实现就是这么简单。

  • @Argument 表明该属性是作为命令行参数(command-line argument)的。
  • 调用 main() 方法,将会开始解析,如果成功将运行命令行工具(command-line tool)。
  • 该库也会提供一些引导性的信息给用户,比如 highValue 属性的名称以及类型等。
  • highValue 被定义成 Int 类型,只有输入合法的值才可以,否则将会报错。

继续阅读“介绍 Swift ArgumentParser 库”

介绍 Standard Library Preview Package

Apple 最近新开源了一个项目,命名为 Standard Library Preview Package,主要是用来加强 Swift Evolution 进程的。该 Preview Package 将包含已被纳入 Swift Standard Library 计划但还没被集成到 Swift 正式版中的功能。这可以使得我们在真实环境中使用这些新特性,并给予及时的反馈,同时也降低了给 Standard Library 贡献代码的技术门槛。

Preview Package 最近接收了 SE-0270 提议,该提议实现了获取一个集合的子集,比如 subranges(where:)moveSubranges(_:to:)

使用 Preview Package

想在 Swift Package Manager 项目中使用 Standard Library Preview Package,只需要编辑 Package.swift 文件即可。

let package = Package(
    name: "MyPackage",
    dependencies: [
       .package(url: "https://github.com/apple/swift-standard-library-preview.git", from: "0.0.1"),
    ],
    targets: [
        .target(
            name: "MyTarget",
            dependencies: [.product(name: "StandardLibraryPreview", package: "swift-standard-library-preview")]),
    ]
)

继续阅读“介绍 Standard Library Preview Package”

介绍 Swift Crypto 库

最近 Apple 官方推出了一个新的 SwiftSwift Crypto 。该库将 Apple 平台的 CryptoKit 库拓展到了其它平台(比如:Linux),这样其它平台上也将可以使用加密相关的 API 了。

使用方法很简单,只需要导入对应库即可:

import Crypto

示例代码

func encrypt(input: [UInt8]) throws -> Data {
    // Don't forget to save your key somewhere!
    let key = SymmetricKey(size: .bits256)
    let sealedBox = try AES.GCM.seal(input, using: key)
    return sealedBox.combined!
}

跨平台

Apple 平台上,Swift Crypto 直接使用已有的 CryptoKit 库,但其它平台上将基于 BoringSSL 库重新实现,最终将在所有平台上提供一套统一且方便使用的 API

继续阅读“介绍 Swift Crypto 库”

Swift 2019 这一年

Swift 2019 回顾

  • Swift 5 & 5.1 发布
  • Swift ABI 稳定
  • SwiftUI 发布
  • Xcode 集成 Swift Package Manager
  • SwiftNIO 2 发布
  • SwiftLog 发布
  • SwiftMetrics 发布
  • StatsdClient 发布
  • swift-numerics 发布
  • Vapor 4 Beta 发布

Swift 2020 展望

  • Swift 5.2
  • Vapor 4 正式版

继续阅读“Swift 2019 这一年”

Swift 文档编写规范

本篇为译文,原文可见:链接

如果超过 6 个月没看过自己写的代码的话,你可能会认为这些代码是其他人写的。

-Eagleson’s Law

当我们使用 Appleclass 时,如果不知道如何使用它们的话,我们有很多方式可以去查找资料。比如你可以通过 Apple Developer Documentation 在线文档或者通过 Xcode 来查找。

Quick help popover

你可以通过 ⌥ – Option + click 方式查看任何 class

Symbol inspector Quick Help

Quick help 也显示在 Quick Help 检查面板(inspector panel)上。

Code completion hint

当你开始打字时,Xcode 将会有相应的提示信息(包含 class 中的 function/property/enum

接下来将介绍如何给自己的代码加上这些提示。

Syntax

给代码写文档就像写注释一样,但是有一点点语法上的差别。你需要 /// 来标注单行的文档。

/// This is your User documentation.
struct User {
    let firstName: String
    let lastName: String
}

对于多行文档,你需要 /** ... */ 符号。

/**
    This is your User documentation.
    A very long one.
*/
struct User {
    let firstName: String
    let lastName: String
}

继续阅读“Swift 文档编写规范”

Swift Weekly 中文 – Issue #176

本篇为译文,原文可见:链接

本周的 issue ,我们主要讨论 updating the view stateanimations in SwiftUIdebugging Combine

文章

如果你正在查找关于 body 是计算型时,去尝试修改 view 状态的资料的话,这篇文章将会告诉你可以做哪些操作以及不应该做哪些操作。

Fernando Moya de Rivas 使用 SwiftUI 创建了几个有趣的动画。

学习不同方式来调试由 Swift Combine framework 编写的 functional reactive code 。通过 print()handleEvents() 来查看 console;通过 breakpointOnError()breakpoint() 来生成 Xcode 断点;以及通过绘制图表的方式。

Josh Adams 通过 SwiftUI 修改了他的一个 app,并分享了一些学习心得。

本篇文章中,Jim Dovey 解释了如何使用 SwiftUICoreData 进行绑定操作。

The folks at Just Eat have experimentation and feature flagging at their heart and they’ve developed a component, named JustTweak, to make things easier on iOS.

John Sundell 找到了一些不同的方式来添加插件支持,这样可以使得系统变得更加灵活。

介绍了如何编写 Swift 代码的文档注释。

介绍了 Alexander Grebenyuk 如何从手动测试他的框架到通过单元测试来自动化测试每一次的变更。

继续阅读“Swift Weekly 中文 – Issue #176”

Swift 之 Property Wrappers 特性

Swift 5.1 新增了 Property Wrappers 特性。该特性可以通过使用 @ 符号以注解的形式来实现某些功能,并达到简化代码的效果。

示例

iOS 中的 UserDefaults 为例,一般用法如下。

  • 存储数据
UserDefaults.standard.set(value, forKey: key)
  • 获取数据
UserDefaults.standard.object(forKey: key)

改造

Property Wrappers 需满足两个基本要求:

  • 必须使用 @propertyWrapper 关键字来修饰。
  • 必须有一个命名为 wrappedValue 的属性。

接下来以 Property Wrappers 方式改造 UserDefaults ,代码如下:

@propertyWrapper
struct MyUserDefault<T> {

    let key: String
    let defaultValue: T

    var wrappedValue: T {
        get {
            return (UserDefaults.standard.object(forKey: key) as? T) ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }

}

使用

@MyUserDefault(key: "username", defaultValue: "")
static var username: String

加了 MyUserDefault 自定义注解后,对 username 的赋值操作相当于是执行了 UserDefaults.standard.set 方法,对 username 的读取操作相当于执行了 UserDefaults.standard.object 方法。

限制

Property Wrappers 也有一些使用上的限制。比如:

  • 无法在 protocol 中进行声明。
  • 通过 wrapper 包装的实例属性(An instance property with a wrapper)无法在 extension 中进行声明。
  • 无法在 enum 中进行声明。
  • class 中通过 wrapper 包装的属性无法被另外一个属性通过 override 覆盖掉。
  • 通过 wrapper 包装的实例属性(An instance property with a wrapper)不能用 lazy@NSCopying@NSManagedweakunowned 来修饰。

继续阅读“Swift 之 Property Wrappers 特性”