摸鱼精选第 27 期

1. Running tasks in parallel

使用 Swift Concurrency 的 Task Group 来代替 GCD 和 OperationQueue,可以做到不依赖 Dispatch 和 Foundation 框架,纯 Swift 原生处理。

func parallelTasks<T>(
    iterations: Int,
    concurrency: Int,
    block: @escaping ((Int) async throws -> T)
) async throws -> [T] {
    try await withThrowingTaskGroup(of: T.self) { group in
        var result: [T] = []

        for i in 0..<iterations {
            if i >= concurrency {
                if let res = try await group.next() {
                    result.append(res)
                }
            }
            group.addTask {
                try await block(i)
            }
        }

        for try await res in group {
            result.append(res)
        }
        return result
    }
}


let workers: Int = 8
let numbers: [Int] = Array(repeating: 1, count: 1_000_000_000)

let res = try await parallelTasks(
    iterations: workers,
    concurrency: 4
) { i in
    print(i)
    let start = i * numbers.count / workers
    let end = (i + 1) * numbers.count / workers
    return numbers[start..<end].reduce(0, +)
}

print("Sum: \(res.reduce(0, +))")

2. ChatGPT 保姆级注册教程(成功注册 ChatGPT,亲测有效)

亲测有效。

3. UI Notes

UI Notes 收集了大量线上优秀 App 的完整 UI 截图,109 个应用 23208 张截图。你可以在这里探索 UI 设计的最新趋势、浏览竞品的产品设计、快速找到工作中需要的灵感。

4. 现代 C++ 教程:高速上手 C++ 11/14/17/20

  1. 本书假定读者已经熟悉了传统 C++ ,至少在阅读传统 C++ 代码上不具备任何困难。换句话说,那些长期使用传统 C++ 进行编码的人、渴望在短时间内迅速了解现代 C++ 特性的人非常适合阅读本书;
  2. 本书一定程度上介绍了一些现代 C++ 的黑魔法,但这些魔法毕竟有限,不适合希望进阶学习现代 C++ 的读者,本书的定位系现代 C++ 的快速上手。当然,希望进阶学习的读者可以使用本书来回顾并检验自己对 现代 C++ 的熟悉度。

Github 地址: modern-cpp-tutorial

5. React JS Best Practices From The New Docs

如果你没有时间阅读新的 React 文档,作者为你提炼了要点。

以下来自 ChatGPT 的回答:

这篇文章主要介绍了 React.js 的最佳实践,这些实践主要来自于 React.js 官方文档的更新。以下是这篇文章的主要要点:

  1. 尽可能使用函数组件:React.js 中的函数组件比类组件更简洁、易于阅读和测试。

  2. 使用 React.memo:使用 React.memo 包装函数组件可以避免不必要的重新渲染。

  3. 使用 Hooks:使用 Hooks 可以更好地管理状态和生命周期。

  4. 使用 PropTypes 进行类型检查:使用 PropTypes 可以避免意外的类型错误,并提高代码的可读性。

  5. 使用 Fragments:使用 Fragments 可以避免在 DOM 中创建多余的节点。

  6. 避免使用 index 作为 key:使用唯一的 key 可以帮助 React 更好地管理和更新组件。

  7. 避免不必要的渲染:在组件中使用 shouldComponentUpdate 或 React.memo 可以避免不必要的重新渲染。

  8. 使用 defaultProps:使用 defaultProps 可以为组件的 props 提供默认值。

  9. 使用 displayName:使用 displayName 可以帮助调试和阅读代码。

  10. 组件命名规范:组件的命名应该遵循 PascalCase 规范,并使用有意义的名字。

这些最佳实践可以帮助开发者编写更具可读性、可维护性和高性能的 React.js 应用程序。

6. How Swift Achieved Dynamic Linking Where Rust Couldn't

一篇 2019 年的老文,主要讲了 Swift 为了 ABI 稳定性所做的一些努力。

以下来自 ChatGPT 的回答:

