DevOrz - 默认分类
type: channel
link: https://www.devorz.com/index.php/category/default/
description: 只是一个默认分类
items: Flutter 渲染机制详解
items: Flutter 学习推荐资料
items: 下载 App Store 上的 IPA 文件到 Mac
items: [译]A successful Git branching model
items: [译]What’s New in Swift5?
items: [译]What's New in Swift4?
items: Objective-c中属性名以new开头编译报错
items: 《Effective-Objective-C 2.0》笔记

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

下载 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…

Objective-c中属性名以new开头编译报错
type: item
date: 2016-10-30T01:18:00+08:00
description: property follows cocoa naming convention for returning ‘owned’ objects问题当做一个修改密码的页面的时候，很自然的把新密码的输入框命名为newPasswordTextField，此时编译不通过。错误提示如下：property follows cocoa naming convention for returning ‘owned’ objects原因Transitioning to ARC Release Notes中写道： You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter// Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle; 在MRC时代，有约定如果方法名以alloc、copy、init、mutableCopy和new开头且有返回值时，return 对象时先调用一次retain。ARC时代只是把retain交给编译器去自动添加。所以当属性名以new开头时生成的getter方法会有内存管理的语义冲突。解决办法重命名属性@property (strong, nonatomic)UITextField *theNewPasswordTextField;修改getter方法名@property (strong, nonatomic, getter=theNewPasswordTextField) UITextField *newPasswordTextField;指明 attribute((objc_method_family(none)))#ifndef __has_attribute #define __has_attribute(x) 0 // Compatibility with non-clang compilers #endif #if __has_attribute(objc_method_family) #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none))) #else #define BV_OBJC_METHOD_FAMILY_NONE #endif @interface ViewController : UIViewController(UITextField *)newPasswordTextField BV_OBJC_METHOD_FAMILY_NONE;@end

《Effective-Objective-C 2.0》笔记
type: item
date: 2016-07-11T22:04:00+08:00
description: 中文译名《编写高质量iOS与OS X代码的52个有效方法》。关于这本书的一些笔记。熟悉Objective-C起源由消息型语言鼻祖Smalltalk演化而来。是C语言的超集。与函数式语言关键区别：消息结构的语言，运行时所执行的代码由运行环境决定(动态绑定)；函数调用的语言，由编译器决定。NSString *someString 中 someString 为指向NSString 的指针。Type *声明的对象总是被分配的堆区(heap space) 中，而绝不可能分配的栈区(stack)。如果只需保存int float double char 等非对象类型（nonoobject type），使用C结构体(如CGRect)比使用OC对象性能更优，因为创建OC对象需要分配及释放堆区内存等额外开销。在类的头文件中尽量少引入其他头文件头文件在类的头文件中，少引入头文件，使用@Class 向前声明即可。 然后在实现文件中再引入那些类的头文件。这样可以降低类之间的耦合。无法使用向前声明的情况，如果 引入当前类遵守的某一项协议，此时把协议单独放下一个头文件中，再将其引入。多用字面量语法，少用与之等价的方法。NSNumber *intNumber = @1; NSNumber *floatNumber = @2.5f; NSArray *namesArray = @[@"张三",@"李四",@"王五"]; NSString *myName = namesArray[0]; NSDictionary *personDict = @{@"Name":@"张建宇"} NSString *name= personDict[@"name"]; 多用类型常量，少用＃define 预处理指令。＃define定义的出来的常量，不包含类型信息，编译器需要再编译前执行查找替换，会增加编译时间。只在当前类使用的常量，可以使用 static const 在.m中定义。在头文件中使用extern来声明全局变量,并在相关实现文件中定义其值。命名时，通常使用于是相关的类名最为前缀。如UITextFieldTextDidBeginEditingNotification。使用枚举来表示状态，选项，状态码易懂的枚举名可以提高代码的可读性。选项为多选时，使用二进制表示枚举值，以便通过按位或将其组合起来。?：UIInterfaceOrientationMask。switch语句中，不要实现default分支。这样加入新的枚举之后，编译器会提示：switch语句没有处理所有枚举值。消息／对象／运行时理解“属性” 这一概念在对象内部尽量直接访问实例变量。直接访问实例变量不经过方法派发，比点语法快。⚠️直接访问copy修饰的属性，不会掉用setter方法，所以不会拷贝该属性。⚠️不会触发KVO通知。是否会产生问题，视情况而定。初始化方法和dealloc方法中，总是应该直接访问。⚠️注意考虑懒加载的情况下，要使用点语法。理解“对象等同性”这一概念。==比较的是指针地址是否一样。特有的等同性判断方法，如isEqualToString比isEqual快一些。相同的对象必须具有相同的哈希码，但是哈希码相同的对象未必相同。不必逐条比较每个属性的哈希码，依情况，使用速度快，碰撞率低的算法。以“类族模式”隐藏实现细节在既有类中使用关联对象存放自定义数据理解objc_msgSend 的作用Objective-c “动态绑定(dynamic binding)” 的特性使得所要调用的函数直到运行时才能确定。通过动态消息派发系统(dynamic message dicpatch system)来查出对应的方法并执行。消息由接收者(receiver)，选择子(selecter)，以及参数构成。调用方法实际上相当于在给对象发送消息。理解消息转发机制用方法调配技术调试黑盒方法 //TODO//Category #import "NSString+Test.h" #import <objc/runtime.h> @implementation NSString (Test) - (NSString*)eoc_myLowercaseString { NSString *lowercase = [self eoc_myLowercaseString]; NSLog(@"%@ => %@", self, lowercase); return lowercase; } // 不会死循环，因为eoc_myLowercaseString与lowercaseString方法互换了，运行时期间eoc_myLowercaseString选择子实际上对应的原有的lowercaseString方法实现。 + (void)load{ Metho…