• 在 SwiftUI 中创建自适应的程序化导航方案

    随着苹果对 iPadOS 的不断投入,越来越多的开发者都希望自己的应用能够在 iPad 中有更好的表现。尤其当用户开启了台前调度( Stage Manager )功能后,应用对不同视觉大小模式的兼容能力就越发显得重要。本文将就如何创建可自适应不同尺寸模式的程序化导航方案这一内容进行探讨。

  • 在多包项目中统一管理资源

    随着 SPM( Swift Package Manager ) 功能的不断完善,越来越多的开发者开始在他的项目中通过创建多个 Package 的方式来分离功能、管理代码。SPM 本身提供了对包中各类资源( 包括本地化资源 )的管理能力,但主要局限于在本包中使用这些资源,难以将资源进行共享。在有多个 Target 均需调用同一资源的情况下,原有的方式很难应对。本文将介绍一种在拥有多个 SPM 包的项目中,对资源进行统一管理的方法。

  • 聊一聊可组装框架( TCA )

    本文将聊聊一个与创建复杂的 SwiftUI 应用很契合的框架 —— The Composable Architecture( 可组装框架,简称 TCA )。包括它的特点和优势、最新的进展、使用中的注意事项以及学习路径等问题。

  • StateObject 与 ObservedObject

    StateObject 是在 SwiftUI 2.0 中才添加的属性包装器,它的出现解决了在某些情况下使用 ObservedObject 视图会出现超预期的问题。本文将介绍两者间的异同,原理以及注意事项。

  • iBug 16 有感

    到 2022 年,SwiftUI 已经迈入了第四个年头。尽管在之前的版本更新过程中,SwiftUI 也出现了或多或少的问题,但从来也没有像 SwiftUI 4 这么严重。Bug 众多的现象不仅仅表现在 SwiftUI 上,在 iOS、macOS 以及苹果很多其他的产品上都有所体现。

  • 一些适合 SwiftUI 初学者的教程

    经常有朋友咨询,学习 SwiftUI 的最佳路径是什么?考虑到每个人的技术背景、学习能力、工作经验均不一样,因此很难说哪种学习方式或哪些资料是适合他本人的。不过随着这个问题被反复提起,最终还是想尝试整理一些资料给对 SwiftUI 感兴趣的朋友。本文将介绍一些对学习者技术基础要求较低( 甚至可以零基础 )的教程。

  • 如何判断 ScrollView、List 是否正在滚动中

    判断一个可滚动控件( ScrollView、List )是否处于滚动状态在某些场景下具有重要的作用。比如在 SwipeCell 中,需要在可滚动组件开始滚动时,自动关闭已经打开的侧滑菜单。遗憾的是,SwiftUI 并没有提供这方面的 API 。本文将介绍几种在 SwiftUI 中获取当前滚动状态的方法,每种方法都有各自的优势和局限性。

  • 在 SwiftUI 中实现视图居中的若干种方法

    将某个视图在父视图中居中显示是一个常见的需求,即使对于 SwiftUI 的初学者来说这也并非难事。在 SwiftUI 中,有很多手段可以达成此目的。本文将介绍其中的一些方法,并对每种方法背后的实现原理、适用场景以及注意事项做以说明。

  • 在 Text 中实现基于关键字的搜索和定位

    前些日子,一位网友在聊天室中就如何通过 Text + AttributedString 实现类似文章关键字检索的功能,并可通过按钮在搜索结果中进行滚动切换的问题与大家进行了交流与探讨。考虑到这个问题对于 SwiftUI 的应用来说比较新颖,且涉及不少博客中介绍过的知识,因此我对聊天室原本给出的解决方案进行了重新整理,并通过本文对解决思路、方法手段以及注意事项等内容与大家进行探讨。

  • 在 SwiftUI 中用 Text 实现图文混排

    SwiftUI 提供了强大的布局能力,不过这些布局操作都是在视图之间进行的。当我们想在 Text 中进行图文混排时,需要采用与视图布局不同的思路与操作方式。本文将首先介绍一些与 Text 有关的知识,并通过一个实际案例,为大家梳理出在 SwiftUI 中用 Text 实现图文混排的思路。

  • 掌握 SwiftUI 的 task 修饰器

    随着 Swift 5.5 引入了 async/await 特性,苹果也为 SwiftUI 添加了 task 视图修饰器,以方便开发者在视图中使用基于 async/await 的异步代码。本文将对 task 视图修饰器的特点、用法、注意事项等内容做以介绍,并提供了将其移植到老版本 SwiftUI 的方法。

  • 避免 SwiftUI 视图的重复计算

    随着近年来有关 SwiftUI 的文章与书籍越来越多,开发者应该都已经清楚地掌握了 —— “视图是状态的函数” 这一 SwiftUI 的基本概念。每个视图都有与其对应的状态,当状态变化时,SwiftUI 都将重新计算与其对应视图的 body 值。如果视图响应了不该响应的状态,或者视图的状态中包含了不该包含的成员,都可能造成 SwiftUI 对该视图进行不必要的更新( 重复计算 ),当类似情况集中出现,将直接影响应用的交互响应,并产生卡顿的状况。通常我们会将这种多余的计算行为称之为过度计算或重复计算。本文将介绍如何减少( 甚至避免 )类似的情况发生,从而改善 SwiftUI 应用的整体表现。

  • SwiftUI 布局 —— 尺寸( 下 )

    在上篇中,我们对 SwiftUI 布局过程中涉及的众多尺寸概念进行了说明。本篇中,我们将通过对视图修饰器 frame 和 offset 的仿制进一步加深对 SwiftUI 布局机制的理解,并通过一些示例展示在布局时需要注意的问题。

  • SwiftUI 布局 —— 尺寸( 上 )

    在 SwiftUI 中,尺寸这一布局中极为重要的概念,似乎变得有些神秘。无论是设置尺寸还是获取尺寸都不是那么地符合直觉。本文将从布局的角度入手,为你揭开盖在 SwiftUI 尺寸概念上面纱,了解并掌握 SwiftUI 中众多尺寸的含义与用法;并通过创建符合 Layout 协议的 frame 和 fixedSize 视图修饰器的复制品,让你对 SwiftUI 的布局机制有更加深入地理解。

  • SwiftUI 布局 —— 对齐

    “对齐”是 SwiftUI 中极为重要的概念,然而相当多的开发者并不能很好地驾驭这个布局利器。在 WWDC 2022 中,苹果为 SwiftUI 增添了 Layout 协议,让我们有了更多的机会了解和验证 SwiftUI 的布局原理。本文将结合 Layout 协议的内容对 SwiftUI 的 “对齐” 进行梳理,希望能让读者对“对齐”有更加清晰地认识和掌握。

  • 用 Table 在 SwiftUI 下创建表格

    Table 是 SwiftUI 3.0 中为 macOS 平台提供的表格控件,开发者通过它可以快捷地创建可交互的多列表格。在 WWDC 2022 中,Table 被拓展到 iPadOS 平台,让其拥有了更大的施展空间。本文将介绍 Table 的用法、分析 Table 的特点以及如何在其他的平台上实现类似的功能。

  • SwiftUI 4.0 的全新导航系统

    长久以来,开发者对 SwiftUI 的导航系统颇有微词。受 NavigationView 的能力限制,开发者需要动用各种技巧乃至黑科技才能实现一些本应具备基本功能(例如:返回根视图、向堆栈添加任意视图、返回任意层级视图 、Deep Link 跳转等 )。SwiftUI 4.0( iOS 16+ 、macOS 13+ )对导航系统作出了重大改变,提供了以视图堆栈为管理对象的新 API ,让开发者可以轻松实现编程式导航。本文将对新的导航系统作以介绍。

  • 为自定义属性包装类型添加类 @Published 的能力

    本文将对 @Published 与符合 ObservableObject 协议的类实例之间的沟通机制做以介绍,并通过三个示例:@MyPublished( @Published 的仿制版本 )、@PublishedObject(包装值为引用类型的 @Published 版本)、@CloudStorage(类似 @AppStorage ,但适用于 NSUbiquitousKeyValueStore ),来展示如何为其他的自定义属性包装类型添加可访问包裹其的类实例的属性或方法的能力。

  • SwiftUI 的动画机制

    大多初学者都会在第一时间惊叹于 SwiftUI 轻松实现各种动画效果的能力,但经过一段时间的使用后,他们会发现 SwiftUI 的动画并非像表面上看起来那样容易驾驭。开发者经常需要面对:如何动、怎么动、什么能动、为什么不动、为什么这么动、如何不让它动等等困扰。对 SwiftUI 的动画处理逻辑了解的不够深入是造成上述困扰的主要原因。本文将尝试对 SwiftUI 的动画机制做以介绍,以帮助大家更好地学习、掌握 SwiftUI 的动画,制作出满意的交互效果。

  • 优化在 SwiftUI List 中显示大数据集的响应效率

    拥有优秀的交互效果和手感,是很多 iOS 开发者长久以来坚守的原则。同样一段代码,在不同数据量级下的响应表现可能会有云泥之别。本文将通过一个优化列表视图的案例,展现在 SwiftUI 中查找问题、解决问题的思路,其中也会对 SwiftUI 视图的显式标识、@FetchRequest 的动态设置、List 的运作机制等内容有所涉及。本文的范例需运行在 iOS 15 及以上系统,技术特性也以 SwiftUI 3.0 为基础。

  • 在 SwiftUI 中用 zIndex 调整视图显示顺序

    本文将对 SwiftUI 的 zIndex 修饰符做以介绍,包括:使用方法、zIndex 的作用域、通过 zIndex 避免动画异常、为什么 zIndex 需要设置稳定的值以及在多种布局容器内使用 zIndex 等内容。

  • ViewBuilder 研究(下) —— 从模仿中学习

    在【ViewBuilder 研究(上)—— 掌握 Result builders】中,我们对 result builders 做了较详细的介绍。本篇我们将通过对 ViewBuilder 的仿制,探索更多有关 SwiftUI 视图背后的秘密。

  • ViewBuilder 研究(上)—— 掌握 Result builders

    作为一个严重依赖 SwiftUI 的开发者,同视图打交道是最平常不过的事情了。从第一次接触 SwiftUI 的声明式编程方式开始,我便喜欢上了这种写代码的感觉。但接触地越多,碰到的问题也越多。起初,我单纯地将很多问题称之为灵异现象,认为大概率是由于 SwiftUI 的不成熟导致的。随着不断地学习和探索,发现其中有相当部分的问题还是因为自己的认知不够所导致的,完全可以改善或避免。我将通过上下两篇博文,对构建 SwiftUI 视图的 ViewBuilder 进行探讨。本篇将首先介绍 ViewBuilder 背后的实现者 —— result builders 。

  • SwiftUI Overlay Container 2 —— 可定制、高效、便捷的视图管理器

    SwiftUI Overlay Container 是一个用于 SwiftUI 的视图容器组件。一个可定制、高效、便捷的视图管理器。仅需简单配置,SwiftUI Overlay Container 即可帮你完成从视图组织、队列处理、转场、动画、交互到显示样式配置等基础工作,让开发者可以将精力更多地投入到应用程序视图的实现本身。

  • 在 SwiftUI 下定制手势

    不同于众多的内置控件,SwiftUI 没有采用对 UIGestureRecognizer(或 NSGestureRecognizer)进行包装的形式,而是重构了自己的手势体系。SwiftUI 手势在某种程度上降低了使用门槛,但由于缺乏提供底层数据的 API,严重制约了开发者的深度定制能力。在 SwiftUI 下,我们无法拥有类似构建全新 UIGestureRecongnizer 的能力。所谓的自定义手势,其实只是对系统预置手势的重构而已。本文将通过几个示例,演示如何使用 SwiftUI 提供的原生手段定制所需手势。

  • Swift Playgrounds 4 娱乐还是生产力

    赶在 2021 年底,苹果终于发布了 Swift Playgrounds 4,作为近年来最具革命性意义的版本,Swift Playgrounds 4 提供了在 iPad 上开发可发行 app 的能力。本文将对 Swift Playground 4 的新功能做以介绍,并探讨将其作为开发工具的可行性。

  • SwiftUI 视图的生命周期研究

    本文将作者对 SwiftUI 视图、SwiftUI 视图生命周期的理解和研究做以介绍,供大家一起探讨。在 UIKit(AppKit)的世界中,通过框架提供的大量钩子(例如 viewDidLoad、viewWillLayoutSubviews 等),开发者可以将自己的意志注入视图控制器生命周期的各个节点之中,宛如神明。在 SwiftUI 中,系统收回了上述的权利,开发者基本丧失了对视图生命周期的掌控。不少 SwiftUI 开发者都碰到过视图生命周期的行为超出预期的状况(例如视图多次构造、onAppear 无从控制等)。

  • 掌握 SwiftUI 的 Safe Area

    Safe Area(安全区域)是指不与导航栏、标签栏、工具栏或其他视图控制器提供的视图重叠的内容空间。本文将探讨如何在 SwiftUI 中获取 SafeAreaInsets、将视图绘制到安全区域之外、修改视图的安全区域等内容。

  • 了解 SwiftUI 的 onChange

    从 iOS 14 开始,SwiftUI 为视图提供了 onChange 修饰器,通过使用 onChange,我们可以在视图中对特定的值进行观察,并在其更改时触发操作。本文将对 onChange 的特点、用法、注意事项以及替代方案做以介绍。

  • SwiftUI TextField 进阶——格式与校验

    SwiftUI 的 TextField 可能是开发者在应用程序中最常使用的文本录入组件了。作为 UITextField(NSTextField)的 SwiftUI 封装,苹果为开发者提供了众多的构造方法和修饰符以提高其使用的便利性、定制性。但 SwiftUI 在封装中也屏蔽了不少的高级接口和功能,增加了开发者实现某些特定需要的复杂性。本文为【SwiftUI 进阶】系列文章中的一篇,在本文中,我将介绍如何在 TextField 中实现如下功能:屏蔽无效字符、判断录入的内容是否满足特定条件、对录入的文本实时格式化显示。

  • AttributedString——不仅仅让文字更漂亮

    在 WWDC 2021 上,苹果为开发者带来了有一个期待已久的功能——AttributedString,这意味着 Swift 开发人员不再需要使用基于 Objective-C 的 NSAttributedString 来创建样式化文本。本文将对其做全面的介绍并演示如何创建自定义属性。

  • 用 NavigationViewKit 增强 SwiftUI 的导航视图

    由于 SwiftUI 原生提供的导航手段能力有限,因此在之前的版本中,NavigationView 总是使用的不是那么的顺手。本文介绍一个我写的针对 NavigationView 的扩展库——NavigationViewKit。为原生 NavigationView 解决几个当前的痛点问题。

  • 在 SwiftUI 中使用 UIKit 视图

    本文将通过对 UITextField 的包装来讲解如何在 SwiftUI 中使用 UIKit 视图、如何让你的 UIKit 包装视图具有 SwiftUI 风格、在 SwiftUI 使用 UIKit 视图需要注意的地方

  • @AppStorage 研究

    本文探讨的是如何优雅、高效、安全地在 SwiftUI 中使用@AppStorage,在不借助第三方库的情况下,解决当前@AppStorage 使用中出现的痛点

  • 在 SwiftUI 下对 iPad 进行适配

    SwiftUI 创建初衷之一便是可以高效、可靠的适配多个苹果的硬件平台。在健康笔记 2.0 开发初始,适配 iPad 便是我本次的设计目标之一。本文并非教程,只是我在进行本次开发中,对于适配 iPad 的一些教训和心得。

  • 健康笔记 2.0 开发随笔(六)

    一晃国庆中秋长假即将结束,距离上次的随笔也有了一段时间。在最近的日子里,我一方面继续着开发的进程,同时还要付出相当的精力同 iOS14 中的各种 Bug 和异常斗智斗勇。本篇随笔主要记录了这段时间碰到的一些问题,以及聊聊 iOS14、Xcode12 以及 SwiftUI2.0 的一些优缺点。想到哪、写到哪,可能逻辑会比较混乱。

  • 健康笔记 2.0 开发随笔(五)

    一晃国庆中秋长假即将结束,距离上次的随笔也有了一段时间。在最近的日子里,我一方面继续着开发的进程,同时还要付出相当的精力同 iOS14 中的各种 Bug 和异常斗智斗勇。本篇随笔主要记录了这段时间碰到的一些问题,以及聊聊 iOS14、Xcode12 以及 SwiftUI2.0 的一些优缺点。想到哪、写到哪,可能逻辑会比较混乱。

  • 健康笔记 2.0 开发随笔(四)

    本周没有太多的精力和情绪用来写代码。这两天在原来统一 sheet 管理和实时 Form 的基础上,完成了可以控制取消手势的 Sheet。这个是 SwiftUI 中一直以来的一个重要的缺失功能。 在 SwiftUI 中制作可以控制取消手势的 Sheet

  • 在 SwiftUI 中制作可以控制取消手势的 Sheet

    在前面的两篇文章中,我们探讨了如何制作一个可以判断是否进行了修改的表单,以及如何统一管理 app 各个层级 View 的弹出 Sheet。今天我们将他们合并在一起,完成整个项目的最终目的——在 Sheet 中制作一个可以实时响应的表单,并且 sheet 会感觉表单的情况响应取消手势。

  • 如何在 SwiftUI 中创建一个实时响应的 Form

    我的 app 健康笔记主要是对数据的收集、管理,所以对于表单的实时检查、响应的要求比较高。因此制作一个对用于输入响应及时、反馈准确的 Form 十分重要。本文尝试提出一个 SwiftUI 下的 Form 开发思路。

  • 在 SwiftUI 中,根据需求弹出不同的 Sheet

    Sheet 是一个我比较喜欢的交互形式,它可以很好的控制用户的操作行为,让用户的交互逻辑单线条化。在 iOS14 上,SwiftUI 增加了 fullCover,支持了全屏的 Sheet 方式,让开发者又了更多的选择。

  • 健康笔记 2.0 开发随笔(一)

    健康笔记从 2020 年 1 月上线以来,至今已经过了大半年的时间(可以从 [老人新兵 —— 一款 iOS app 的开发手记](https://zhuanlan.zhihu.com/p/103822455) 了解健康笔记 app 的由来)。在这段时间里,我对于 Swift、SwiftUI、CoreData 等都有了进一步的了解和认识。在开发 1.0 版本时所面对的问题和疑惑多数都得到了解决。

  • 用 SwiftUI 实现 iOS mail 程序的侧滑菜单

    随着 SwiftUI2.0 的不断完善,我觉得是时候将我的 app 做一个较大的升级了。之前一直想在 app 中实现类似 iOS 邮件程序那样优雅的侧滑菜单效果,在网上也找了一下,实现的较好的是适用于 UIKit 的,基本上没有能够很好的适配 SwiftUI 的项目库。最终自己在 Xcode12 实现了一个。

  • HowTo —— SwiftUI2.0 使用 ProgressView 显示进度条

    SwiftUI2.0 新增了一些便捷的内置控件,比如说 Label、ProgressView 等。其基本形态都很普通,不过都支持自定义 style。官方的意图也比较明显,通过内置控件,规范代码、提高原型编写速度,如需要更精细控制可通过扩展 style 来完成。

  • HowTo —— 使用 onOpenURL 处理 Universal Links

    SwiftUI2.0 由于可以采用新的代码架构(Life Cycle SwiftUI App)来组织 app, 因此提供了 onOpenURL 来处理 Univeresal Links。不同于在 AppDelegate 或 SceneDelegate 中的解决方案,onOpenURL 作为一个 view modifier,你可以在任意 View 上注册你的 app 的 URL 处理机制。

  • HowTo —— SwiftUI2.0 使用 ToolBar 替代 navigationbarItems

    SwiftUI2.0 为了实现更好的多平台支持同时需要兼顾 1.0 版本代码兼容性,提供了一些与已有控件功能上类似但名称和用法全新的控件。比如 ToolBar, navigationTitle 等。Toolbar 可以实现 navigationbarItems 的全部功能,并新增了在多平台下的适配。采用了全新的语法,代码更易阅读。

  • HowTO —— SwiftUI2.0 原生的 Grid

    SwiftUI 的第一版中,官方并没有提供 UICollectionView 的对应功能。开发者需要自行包装或者依赖很多第三方库。SwiftUI2.0 中,苹果通过 LazyVGrid、LazyHGrid 提供了 Grid 控件。该控件的实现很有 SwiftUI 的风格,和众多的第三方库有显著的区别。

  • SwiftUI2.0 —— App、Scene、新的代码结构(一)

    本文简单介绍了 SwiftUI2.0 中全新提供的 App 协议、Scene 协议,浅谈了在全新的代码结构下如何组织 Data Flow,并提供了 SwiftUI2.0 中预置的 Scene 的一些使用示例。当前运行环境为 Xcode Version 12.0 beta (12A6159), macOS Big Sur 11.0 Beta 版 (20A4299v)。

  • @FocusedBinding 浅谈

    在苹果 WWDC20 中视频中出现了下面的代码,介绍了一个新的属性包装器@FocusedBinding。由于仍处于测试阶段,当前的代码并不能被正确的执行。@FocusedBinding 的资料苹果披露的也很少,网上也没有相关的信息。出于个人兴趣,我对它进行了简单的研究。尽管@FocusedBinding 在目前 Xcode Version 12.0 beta 2 (12A6163b) 的版本上运行还有很多问题,但我基本上对其有了一定的了解。

  • SwiftUI2.0 —— Commands(macOS 菜单)

    本文介绍了 SwiftUI 2.0 中,如何为 macOS 平台添加菜单。苹果在 SwiftUI2.0 中增加了 Multiplatform 项目模板,使得同一套代码,仅需少量的适配便可以同时满足 iOS 以及 macOS 的需要。对于 macOS 上运行的 app, 拥有自定义的菜单是一个十分重要的平台特征。对于没有 macOS 开发经验的我来说,学习如何设计开发菜单变得十分有趣且必要。

  • SwiftUI 2.0 —— @StateObject 研究

    WWDC20 刚刚结束,在过去的一周,苹果为开发者带来了巨大的惊喜。由于新特性实在太多,需要不少时间来消化,我首先选择自己最感兴趣的内容进行一些简单的研究和探讨。本文首先浅谈一下 SwiftUI 新提供的属性包装器@StateObject。

  • @state 研究

    本文试图探讨并分析 SwiftUI 中 @State 的实现方式和运行特征;最后提供了一个有关扩展@State 功能的思路及例程。读者需要对 SwiftUI 的响应式编程有基本概念。

  • ObservableObject 研究——想说爱你不容易

    本文主要研究在 SwiftUI 中,采用单一数据源 (Single Source of Truth) 的开发模式,ObservableObject 是否为最佳选择。是否可以在几乎不改变现有设计思路下进行新的尝试,以提高响应效率。最后提供了一个仍采用单一数据源设计思路但完全弃用 ObservableObject 的方式。