DevOrz
type: channel
link: https://www.devorz.com/
description: 张建宇的技术博客
items: Flutter 渲染机制详解
items: Flutter 学习推荐资料
items: Flutter State 的生命周期
items: Dart中的类修饰符
items: Xcode Build 配置文件
items: 下载 App Store 上的 IPA 文件到 Mac
items: [译]A successful Git branching model
items: [译]What’s New in Swift5?
items: [译]What's New in Swift4?

Flutter 渲染机制详解
type: item
date: 2025-10-22T00:10:00+08:00

Flutter 学习推荐资料
type: item
date: 2025-07-01T00:23:00+08:00
description: Roadmap.sh Flutter 学习路线图 - 这个交互式路线图将 Flutter 学习内容结构化展示，你可以点击每个技能点查看详细说明，是规划学习进度和查漏补缺的绝佳工具。Flutter 官方文档 - 学习 Flutter 的第一手资料！文档结构清晰，从入门教程到深度指南应有尽有，配有丰富的代码示例和交互式演示。Flutter 中文文档 - 官方文档的中文翻译版。Flutter 官方文档（英文原版）+ 翻译辅助工具 - 社区维护的中文文档会略微落后于官方文档，个人更推荐直接阅读英文官方文档，配合浏览器双语翻译插件，可以对照学习，逐步适应英文技术文档。B站 王叔不秃系列教程 - 用爱发电宝藏 UP，视频由浅入深通俗易懂，5🌟推荐。掘金张风捷特烈 Flutter系列课程 - 3块钱买不了吃亏买不了上当。B站 whoitao Dart 进阶 - 多线程、Stream 进阶资料，PPT 制作精良，力推。CODE WITH ANDREA - Flutter GDE 的专业技术博客，文章质量高、更新及时，是学习 Flutter 最佳实践和高级技巧的优质英文资源。Effective Dartvandadnp / flutter-tips-and-tricksbizz84 / flutter-tips-and-tricks

Flutter State 的生命周期
type: item
date: 2025-03-11T00:28:05+08:00
description: Flutter 中 State 的生命周期是理解 StatefulWidget 工作原理的关键。以下是 Flutter 中 State 对象的完整生命周期：createState()当框架被要求构建 StatefulWidget 时首先调用必须被覆盖并返回 State 类的实例initState()在 State 对象插入视图树时调用仅被调用一次这里适合进行一次性初始化，如控制器初始化、监听器注册等必须调用 super.initState()didChangeDependencies()在 initState() 之后立即调用当 State 对象的依赖项更改时会再次调用例如，当使用 InheritedWidget (如 Theme 或 MediaQuery) 时，此方法会被调用build()必须实现的方法描述如何构建组件的 UI可能被频繁调用，所以应该是轻量级的每当 widget 需要重新渲染时会调用didUpdateWidget(covariant oldWidget)当父 widget 重建并提供新 widget 时调用widget 的配置发生变化时使用旧的 widget 作为参数传入setState()通知框架 State 对象的内部状态已更改触发 build() 方法重新调用不是生命周期方法，但用于管理状态变化deactivate()当 State 从视图树中移除时调用如果稍后将其重新插入，可能还会再次激活在从一个位置移动到另一个位置的情况下使用dispose()当 State 对象永久从视图树中移除时调用用于清理资源，如取消订阅、销毁控制器等必须调用 super.dispose()这些方法构成了 Flutter 中 State 的完整生命周期。正确理解和使用这些生命周期方法对于创建高效、无内存泄漏的 Flutter 应用非常重要。