这篇文章主要讨论了 Swift 的 ABI(应用程序二进制接口)和其在 Swift 应用程序中的重要性。以下是这篇文章的主要要点:

  1. ABI 是什么:ABI 是应用程序二进制接口的缩写,它是一种约定,规定了二进制接口应该如何工作,包括函数调用、参数传递、内存布局等。

  2. Swift ABI 的重要性:Swift ABI 定义了 Swift 应用程序的二进制接口,对于 Swift 应用程序的运行和交互来说至关重要。Swift ABI 的改变可能会影响到不同版本的 Swift 应用程序之间> 的兼容性。

  3. Swift ABI 的历史:Swift ABI 在 Swift 1.0 中并没有被实现,这导致了许多兼容性问题。在 Swift 3.0 中,Swift ABI 被引入,并且在之后的版本中不断改进和完善。

  4. Swift ABI 的组成:Swift ABI 由多个部分组成,包括函数调用约定、类型元数据、泛型和标准库等。

  5. Swift ABI 的变化:Swift ABI 的变化可能会影响到不同版本的 Swift 应用程序之间的兼容性。Swift ABI 的改变通常会伴随着 Swift 版本的更新,开发者需要注意并进行适当的升级和测> 试。

  6. Swift ABI 的未来:Swift ABI 的改进仍在进行中,未来的版本可能会引入更多的特性和改进,以提高 Swift 应用程序的性能和兼容性。

了解 Swift ABI 对于开发者来说非常重要,可以帮助他们更好地编写和维护 Swift 应用程序,并且避免由于 ABI 变化而导致的兼容性问题。

9. iOS 使用 agvtool 管理项目版本号

agvtool 是 Apple Generic Version Tool,用于版本管理的工具。 主要用法如下:

# 查看当前的版本号(CFBundleShortVersionString)
xcrun agvtool what-marketing-version

# 设置版本号(CFBundleShortVersionString) 位 2.0
xcrun agvtool new-marketing-version 2.0

# 查看当前项目的 Build
xcrun agvtool what-version

# 设置 Build 自动加 1
xcrun agvtool next-version -all

# 设置 Build 为 100
xcrun agvtool next-version -all 100

10. 夸克 iOS Top1 JSC 崩溃攻克之旅

Top Crash 的排查一直是 iOS 开发中的一个难点,尤其是内存相关的问题,往往会崩溃到系统符号里,排查起来经常一头雾水。这篇文章是夸克团队在排查 JSC 崩溃的实践,涵盖了 Crash 分析的整体思路、工具建设和崩溃原理,文章质量较高,推荐阅读。

11. The evolution of Facebook’s iOS app architecture

Facebook for iOS (FBIOS) 是 Meta 最古老的移动代码库。自 2012 年该应用程序被重写以来,它已经由数千名工程师共同开发并交付给数十亿用户,它可以支持数百名工程师同时对其进行迭代。经过多年的迭代,Facebook 代码库已经不像典型的 iOS 代码库了,本文将阐明演变背后的技术决策及其历史背景:

  • 2014,建立自己的移动框架:React
  • 2015,减轻和改进启动所需的更改
  • 2016,动态库和模块化
  • 2017,重新思考 FBIOS 架构
  • 2018,生成代码的激增
  • 2020,Swift 和语言架构
  • 2022,架构演变完成了 1%,未来仍将继续

12. Flutter 3.7 之快速理解 toImageSync 是什么?能做什么?

作者从 toImageSync 方法入手,详细的描述了 toImageSync 性能上带来的优势与副作用。 toImageSync 优势是生成的图像会在 GPU 中常驻,所以它的绘制速度会更快,并且可以重复利用,提高效率。并且 toImageSync 为同步方法,在方法调用上更加自由。作者更是通过对 Flutter 中 SnapshotWidget 的调用方式来详细分析 toImageSync 与标准动画的差别,并通过对比明显展示了 toImageSync 的副作用:“冻结” child 控件。

最后作者更是通过源码对比以及各版本之间的命名差异分析 toImageSync 的设计初衷与作用,这种对源码分析的严谨与执着更是值得开发者的学习。

13. 云音乐 iOS 跨端缓存库 - NEMichelinCache

网易云音乐客户端集成了 React Native 了,为了兼容原生、H5、RN 三端的缓存读写,重新设计了缓存库 NEMichelinCache。

14. Building a QR Code Scanner App in SwiftUI

在 SwiftUI 里面创建二维码扫描,其实核心还是先创建一个 View Controller,然后再通过 UIViewControllerRepresentable 来套一层。