Dart中的类修饰符
type: item
date: 2024-03-27T23:50:00+08:00
description: 类修饰符可以用在 class 关键词前面，例如 abstract class 用于定义一个抽象类。类修饰符种类：abstractbasefinalinterfacesealedmixin除 abstract 外，其他修饰符均需要 dart version => 3.0 。仅有 base 可以出现在 mixin 前面。修饰符不能其他诸如 enum, typedef, extension 或 extension type 的声明中使用。无修饰符对于无修饰符的 class ,允许不受限制地从任何库构造或子类型. 允许以下操作：实例化;扩展一个子类;实现一个类或者一个mixin;mixin 一个 mixin 或者 mixin class.abstract对于不需要完整实现的,只需要定义接口的场景使用 abstract，abstract class 不允许实例化.// 声明一个 abstract class abstract class Vehicle { void moveForward(int meters); } import 'a.dart'; // 错误: abstract class 不允许实例化 Vehicle myVehicle = Vehicle(); // ✅被扩展 class Car extends Vehicle { int passengers = 4; // ··· } // ✅被实现 class MockVehicle implements Vehicle { @override void moveForward(int meters) { // ... } }base允许继承，不允许实现。// 声明一个 base class base class Vehicle { void moveForward(int meters) { // ... } } import 'a.dart'; // ✅允许实例化 Vehicle myVehicle = Vehicle(); // ✅允许扩展 base class Car extends Vehicle { int passengers = 4; // ... } // ❌不允许实现 base class MockVehicle implements Vehicle { @override void moveForward() { // ... } } interface可以被实现，但是不允许扩展。interface class Vehicle { void moveForward(int meters) { // ... } } import 'a.dart'; // ✅允许实例化 Vehicle myVehicle = Vehicle(); // ❌不允许继承 class Car extends Vehicle { int passengers = 4; // ... } // ✅允许被实现 class MockVehicle implements Vehicle { @override void moveForward(int meters) { // ... } } abstract 和 interface 可以组合使用，abstract interface class。final关闭类的结构层次，禁止被扩展和实现。final class Vehicle { void moveForward(int meters) { // ... } } // ✅允许实例化 Vehicle myVehicle = Vehicle(); // ❌不允许被扩展 class Car extends Vehicle { int passengers = 4; // ... } // ❌不允许被实现 class MockVehicle implements Vehicle { // ERROR: Can't be implemented. @override void moveForward(int meters) { // ... } }sealed用于创建一个可以被穷举的子类合集。声明一个 sealed class sealed class Vehicle {} class Car extends Vehicle {} class Truck implements Vehicle {} class Bicycle extends Vehicle {} // ❌不允许实例化 Vehicle myVehicle = Vehicle(); // ✅子类允许实例化 Vehicle myCar = Car(); String getVehicleSound(Vehicle vehicle)…

Xcode Build 配置文件
type: item
date: 2021-03-08T22:09:00+08:00
description: 原文：Xcode Build Configuration Files软件开发最佳实践 规定了 配置与代码的严格分离。然而，Apple 平台上的开发人员通常很难将这些准则与 Xcode 的项目繁琐的工作流程相结合。了解每个项目设置的功能以及它们之间如何交互，是一项需要多年磨练的技能。然而很多信息都被深藏在Xcode的GUI中，事实上这对我们没有帮助。导航到项目编辑器的 “Build Settings” tab，你会看到分布在 project、target 和 configuration 上的 数百条 Build Setting —— 更不用说其他六个 tab 了!幸运的是，有一个更好的办法，不必点击迷宫般的 tab 和箭头，就可以管理所有的配置。本周，我们将向您展示如何使用基于文本的 xcconfig文件 从 Xcode 外部化构建设置，以使您的项目更加紧凑，易懂且功能强大。请访问XcodeBuildSettings.com以获取最新版本的Xcode支持的每个构建设置的完整参考。Xcode Build 配置文件 他们的 xcconfig 文件扩展名更加众所周知。允许在不使用 Xcode 的情况下声明和管理应用程序的构建设置。它们是纯文本格式，这意味着它们对代码管理系统更加友好，并且可以使用任何编辑器进行修改。从根本上讲，每个配置文件都由一系列键值分配组成，这些键值分配具有以下语法：BUILD_SETTING_NAME = value例如，你可以使用下面这样的 SWIFT_VERSION Build Setting，指定项目的 Swift 语言版本：SWIFT_VERSION = 5.0根据posix 标准，环境变量的名称仅由大写字母，数字和下划线（_）组成，这是一个惯例，我喜欢称之为SCREAMING_SNAKE_CASE ??.乍一看，xcconfig 文件与.env 文件具有惊人的相似之处，它们具有简单的换行符分隔的语法。但是，Xcode构建配置文件不仅仅让人眼前一亮。看哪！保留现有值要附加而不是替换现有定义，请使用$(inherited)变量，如下所示：BUILD_SETTING_NAME = $(inherited) additional value通常，您这样做是为了建立值列表，例如编译器在其中搜索框架以查找包含的头文件（FRAMEWORK_SEARCH_PATHS）的路径：FRAMEWORK_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)Xcode按以下顺序分配继承的值（从最低优先级到最高优先级）：Platform Defaults(平台默认值)Xcode Project File Build Settings(Xcode 项目文件的 Build Setting)xcconfig File for the Xcode Project(Xcode 项目的 xcconfig 文件)Active Target Build Settings(Active Target 的 Build Setting)xcconfig File for the Active Target(Active Target 的 xcconfig 文件)空格用于分隔字符串和路径列表中的项。指定包含空格的项时，必须用引号(")括起来。引用其他值你可以按照下面的语法，通过其他设置的名字引用它们的值：BUILD_SETTING_NAME = $(ANOTHER_BUILD_SETTING_NAME)这种引用既可以用于根据现有值定义新变量，也可以用于以内联方式动态构建新值。OBJROOT = $(SYMROOT) CONFIGURATION_BUILD_DIR = $(BUILD_DIR)/$(CONFIGURATION)-$(PLATFORM_NAME)设置参考的构建设置的默认值在Xcode 11.4和更高版本中，可以使用默认的评估运算符来指定回退值，如果引用的构建设置的评估结果为空，则使用该替代值。$(BUILD_SETTING_NAME:default=value)条件编译设置您可以根据以下语法根据其SDK（sdk），architecture（arch）和/或configuration（config）来对 Build Setting 进行条件约束：BUILD_SETTING_NAME[sdk=sdk] = value for specified sdk BUILD_SETTING_NAME[arch=architecture] = value for specified architecture BUILD_SETTING_NAME[config=configuration] = value for specifie…

下载 App Store 上的 IPA 文件到 Mac
type: item
date: 2020-05-23T16:19:00+08:00
description: 前言苹果已经从iTunes的12.7版本中删除了App Store，这使得从App Store下载IPA变得更加困难。但是，现在可以通过使用Apple Configurator 2来实现。Apple Configurator 2选中设备，点击 Add -> Apps如果设备上之前没有当前添加的 App，会直接安装。如果该 App 已经再设备上存在，会询问是否覆盖，此时不要做选择。打开 使用 iTerm 或者 PopClip打开进去如下路径：~/Library/Group Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps/应该看到带有随机生成的ID的目录，深入到该目录应该就能找到IPA文件了。

[译]A successful Git branching model
type: item
date: 2019-04-18T20:46:00+08:00
description: 原文: A successful Git branching modelWhy git?有关Git与集中式源代码控制系统相比的利弊的详细讨论，请参阅网站。那里战火纷飞。作为开发人员，我喜欢Git超过所有的其他工具。 Git 真的改变了开发人员对合并和分支的看法。在 古老的的 CVS / Subversion 世界里，合并/分支一直被认为有点可怕（“小心合并冲突，它们会咬你”），但是你每隔一段时间都要做。但是使用Git，这些操作非常容易和简单，并且它们被认为是你日常工作流程的核心部分之一。例如，在 CVS / Subversion 书籍中，分支和合并通常在最后的章节才第一次谈论（对于高级用户），而在每本Git书中，它已经在第3章（基础知识）中介绍过了。由于其简单性和重复性，分支和合并不再是一件令人害怕的事情。版本控制工具应该比其他任何东西更有助于分支/合并。准备好工具，让我们进入开发模型。我将在这里介绍的模型基本上只是每个团队成员必须遵循的一组步骤以便来管理软件开发过程。Decentralized but centralized我们使用的仓库设置与该分支模型配合良好，具有一个“真实”中央仓库。请注意，这个仓库只被认为是中央仓库（因为Git是DVCS，在技术层面没有中央仓库）。我们将此repo称为origin，所有Git用户应该都熟悉此名称。每个开发人员都会pull并puch 到 origin。但除了集中式 push-pull 关系之外，每个开发人员还可以从其他同行中获取更改以形成子团队。例如，在将正在进行的工作过早地推送到 origin 中之前，这对于与两个或更多开发人员一起处理大型新功能可能是有用的。在上图中，有 Alice 和 Bob，Alice 和 David 以及 Clair和David 的子团队。从技术上讲，这意味着Alice已经定义了一个名为 bob 的Git remote，指向Bob的仓库，反之亦然。The main branches事实上，这个开发模型受到现有模型的极大启发。中央仓库拥有两个主要分支，具有无限的生命周期：masterdeveloporigin 上的 master 分支每个Git用户应该都熟悉。与 master(本地) 分支并行，另一个分支称为develop。我们认为 origin/master 是主分支，其中HEAD的源代码总是反映生产就绪状态。我们将 origin/develop 视为主要分支，而它的 HEAD 指针始终指向为下一发版而做的最新开发改动。有些人称之为“整合分支”(integration branch)。这是建立任何自动夜间构建的地方。当 develop 分支中的源代码达到稳定点并准备好发布时，所有更改都应以某种方式合并回master，然后使用版本号进行标记。具体如何做我们将进一步讨论。因此，每次将更改合并回master时，根据定义，这是一个新的生产版本。我们对此非常严格，因此从理论上讲，我们可以使用Git钩子脚本在每次有master提交时自动构建和推出我们的软件到我们的生产服务器。Supporting branches主干分支master和develop之外，我们的开发模型使用了很多辅助分支来帮助团队成员间的并行开发，减轻功能跟踪的成本，预备生产环境的发布，协助快速修复已发布版本的问题。和主干分支相反，这些辅助分支只有有限的生命期，最终会被移除。我们可能会用到的辅助分支有：Feature branchesRelease branchesHotfix branches上面的每个辅助分支都有一个特定的目标，且严格限制哪些是起源分支，哪些是合并的目标分支。我们一会儿会详细解释。从技术角度来看，这些分支绝不是”特殊的”。分支的类型是按照我们如何使用它们而划分的，也就是普通的 Git 分支而已。Feature branches可以从 develop 派生。必须合并到 develop 分支。分支命名公约： 除 master 、develop、 release-_ 和 hotfix-_ 以外的任意命名。Feature 分支（有时称为 topic 分支），是用来为未来的发版而开发新 features 的分支。当开始 feature 的开发时，。Feature 分支的本质它会在 feature 的开发期内存在，但最终会合并回 develop 分支（一定会在即将发布的版本中添加新功能），或者被直接丢弃掉（在令人失望的试验的情况下）。Feature 分支通常仅存在于开发人员的 repos 中，而不在 origin 中。Creating a release branch要创建一个新的 Feature 分支，从 develop 分支上派生：$git checkout -b myfeature develo…

[译]What’s New in Swift5?
type: item
date: 2019-04-04T22:55:00+08:00
description: 原文链接：What’s New in Swift 5?Swift 5 最终伴随着Xcode 10.2一起到来。这次发布带来了 ABI 稳定性 并且改进了语言，一些期待已久的特性。来看看这些新东西吧！在这篇教程，你将学习Swift 5的一些重大改变。使用 Swift 5 需要Xcode 10.2，所以在开始前请确认你安装了它。Getting StartedSwift 5 源兼容(source compatible) Swift 4.2，但是它不二进制兼容（binary compatible）更早的Swift 发行版。不过由于 ABI 稳定性，未来发行版将与Swift 5二进制兼容。ABI 稳定性让使用不同 Swift版本编译的应用程序和库之间的二进制兼容性。Swift 标准库和运行时嵌入在 OS 中，因此应用程序不会在任何平台上分发自己的库副本。这导致更好的 工具解耦(tool decoupling) 和 OS 集成(OS integration)。你还需要 ABI 稳定性来分发跨多个 Swift 版本的二进制frameworks(binary frameworks )。这需要模块格式稳定性(module format stability)，稳定模块包含编译器的框架公开接口表示的模块文件。你可以在本教程的每个章节找到 Swift Evolution像 [SE-0001] 这样的提议号。你可以浏览每个提案的链接来详细了解每项新变化。最好是在 playground 中尝试这些新特性。启动 Xcode 10.2，选择 File ▸ New ▸ Playground，在 platform 项选择 iOS ，template 选 Blank。命名和保存位置随意，你开心就好。开始吧！需要快速复习一下 Swift 4.2 重点，查看 Swift 4.2教程。What’s New in Swift 4.2?Language ImprovementsSwift 5有很多语言特性，如 动态可调用类型(dynamic callable types),处理未来的枚举(handling future enumeration)等等.Testing Integer Multiples在Swift 4.2中，你可以使用余数运算符确定数字是否是另一个的倍数：let firstNumber = 4 let secondNumber = 2 if secondNumber != 0 && firstNumber % secondNumber == 0 { print("\(secondNumber) * \(firstNumber / secondNumber) = \(firstNumber)") }这段代码如何工作：确认 secondNumber 不为 0.确认 firstNumber除以secondNumber余 0.执行除法操作。你必须确认 secondNumber 不为 0,否则 % 操作将抛出错误。Swift 5 通过给BinaryInteger添加了 isMultiple(of:) 方法简化了这一操作SE-0225:if firstNumber.isMultiple(of: secondNumber) { print("\(secondNumber) * \(firstNumber / secondNumber) = \(firstNumber)") }即使你传入 0 作为参数,isMultiple(of:)依然可以工作，而且是代码更加简洁明了。Escaping Raw StringsSwift 4.2使用转义符来表示字符串中的反斜杠和引号：let escape = "You use escape sequences for \"quotes\"\\\"backslashes\" in Swift 4.2." let multiline = """ You use escape sequences for \"\"\"quotes\"\"\"\\\"\"\"backslashes\"\"\" on multiple lines in Swift 4.2. """Swift 5添加了 raw strings 。你可以在字符串的开头和结尾添加＃，这样你就可以使用反斜杠和引号而不会出现问题:let raw = #"You can create "raw"\"plain" strings in Swift 5."# let multiline = #""" You can create """raw"""\"""plain""" strings on multiple lines in Swift 5. """#在原始字符串中使用字符串插值时，必须在反斜杠后使…

[译]What's New in Swift4?
type: item
date: 2017-06-19T01:17:00+08:00
description: 翻译自Raywenderlich的文章：What’s New in Swift 4? Swift 4 是Swift下一个大版本更新，预计在2017年秋推出Beta版。其重点在与Swift3的兼容性和ABI稳定性。 本文重点介绍一些这个版本中显著影响你代码的变化。好了，让我们开始吧。Getting StartedSwift 4包含在Xcode 9。你可以从苹果的developer portal下载最新的Xcode9(需要一个有效的开发者账号)。每个Beta版的Xcode 都会捆绑最新的Swift 4 快照。在你阅读时，你会注意到[SE-xxxx]格式的链接，这些链接将带你进去相关的Swift Evolution提案。如果你想获得很多和主题相关的信息，请务必点开它们。我推荐在Playground中尝试Swift 4 的新特性和更新，这有助于在脑海中巩固知识，并使你深入每个主题。把玩这些例子，并尝试扩展／打断他们。玩得开心。注：这篇文件将在为每个Bate版的Xcode更新，如果你使用的是不同的Swift快照，这些代码不保证可以运行。Migrating to Swift 4从Swift 3到 4 的迁移比 Swift 2.2 到 3 少了很多麻烦，一般来说，绝大多数的改变都是附加的，并不需要大量的人为修改。因此，Swift 迁移工具为你处理多数的改变。 Xcode 9 同时支持 Swift 4 和 Swift 3.2。如果需要，你可以逐个指定项目中的每个 target 使用 Swift 3.2 还是 Swift 4。 迁移到 并不是完全不受限制的，你可能需要重新部分代码来兼容修的 SDK .而且由于 Swift ABI 仍然尚未稳定所以你需要用 Xcode 9 重新编译你依赖。 当你准备迁移到 Swift 4 ， Xcode 9 再次提供一个工具来帮助你，你可以点击Edit/Convert/To Current Swift Syntax…来呼出转换工具。 选择你想要转换的 targets 后，Xcode 将提示你 Objective-C 推导中的偏好， 选择推荐的选项通过限制推断来减少你的二进制文件的大小。（关于这个的主题的更多信息，参阅Limiting @objc Inference）. 为了更好地理解你代码中预期的变化，我们将首先介绍Swift 4 中变更的API。API Changes在跳转到 Swift 4 加入的新特新前，让我们首先来看一下它对现有的 API 有哪些改成／改善。StringSwift 4 中的 String 获得了很多应得的称赞。这个提案包含大量的改变，让我们来分解下[SE-0163]：怕你怀旧，strings 再次变为集合像之前的 Swift2.0 一样。这个改变使你不在依赖 characters数组，现在你直接遍历 String 对象 ：let galaxy = "Milky Way ?" for char in galaxy { print(char) }不仅仅是循环，你还可以获得 Sequence 和 Collection 所有附加功能;galaxy.count // 11 galaxy.isEmpty // false galaxy.dropFirst() // "ilky Way ?" String(galaxy.reversed()) //"? yaW ykliM" // Filter out any none ASCII characters galaxy.filter { char in let isASCII = char.unicodeScalars.reduce(true, { $0 && $1.isASCII }) return isASCII } // "Milky Way " ASCII 的例子演示了对 Character 一个小改进,现在你可以从 Character 直接访问 UnicodeScalarView,以前你需要实例化一个新的 String[SE-0178]。还有一个附加的时候 StringProtocol, 它声明以前在 String 上声明的大部分功能。这种变化的原因是为了改善切片工作。Swift 4 在 String 中增加了 Substring 类型，继承自 StringProtocol。String 和 Substring 都实现了 StringProtocol,这是两者几乎拥有相同的功能。// Grab a subsequence of String let endIndex = galaxy.index(galaxy.startIndex, offsetBy: 3) var milkSubstring = galaxy[galaxy.startIndex…