<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Objective-C 的余晖 on 错误的，</title>
        <link>https://blog.jorne.top/zh-cn/categories/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/</link>
        <description>Recent content in Objective-C 的余晖 on 错误的，</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Sat, 24 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.jorne.top/zh-cn/categories/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Objective-C 的余晖</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/</guid>
        <description>&lt;p&gt;&lt;img src=&#34;https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/cover.png&#34;
	width=&#34;1024&#34;
	height=&#34;1024&#34;
	srcset=&#34;https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/cover_hu_7f4b236204bb9c4d.png 480w, https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/cover_hu_1d1ab8b3c9aaf129.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Cover&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;100&#34;
		data-flex-basis=&#34;240px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;book-description&#34;&gt;Book Description
&lt;/h2&gt;&lt;p&gt;An in-depth look at the language that powered the Apple revolution. From the NeXT Cube to the iPhone App Store, these are the stories and the syntax of a golden era.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第一章：那只薛定谔的猫 —— OC的诞生</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/01-birth/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/01-birth/</guid>
        <description>&lt;h2 id=&#34;11-c语言的狂野与smalltalk的优雅&#34;&gt;1.1 C语言的狂野与Smalltalk的优雅
&lt;/h2&gt;&lt;p&gt;故事开始于1980年代初。那是一个计算机还在穿纸尿裤的年代。&lt;/p&gt;
&lt;p&gt;当时，&lt;strong&gt;C语言&lt;/strong&gt; 就像是那个拿着电锯的德州杀人狂——强大、高效、但也极其危险。它能让你直接操作内存，能让你写出极快的代码，但也能让你因为一个野指针而让整个系统崩溃。&lt;/p&gt;
&lt;p&gt;而在另一个平行宇宙里，施乐（Xerox）帕罗奥多研究中心（PARC）的一群天才们搞出了 &lt;strong&gt;Smalltalk&lt;/strong&gt;。Smalltalk 就像是一个优雅的芭蕾舞者，它不仅是一门语言，更是一个完整的环境。在它的世界里，一切皆对象，一切皆消息。它不用你操心内存，不用你关心底层，你只需要对着对象喊：“嘿，跳个舞！”，它就会跳个舞。&lt;/p&gt;
&lt;p&gt;这时候，有两个叫 &lt;strong&gt;Brad Cox&lt;/strong&gt; 和 &lt;strong&gt;Tom Love&lt;/strong&gt; 的哥们出现了。他们看着C语言，又看着Smalltalk，心里产生了一个大胆（甚至有点变态）的想法：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“如果我们把Smalltalk的消息机制，嫁接到C语言的身上，会生出一个什么怪胎……啊不，天才？”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;于是，Objective-C 就在这种“杂交”实验中诞生了。它不是一门全新的语言，它严格来说是 C 语言的一个 &lt;strong&gt;超集&lt;/strong&gt;。
也就是说，&lt;strong&gt;任何合法的 C 语言代码，都是合法的 Objective-C 代码&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这就像是：你本来只会骑自行车（C语言），突然有人给你的自行车装了一个甚至能飞的火箭助推器（Smalltalk的运行时），但你依然可以像骑自行车一样踩脚踏板。&lt;/p&gt;
&lt;h2 id=&#34;12-next被流放国王的复仇之剑&#34;&gt;1.2 NeXT：被流放国王的复仇之剑
&lt;/h2&gt;&lt;p&gt;如果OC只是Brad Cox的一个实验品，它可能早就淹没在历史的垃圾堆里了。让它真正加冕为王的，是一个被自己创立的公司踢出门的男人——&lt;strong&gt;Steve Jobs&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Jobs 被赶出苹果后，创立了 &lt;strong&gt;NeXT&lt;/strong&gt;。他想造一台完美的电脑，这台电脑不仅要有完美的硬件，还要有完美的软件。他需要一个强大的操作系统，和一套能让开发者快速开发出漂亮GUI程序的开发工具。&lt;/p&gt;
&lt;p&gt;他看上了 Objective-C。&lt;/p&gt;
&lt;p&gt;在那个年代，写GUI程序简直是刑罚。你得处理几千行的C代码来画一个窗口。但是用OC，配合NeXT开发的 &lt;strong&gt;Interface Builder&lt;/strong&gt;（是的，它那时候就叫这个），你可以像搭积木一样拖拽按钮、窗口，然后用简单的 &lt;code&gt;[window makeKeyAndOrderFront:self]&lt;/code&gt; 这种像英语一样的代码来控制它。&lt;/p&gt;
&lt;p&gt;NeXTSTEP 操作系统诞生了。它优雅、先进、完全面向对象。它是乔布斯的复仇之剑。&lt;/p&gt;
&lt;h2 id=&#34;13-如果你觉得现在的xcode难用&#34;&gt;1.3 如果你觉得现在的Xcode难用……
&lt;/h2&gt;&lt;p&gt;回想一下当初的开发环境。那时候没有自动补全，没有ARC，没有StackOverflow。
开发者们靠着名为 &lt;code&gt;Project Builder&lt;/code&gt;（Xcode的前身）和 &lt;code&gt;Interface Builder&lt;/code&gt; 的双剑合璧，在NeXTSTEP上创造了一个又一个奇迹。&lt;/p&gt;
&lt;p&gt;比如 &lt;strong&gt;WorldWideWeb&lt;/strong&gt; —— 世界上第一个Web浏览器，就是蒂姆·伯纳斯-李（Tim Berners-Lee）在NeXT电脑上用Objective-C写出来的。
是的，&lt;strong&gt;没有OC，就没有现在的互联网&lt;/strong&gt;。（好的，这有点夸张，但它确实加速了 Web 的诞生。）&lt;/p&gt;
&lt;h2 id=&#34;14-总结&#34;&gt;1.4 总结
&lt;/h2&gt;&lt;p&gt;OC 的出生，带着一种“实用主义的缝合怪”气质。
它不像 C++ 那样试图重新发明轮子（然后造出了一个正十二面体轮子），它极其简单粗暴：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;保留 C 的一切（指针、结构体、宏）。&lt;/li&gt;
&lt;li&gt;引入 Smalltalk 的面向对象运行时。&lt;/li&gt;
&lt;li&gt;用一对方括号 &lt;code&gt;[]&lt;/code&gt; 把它们强行把它们箍在一起。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这种“简单的暴力美学”，贯穿了 OC 的一生。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第二章：黄金时代 —— 当方括号统治世界</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/02-goldenage/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/02-goldenage/</guid>
        <description>&lt;h2 id=&#34;21-逆袭next-吞并-apple&#34;&gt;2.1 逆袭：NeXT 吞并 Apple
&lt;/h2&gt;&lt;p&gt;1996年，Apple 即使快要倒闭了。他们的操作系统 Mac OS 9 就像一座摇摇欲坠的危楼，那是还是以 Pascal 风格为基础的 Toolbox 年代。他们试图开发下一代操作系统 Copland，但失败得一塌糊涂。&lt;/p&gt;
&lt;p&gt;走投无路的 Apple 看向了外界。他们有两个选择：BeOS 和 NeXTSTEP。
最终，他们选择了 NeXT。乔布斯带着他的 Objective-C 军火库，回到了库比蒂诺。
虽说是 Apple 收购了 NeXT，但正如乔布斯后来所做的那样，怎么看都像是 NeXT 的文化吞噬了旧 Apple。&lt;/p&gt;
&lt;h2 id=&#34;22-cocoa-与-carbon-的战争&#34;&gt;2.2 Cocoa 与 Carbon 的战争
&lt;/h2&gt;&lt;p&gt;回到 Apple 后，乔布斯面临一个巨大的问题：怎么让现有的开发者迁移到这个满是方括号的新世界？
当时的 Mac开发者习惯了 C++ 和 Pascal 风格的 API。让他们去学这门看起来像天书一样的 Objective-C？没门。&lt;/p&gt;
&lt;p&gt;于是 Apple 搞出了两条路：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Carbon&lt;/strong&gt;：旧世界的桥梁。你几乎不用改太多代码就能让你的老程序跑在 Mac OS X 上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cocoa&lt;/strong&gt;：新世界的船票。纯正的 NeXTSTEP 血统，纯正的 Objective-C。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这场战争持续了几年，但胜负早已注定。Cocoa 的开发效率是 Carbon 无法比拟的。
那些坚持用 Carbon 的开发者发现，隔壁用 Cocoa 的家伙，一边喝着咖啡，一边用几行代码就实现了一个带有漂亮动画的抽屉效果窗口，而自己还在和事件循环（Event Loop）搏斗。&lt;/p&gt;
&lt;p&gt;最终，Objective-C 赢了。方括号插满了 Mac OS X 的每一个角落。&lt;/p&gt;
&lt;h2 id=&#34;23-2008寒武纪大爆发&#34;&gt;2.3 2008：寒武纪大爆发
&lt;/h2&gt;&lt;p&gt;如果说 Mac 只是让 OC 站稳了脚跟，那么 iPhone 则让 OC 统治了世界。&lt;/p&gt;
&lt;p&gt;2007年，初代 iPhone 发布。那时只有 Web App。黑客们通过越狱证明了这台设备能运行原生代码。
2008年，Jobs 终于妥协（或者说是顺水推舟），发布了 &lt;strong&gt;iPhone SDK&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这一刻，Objective-C 的命运齿轮开始疯狂转动。
全世界的开发者蜂拥而至。不管你之前是写 Java 的、写 C# 的、还是写 PHP 的，要想在那个闪闪发光的 App Store 里淘金，你就必须学会 Objective-C。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你必须学会什么叫 &lt;code&gt;[alloc init]&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;你必须学会为什么字符串前面要加个 &lt;code&gt;@&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;你必须学会对着屏幕骂：“这该死的 EXC_BAD_ACCESS 是什么鬼？！”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;成千上万的 App 像雨后春笋一样冒出来。愤怒的小鸟、水果忍者、Instagram……
Objective-C 成了当时世界上薪水最高的语言之一。也就是在这个时候，无数中国开发者通过名为《Objective-C 2.0 程序设计》（那是红皮书吗？还是黄皮书？）的武林秘籍，踏入了 iOS 开发的大门。&lt;/p&gt;
&lt;p&gt;那是一个疯狂的、充满梦想的、满屏幕都是方括号的黄金时代。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第三章：战壕里的故事 —— 你的 App 为什么又崩了？</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/03-stories/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/03-stories/</guid>
        <description>&lt;h2 id=&#34;31-手动挡的乐趣与恐惧&#34;&gt;3.1 手动挡的乐趣（与恐惧）
&lt;/h2&gt;&lt;p&gt;现在的孩子们（指 Swift 开发者）可能无法想象，在 ARC（Automatic Reference Counting）出现之前，我们是怎么活下来的。&lt;/p&gt;
&lt;p&gt;那时候，我们是手动的引用计数（MRC, Manual Reference Counting）的奴隶。
每一个对象生下来（&lt;code&gt;alloc&lt;/code&gt;），你都要负责对它说“我要你”（&lt;code&gt;retain&lt;/code&gt;）。当你用完了，你必须记得说“我不要你了”（&lt;code&gt;release&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;如果你忘了说 &lt;code&gt;retain&lt;/code&gt;，对象就会在你转身的一瞬间消失，然后你的程序就会在一个莫名其妙的地方崩溃，报错信息只有冷冰冰的一行：&lt;code&gt;EXC_BAD_ACCESS&lt;/code&gt;。这通常意味着你访问了一个还是温热的尸体（Zombie Object）。&lt;/p&gt;
&lt;p&gt;如果你忘了说 &lt;code&gt;release&lt;/code&gt;，恭喜你，你的 App 会像吃自助餐一样吞噬内存，直到被操作系统无情地杀掉。&lt;/p&gt;
&lt;p&gt;那时候的 iOS 面试题，有一半都是关于内存管理的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“请问 &lt;code&gt;retainCount&lt;/code&gt; 是几？”（正确答案是：别问，问就是不准。）&lt;/li&gt;
&lt;li&gt;“&lt;code&gt;autorelease&lt;/code&gt; 什么时候释放？”&lt;/li&gt;
&lt;li&gt;“为什么我在循环里创建临时对象会导致内存飙升？”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们不仅是程序员，我们还是拆弹专家。&lt;/p&gt;
&lt;h2 id=&#34;32-经典的崩溃unrecognized-selector&#34;&gt;3.2 经典的崩溃：Unrecognized Selector
&lt;/h2&gt;&lt;p&gt;如果你写过 OC，你一定见过这个报错：
&lt;code&gt;-[__NSCFString count]: unrecognized selector sent to instance 0x...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这通常发生在你把一个 &lt;code&gt;NSArray&lt;/code&gt; 当成了 &lt;code&gt;NSString&lt;/code&gt; 用，或者反过来。
因为 OC 是动态类型的，你把一个猫指给编译器看，说“这是狗”，编译器会说“好的，它是狗”。
但是当你试图命令这只“狗”去“汪汪叫”的时候，这只猫就会给你一巴掌（抛出异常）。&lt;/p&gt;
&lt;p&gt;这种极其宽松的类型检查，既是噩梦，也是乐子。
它意味着你可以把任何东西传给任何方法。这也催生了一个著名的防崩溃库模式：即使你向我发送了我听不懂的消息，我也假装听懂了，或者把消息转发给那个真正懂的人。&lt;/p&gt;
&lt;h2 id=&#34;33-那些年我们写的宏&#34;&gt;3.3 那些年我们写的宏
&lt;/h2&gt;&lt;p&gt;为了少写点代码，OC 程序员个个都是宏定义（&lt;code&gt;#define&lt;/code&gt;）大师。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define WEAK_SELF __weak typeof(self) weakSelf = self;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define STRONG_SELF __strong typeof(weakSelf) strongSelf = weakSelf;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define RGB(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;每一个项目里都有一个 &lt;code&gt;Prefix.pch&lt;/code&gt;，里面塞满了各种奇技淫巧。
有的宏甚至能把 OC 伪装成 JS 或者是 C#。&lt;/p&gt;
&lt;h2 id=&#34;34-总结&#34;&gt;3.4 总结
&lt;/h2&gt;&lt;p&gt;那是一个充满了危险的年代。代码里到处是地雷。
但当我们成功地在一台 256MB 内存的 iPhone 3GS 上跑起一个复杂的 3D 游戏，且没有内存泄漏时，那种成就感是无与伦比的。
我们是走钢丝的人。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第四章：遗产 —— 它留下了什么？</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/04-legacy/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/04-legacy/</guid>
        <description>&lt;h2 id=&#34;41-好的遗产命名即文档&#34;&gt;4.1 好的遗产：命名即文档
&lt;/h2&gt;&lt;p&gt;OC 最被人诟病的地方，也是它最伟大的地方，就是它的 &lt;strong&gt;冗长&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在 C 语言里，你可能会看到 &lt;code&gt;strcpm&lt;/code&gt; 这种 cryptic 的函数名。
但在 OC 里，你會看到：
&lt;code&gt;stringByReplacingOccurrencesOfString:withString:options:range:&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;“太长了！”新手惊呼。
“太清晰了！”老手感叹。&lt;/p&gt;
&lt;p&gt;Objective-C 这种如同写文章一样的命名风格（Verbose），直接影响了 Cocoa 框架的设计哲学，也深深地刻在了 Swift 的基因里（虽然 Swift 稍微剪短了一点，但 Argument Label 的精髓依然保留了）。
它教会了我们：&lt;strong&gt;代码是写给人看的，偶尔顺便给机器运行一下。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;42-坏的遗产头文件地狱&#34;&gt;4.2 坏的遗产：头文件地狱
&lt;/h2&gt;&lt;p&gt;OC 继承了 C 的 &lt;code&gt;.h&lt;/code&gt; 和 &lt;code&gt;.m&lt;/code&gt; 分离的传统。
这意味着你改了一个方法的签名，你得在两个地方修改。
这意味着编译器在编译你的项目时，需要把成千上万个头文件复制粘贴几十万次。
这也是为什么 OC 的编译速度（尤其是以前）那么慢的原因之一。&lt;/p&gt;
&lt;p&gt;Swift 终于消灭了头文件，这是 OC 送给我们的最后一份礼物：作为一个反面教材，告诉我们 Module 是多么重要。&lt;/p&gt;
&lt;h2 id=&#34;43-永远的方括号&#34;&gt;4.3 永远的方括号
&lt;/h2&gt;&lt;p&gt;虽然我们正在逐渐告别 OC，但当你偶然打开一个底层的 C++ 库，或者深入 Runtime 的源码时，你依然会感受到那种力量。
Objective-C 证明了：&lt;strong&gt;动态运行时（Runtime）不仅是可行的，而且是强大的。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它让我们明白，并在移动设备如此受限的资源下，依然可以拥有 Smalltalk 般灵动的架构。
这一章结束了历史的回顾。下一部分，我们将深入代码，去解剖那对方括号背后的秘密。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第五章：方括号的艺术 —— 不是调用，是发消息</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/05-messaging/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/05-messaging/</guid>
        <description>&lt;h2 id=&#34;51-从-objectmethod-到-object-method&#34;&gt;5.1 从 &lt;code&gt;object.method()&lt;/code&gt; 到 &lt;code&gt;[object method]&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;如果你来自 Java、C#、或者 Swift，你习惯了“点语法”。
&lt;code&gt;dog.bark()&lt;/code&gt; —— 意思是：命令狗叫。这也是大多数现代语言的逻辑：&lt;strong&gt;函数调用（Function Call）&lt;/strong&gt;。
你拿到一个对象的地址，直接跳转到它内存里的那个函数代码块去执行。&lt;/p&gt;
&lt;p&gt;但在 Objective-C 里，事情变得哲学了起来。
&lt;code&gt;[dog bark]&lt;/code&gt; —— 意思是：&lt;strong&gt;向狗发送一个“bark”的消息&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;区别在哪？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;函数调用&lt;/strong&gt;：是很生硬的。编译器必须知道 &lt;code&gt;dog&lt;/code&gt; 有没有 &lt;code&gt;bark&lt;/code&gt; 方法。如果没有，编译报错。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;发消息&lt;/strong&gt;：是很礼貌的。我只是把“bark”这张纸条递给 &lt;code&gt;dog&lt;/code&gt;。至于 &lt;code&gt;dog&lt;/code&gt; 看了纸条是高兴地叫两声，还是把纸条撕了（忽略），或者是转交给旁边的猫（消息转发），那完全取决于 &lt;code&gt;dog&lt;/code&gt; 心情（Runtime 决议）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是 OC 动态性的根源。因为是“发消息”，所以你可以给 &lt;code&gt;nil&lt;/code&gt; 发消息（对着空气说话，不会有人打你），所以你可以在运行时把消息截获下来换成别的。&lt;/p&gt;
&lt;h2 id=&#34;52-多参数的魅力像写句子一样写代码&#34;&gt;5.2 多参数的魅力：像写句子一样写代码
&lt;/h2&gt;&lt;p&gt;C++ / Java 的函数多参数调用长这样：
&lt;code&gt;subString(0, 5)&lt;/code&gt;
有时候你看着这两个数字，不仅陷入沉思：哪个是 Start？哪个是 Length？还是 End？&lt;/p&gt;
&lt;p&gt;Objective-C 就在这里展示了它的&lt;strong&gt;文科生气质&lt;/strong&gt;：
&lt;code&gt;[string substringFromIndex:0 toIndex:5]&lt;/code&gt; (注：虽然 OC 实际 API 是 &lt;code&gt;substringWithRange:&lt;/code&gt; 等，但这里举例展示标签（Label）的意义)
或者更真实的：
&lt;code&gt;[array insertObject:obj atIndex:5]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;每一个参数前面都有一个介词或者标签。这让 OC 的代码读起来就像一句英语长难句。
&lt;code&gt;[waiter bringCoffee:hot toTable:5 withSugar:YES]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这被 Swift 完美继承了下来。&lt;/p&gt;
&lt;h2 id=&#34;53-嵌套的方括号无数个框&#34;&gt;5.3 嵌套的方括号：无数个框
&lt;/h2&gt;&lt;p&gt;当你想把这一连串操作连起来时，噩梦开始了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[[[[string uppercaseString] substringFromIndex:&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;] stringByAppendingString:&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;World&amp;#34;&lt;/span&gt;] length]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就是著名的“方括号盖饭”。
为了读懂这行代码，你得像剥洋葱一样，从最里面那个括号开始往外剥。
这也是为什么后来 OC 引入了点语法（Dot Syntax）来访问属性（Properties），试图挽救一下大家的视力。
&lt;code&gt;string.uppercaseString.length&lt;/code&gt; —— 啊，世界清净了。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第六章：关键词大观园 —— 那些带 @ 的家伙</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/06-keywords/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/06-keywords/</guid>
        <description>&lt;p&gt;在 C 语言里，关键词通常没有前缀。
在 OC 里，为了避免和 C 语言的关键词冲突（因为 OC 是 C 的超集），OC 的特有关键词前面都带了一个 &lt;code&gt;@&lt;/code&gt;。
这让 OC 的代码看起来充满了“邮件感”。&lt;/p&gt;
&lt;h2 id=&#34;61-interface-与-implementation&#34;&gt;6.1 @interface 与 @implementation
&lt;/h2&gt;&lt;p&gt;如果你想定义一个类 &lt;code&gt;Person&lt;/code&gt;，你需要两步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 在头文件（.h）里昭告天下 (@interface)：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt; : &lt;span style=&#34;color:#a6e22e&#34;&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 我有什么属性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@property&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;nonatomic&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;strong&lt;/span&gt;) NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 我能干什么
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;sayHello&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就好比你的名片。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 在实现文件（.m）里修炼内功 (@implementation)：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@implementation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;sayHello&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLog(&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;Hello, I am %@&amp;#34;&lt;/span&gt;, self.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就好比你的真身。&lt;/p&gt;
&lt;h2 id=&#34;62---号的分野&#34;&gt;6.2 +/- 号的分野
&lt;/h2&gt;&lt;p&gt;你在方法定义前会看到 &lt;code&gt;-&lt;/code&gt; 或 &lt;code&gt;+&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; (减号)：&lt;strong&gt;实例方法 (Instance Method)&lt;/strong&gt;。必须先 &lt;code&gt;alloc init&lt;/code&gt; 出一个对象才能用。
&lt;code&gt;[person sayHello]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; (加号)：&lt;strong&gt;类方法 (Class Method)&lt;/strong&gt;。直接对着类喊。
&lt;code&gt;[Person new]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;63-property-的魔力&#34;&gt;6.3 @property 的魔力
&lt;/h2&gt;&lt;p&gt;在很久很久以前，我们必须手动写 getter 和 setter。
&lt;code&gt;@property&lt;/code&gt; 的出现拯救了我们。
&lt;code&gt;@property (nonatomic, strong) NSString *name;&lt;/code&gt;
这一行代码，编译器自动帮你生成了 &lt;code&gt;_name&lt;/code&gt; 成员变量，&lt;code&gt;name&lt;/code&gt; (getter) 方法，和 &lt;code&gt;setName:&lt;/code&gt; (setter) 方法。&lt;/p&gt;
&lt;p&gt;这里的 &lt;code&gt;nonatomic&lt;/code&gt; 和 &lt;code&gt;strong&lt;/code&gt; (或者 &lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;assign&lt;/code&gt;, &lt;code&gt;weak&lt;/code&gt;) 是内存管理的“咒语”。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strong&lt;/code&gt;: &amp;ldquo;你是我的，我死你才能死。&amp;rdquo; (拥有权)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weak&lt;/code&gt;: &amp;ldquo;我看着你，你死了我就当不认识你。&amp;rdquo; (弱引用，防止循环引用)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;copy&lt;/code&gt;: &amp;ldquo;复印一份给我，原件随你便。&amp;rdquo; (通常用于字符串)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assign&lt;/code&gt;: &amp;ldquo;我就存个地址，死了别找我。&amp;rdquo; (用于基本数据类型)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;64-别的--伙伴&#34;&gt;6.4 别的 @ 伙伴
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@class&lt;/code&gt;: &amp;ldquo;这就是个类名，别问细节，先编译过去再说。&amp;rdquo; (前向声明)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@protocol&lt;/code&gt;: &amp;ldquo;这也是一份合同，签了就得干活。&amp;rdquo; (协议/接口)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@synthesize&lt;/code&gt;: &amp;ldquo;编译器，帮我生成代码。&amp;rdquo; (现在基本不用写了)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@dynamic&lt;/code&gt;: &amp;ldquo;编译器，别管，我自己会在运行时搞定。&amp;rdquo; (高阶玩法)&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>第七章：文件与头文件 —— 你的入场券</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/07-files/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/07-files/</guid>
        <description>&lt;h2 id=&#34;71-h-与-m-的分离&#34;&gt;7.1 .h 与 .m 的分离
&lt;/h2&gt;&lt;p&gt;C 语言的遗产。
任何一个 OC 类通常需要两个文件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Header (.h)&lt;/strong&gt;: 你的脸。你要告诉别人你是谁，你有什么公开的方法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implementation (.m)&lt;/strong&gt;: 你的心。你实际上是怎么干活的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种分离在几十年前是为了提高编译速度（不用每次都解析实现细节），也是为了封装（虽然 OC 的封装是防君子不防小人的）。&lt;/p&gt;
&lt;h3 id=&#34;什么是-mm&#34;&gt;什么是 .mm？
&lt;/h3&gt;&lt;p&gt;如果你看到 &lt;code&gt;.mm&lt;/code&gt; 文件，别怕。那是 &lt;strong&gt;Objective-C++&lt;/strong&gt;。
它是 OC 和 C++ 的混血儿。在那个文件里，你可以左手写 &lt;code&gt;std::vector&lt;/code&gt;，右手写 &lt;code&gt;[NSArray array]&lt;/code&gt;。
这是通往 C++ 庞大生态库的桥梁。&lt;/p&gt;
&lt;h2 id=&#34;72-import-与-class&#34;&gt;7.2 #import 与 @class
&lt;/h2&gt;&lt;p&gt;在 C 里面，我们用 &lt;code&gt;#include&lt;/code&gt;。
在 OC 里，请永远使用 &lt;code&gt;#import&lt;/code&gt;。
&lt;code&gt;#import&lt;/code&gt; 聪明一点，它保证同一个文件只会被包含一次，不会让你出现“重定义”的错误。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;面试必考题：#import 与 @class 的区别？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#import &amp;quot;Person.h&amp;quot;&lt;/code&gt;: 我不仅知道有一个类叫 Person，我还知道它内裤是什么颜色的（知道它所有的公开属性和方法）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@class Person;&lt;/code&gt;: 我只知道有一个叫 Person 的东西，至于它具体长啥样，我不关心。我只需要能声明 &lt;code&gt;Person *p&lt;/code&gt; 这个指针就行了。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这也是解决 &lt;strong&gt;循环引用（Circular Dependency）&lt;/strong&gt; 的唯一解药：A 引用 B，B 引用 A时，至少有一方由于只能用 &lt;code&gt;@class&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;73-pch-与-module&#34;&gt;7.3 pch 与 module
&lt;/h2&gt;&lt;p&gt;以前，我们把所有通用的头文件（比如 UIKit）都塞进 &lt;code&gt;Prefix.pch&lt;/code&gt; 里，这样就不用每个文件都写 import。
但这样会让编译变慢。&lt;/p&gt;
&lt;p&gt;后来，Apple 发明了 &lt;strong&gt;Modules&lt;/strong&gt; (&lt;code&gt;@import UIKit;&lt;/code&gt;)。
它预编译了模块，极大地加速了编译，而且让你不再需要手动去 Link 二进制库文件。
这是现代 OC 开发的标配。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第八章：实战 —— Hello, Object!</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/08-example/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/08-example/</guid>
        <description>&lt;h2 id=&#34;81-一个完整的-oc-程序&#34;&gt;8.1 一个完整的 OC 程序
&lt;/h2&gt;&lt;p&gt;让我们把之前学到的东西拼装起来。如果不依赖 Xcode 的模板，一个纯粹的 OC 程序长什么样？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Greeter.h&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 定义协议
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@protocol&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GreeterDelegate&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;NSObject&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)greeterDidFinishGreeting:(NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)message;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Greeter&lt;/span&gt; : &lt;span style=&#34;color:#a6e22e&#34;&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@property&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;nonatomic&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;copy&lt;/span&gt;) NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@property&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;nonatomic&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;weak&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;GreeterDelegate&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; delegate;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;initWithName:&lt;/span&gt;(NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;greet&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Greeter.m&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#import &amp;#34;Greeter.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@implementation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Greeter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;initWithName:&lt;/span&gt;(NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)name {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [super init]; &lt;span style=&#34;color:#75715e&#34;&gt;// 先初始化父类
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [name &lt;span style=&#34;color:#66d9ef&#34;&gt;copy&lt;/span&gt;]; &lt;span style=&#34;color:#75715e&#34;&gt;// 记住要 Copy 字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; self;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;greet&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;msg &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [NSString stringWithFormat:&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;Hello, %@!&amp;#34;&lt;/span&gt;, self.name];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLog(&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;%@&amp;#34;&lt;/span&gt;, msg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 检查代理是否响应方法，然后发送消息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; ([self.delegate respondsToSelector:&lt;span style=&#34;color:#66d9ef&#34;&gt;@selector&lt;/span&gt;(greeterDidFinishGreeting:)]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [self.delegate greeterDidFinishGreeting:msg];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;main.m&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#import &amp;#34;Greeter.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 稍微作弊一下，直接在 main 里面实现协议
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MainRunner&lt;/span&gt; : &lt;span style=&#34;color:#a6e22e&#34;&gt;NSObject&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;GreeterDelegate&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@implementation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MainRunner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;greeterDidFinishGreeting:&lt;/span&gt;(NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)message {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLog(&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;[Delegate Callback] Done: %@&amp;#34;&lt;/span&gt;, message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; main(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;@autoreleasepool&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// 自动释放池，内存的保护伞
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        MainRunner &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;runner &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [MainRunner new];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Greeter &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;g &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [[Greeter alloc] initWithName:&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;Objective-C&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        g.delegate &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; runner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [g greet];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;82-解读&#34;&gt;8.2 解读
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@autoreleasepool&lt;/code&gt;&lt;/strong&gt;:
在 main 函数里，所有的 OC 对象通常都需要在这个池子里。当出了这个括号，临时的对象（autoreleased objects）就会被统一清理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;[super init]&lt;/code&gt;&lt;/strong&gt;:
OC 的初始化模式。先让爸爸初始化，爸爸同意了（返回非 nil），儿子再初始化。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;respondsToSelector:&lt;/code&gt;&lt;/strong&gt;:
这就是动态性的体现。我在运行时问你：“你会不会这招？”你会我才调，不会我就不调，防止崩。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Delegate 模式&lt;/strong&gt;:
&lt;code&gt;id&amp;lt;GreeterDelegate&amp;gt;&lt;/code&gt;。这里用 &lt;code&gt;id&lt;/code&gt; 表示“随便什么对象”，只要它遵守 &lt;code&gt;GreeterDelegate&lt;/code&gt; 协议。
这是 iOS 开发中最著名的设计模式。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;83-categories-分类&#34;&gt;8.3 Categories (分类)
&lt;/h2&gt;&lt;p&gt;OC 还有一个大杀器：&lt;strong&gt;Category&lt;/strong&gt;。
你可以不通过继承，直接给现有的类（甚至是系统类 NSString）添加方法。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NSString&lt;/span&gt; (Reverse)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (NSString &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;reversedString&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这在 Swift 里叫 Extension。但 OC 的 Category 更加野蛮，甚至可以通过 Runtime 给分类添加属性（虽然有点绕）。&lt;/p&gt;
&lt;h2 id=&#34;84-总结&#34;&gt;8.4 总结
&lt;/h2&gt;&lt;p&gt;这一部分我们了解了 OC 的骨架。
你可能会觉得有点繁琐。没错，OC 就是繁琐。
但这种繁琐中包含着一种&lt;strong&gt;确定性&lt;/strong&gt;。所有的逻辑都赤裸裸地摆在桌面上，没有 Swift 那么多语法糖藏着掖着。
下一章，我们将进入深水区：Advanced &amp;amp; Runtime。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第九章：灵魂 —— Runtime 运行时</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/09-runtime/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/09-runtime/</guid>
        <description>&lt;h2 id=&#34;91-面向对象的谎言&#34;&gt;9.1 面向对象的谎言
&lt;/h2&gt;&lt;p&gt;你写的代码：
&lt;code&gt;[receiver message]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;编译器眼中的代码：
&lt;code&gt;objc_msgSend(receiver, @selector(message))&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Objective-C 是一门披着 C 语言外衣的动态语言。
普通的 C 语言在编译时就决定了哪个函数被调用（静态绑定）。
而 OC 直到运行的那一刻，才决定去哪里找这个方法。&lt;/p&gt;
&lt;p&gt;这就像是：
C 语言是拿着地图走路，路线早就画好了。
OC 是打车，上车了才跟司机说去哪，半路还能改目的地（Method Swizzling）。&lt;/p&gt;
&lt;h2 id=&#34;92-objc_msgsend-的魔法&#34;&gt;9.2 objc_msgSend 的魔法
&lt;/h2&gt;&lt;p&gt;这个函数是 OC 的心脏。它是用汇编写的，为了极致的速度。
它做的事情很简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;检查 &lt;code&gt;receiver&lt;/code&gt; 是不是 &lt;code&gt;nil&lt;/code&gt;。是的话直接返回 0。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;receiver&lt;/code&gt; 的 &lt;code&gt;Class&lt;/code&gt; 的缓存（Cache）里找 &lt;code&gt;message&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;找不到？去 &lt;code&gt;Class&lt;/code&gt; 的方法列表（Method List）里找。&lt;/li&gt;
&lt;li&gt;还找不到？去 &lt;code&gt;SuperClass&lt;/code&gt; 里找。&lt;/li&gt;
&lt;li&gt;&amp;hellip;一直找到 &lt;code&gt;NSObject&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这也是为什么 OC 的方法调用比 C++ 的虚函数稍微慢那么一点点的原因，但换来的是无与伦比的灵活性。&lt;/p&gt;
&lt;h2 id=&#34;93-黑魔法method-swizzling&#34;&gt;9.3 黑魔法：Method Swizzling
&lt;/h2&gt;&lt;p&gt;因为方法查找本身就是一个在表里查字符串的过程。
那如果我们悄悄把表改了呢？
我们要把 &lt;code&gt;[UIViewController viewWillAppear:]&lt;/code&gt; 方法换成我们自己的 &lt;code&gt;[MyClass my_viewWillAppear:]&lt;/code&gt;，在里面偷偷埋点统计用户行为，然后再调用回原来的方法。&lt;/p&gt;
&lt;p&gt;这就是 &lt;strong&gt;AOP（面向切面编程）&lt;/strong&gt; 在 OC 里的终极形态。
Swift 只有在继承了 &lt;code&gt;NSObject&lt;/code&gt; 并且标记了 &lt;code&gt;dynamic&lt;/code&gt; 的时候才能这么干。但在 OC 里，这是标配。&lt;/p&gt;
&lt;p&gt;你可以把系统的 &lt;code&gt;UIImage imageNamed:&lt;/code&gt; 替换掉，给所有图片加载加个缓存或者是打印个日志。
能力越强，责任越大。乱用 Swizzling 的后果就是 Debug 的时候你想杀人。&lt;/p&gt;
&lt;h2 id=&#34;94-消息转发死前的挣扎&#34;&gt;9.4 消息转发：死前的挣扎
&lt;/h2&gt;&lt;p&gt;当 &lt;code&gt;obj&lt;/code&gt; 真的找不到 &lt;code&gt;message&lt;/code&gt; 时，系统不会立刻崩溃，而是给你三次机会：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Resolve&lt;/strong&gt;: &lt;code&gt;+resolveInstanceMethod:&lt;/code&gt; —— 给你个机会动态添加一个方法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ForwardingTarget&lt;/strong&gt;: &lt;code&gt;-forwardingTargetForSelector:&lt;/code&gt; —— 问你有没有备胎（其他对象）能处理这个消息？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ForwardInvocation&lt;/strong&gt;: &lt;code&gt;-forwardInvocation:&lt;/code&gt; —— 把消息打包成 &lt;code&gt;NSInvocation&lt;/code&gt;，随你随便怎么处理（改参数、改目标、甚至吞掉）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果这三步你都无动于衷，那么 &lt;code&gt;doesNotRecognizeSelector:&lt;/code&gt; 才会把你送走。&lt;/p&gt;
&lt;h2 id=&#34;95-总结&#34;&gt;9.5 总结
&lt;/h2&gt;&lt;p&gt;Runtime 是 OC 的灵魂。
Swift 很棒，很快，很安全。
但只有在操作 Runtime 的时候，你才会感觉自己像个真正的黑客。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十章：现代化的救赎 —— Block 与 GCD</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/10-blocksandgcd/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/10-blocksandgcd/</guid>
        <description>&lt;h2 id=&#34;101-block闭包的方括号版本&#34;&gt;10.1 Block：闭包的方括号版本
&lt;/h2&gt;&lt;p&gt;在很久以前，OC 想要回调，只能靠 Delegate。
为了回传一个状态，你得写协议、设代理、实现方法……太累了。
后来，Apple 引入了 &lt;strong&gt;Blocks&lt;/strong&gt;（&lt;code&gt;^&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;它的语法可以说是 OC 中最反人类的设计之一（著名的 &lt;code&gt;fuckingblocksyntax.com&lt;/code&gt; 就是为此而生）：
&lt;code&gt;returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;但是，它让代码可以在原地执行回调。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[manager fetchWeathersWithCompletion:&lt;span style=&#34;color:#f92672&#34;&gt;^&lt;/span&gt;(NSArray &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;weathers, NSError &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 收到数据，直接在这里处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    NSLog(&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;Fetched: %@&amp;#34;&lt;/span&gt;, weathers);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这极大地简化了异步编程的逻辑。需要注意的是 &lt;strong&gt;循环引用（Retain Cycle）&lt;/strong&gt;：在 Block 里用 &lt;code&gt;self&lt;/code&gt;，一定要先 &lt;code&gt;__weak typeof(self) weakSelf = self;&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;102-gcd把线程扔进队列&#34;&gt;10.2 GCD：把线程扔进队列
&lt;/h2&gt;&lt;p&gt;与 Blocks 一起诞生的，是 &lt;strong&gt;Grand Central Dispatch (GCD)&lt;/strong&gt;。
在 GCD 之前，我们用 &lt;code&gt;NSThread&lt;/code&gt; 或 &lt;code&gt;NSOperation&lt;/code&gt;。
GCD 告诉我们：&lt;strong&gt;忘掉线程吧。你只需要关心队列（Queue）。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;串行队列 (Serial Queue)&lt;/strong&gt;: 一个接一个做。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;并发队列 (Concurrent Queue)&lt;/strong&gt;: 大家一起做。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主队列 (Main Queue)&lt;/strong&gt;: 专门负责更新 UI 的（UI 只能在主线程更新）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;), &lt;span style=&#34;color:#f92672&#34;&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 在后台干脏活累活（下载图片）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    UIImage &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;img &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [self downloadImage];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dispatch_async(dispatch_get_main_queue(), &lt;span style=&#34;color:#f92672&#34;&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 回到主线程更新 UI
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        self.imageView.image &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; img;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这套 &lt;code&gt;dispatch_async&lt;/code&gt; 的模板代码，是每一个 OC 程序员的肌肉记忆。
虽然 Swift 如今有了 &lt;code&gt;async/await&lt;/code&gt;，但 GCD 依然是底层最坚实的基石。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十一章：设计的哲学 —— OC 的七种武器</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/11-patterns/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/11-patterns/</guid>
        <description>&lt;h2 id=&#34;111-单例singleton只有一个&#34;&gt;11.1 单例（Singleton）：只有一个
&lt;/h2&gt;&lt;p&gt;OC 的单例写起来很有仪式感：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ (&lt;span style=&#34;color:#66d9ef&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;sharedInstance&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; MyClass &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;instance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; dispatch_once_t onceToken;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dispatch_once(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;onceToken, &lt;span style=&#34;color:#f92672&#34;&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        instance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [[super allocWithZone:NULL] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; instance;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dispatch_once&lt;/code&gt; 保证了线程安全，保证了只会执行一次。这是最标准的写法。&lt;/p&gt;
&lt;h2 id=&#34;112-代理delegate一对一的纠缠&#34;&gt;11.2 代理（Delegate）：一对一的纠缠
&lt;/h2&gt;&lt;p&gt;前面说过，Delegate 是为了解耦。
WebView 即使不知道正在使用它的是哪个 ViewController，也能通过 &lt;code&gt;id&amp;lt;UIWebViewDelegate&amp;gt;&lt;/code&gt; 告诉外面：“网页加载完了”。
弱引用（&lt;code&gt;weak&lt;/code&gt; property）是关键，否则两个对象互相抱着对方的大腿（Retain Cycle），谁也死不掉。&lt;/p&gt;
&lt;h2 id=&#34;113-通知notification一对多的广播&#34;&gt;11.3 通知（Notification）：一对多的广播
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;NSNotificationCenter&lt;/code&gt; 是一个大喇叭。
只要你注册了监听，我不认识你，我还是能发消息给你。
适用于：登录成功、键盘弹出、APP 进入后台这些全局事件。
记得在 &lt;code&gt;dealloc&lt;/code&gt; 里移除监听（虽然 iOS 9 以后系统自动帮你做了，但老习惯很难改）。&lt;/p&gt;
&lt;h2 id=&#34;114-kvo-key-value-observing暗中观察&#34;&gt;11.4 KVO (Key-Value Observing)：暗中观察
&lt;/h2&gt;&lt;p&gt;OC 允许你观察任意对象的任意属性的变化。
&lt;code&gt;[person addObserver:self forKeyPath:@&amp;quot;name&amp;quot; ...]&lt;/code&gt;
这在实现 MVVM（Model-View-ViewModel）架构时非常有用。
不用写任何回调代码，只要 Model 变了，View 自动就变了。&lt;/p&gt;
&lt;h2 id=&#34;115-总结&#34;&gt;11.5 总结
&lt;/h2&gt;&lt;p&gt;OC 的设计模式非常推崇 &lt;strong&gt;松耦合&lt;/strong&gt;。
无论是 Delegate 还是 Runtime 消息机制，都在试图让对象之间的连接变得没那么“僵硬”。
这种哲学让 OC 的代码往往比 C++ 项目更容易拆分和重构（如果不算那堆头文件的话）。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十二章：双城记 —— OC vs Swift</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/12-rivalry/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/12-rivalry/</guid>
        <description>&lt;h2 id=&#34;121-安全感-vs-自由度&#34;&gt;12.1 安全感 vs 自由度
&lt;/h2&gt;&lt;p&gt;Swift 是一门&lt;strong&gt;安全&lt;/strong&gt;的语言。
它有 &lt;code&gt;Optional&lt;/code&gt;，逼着你处理 &lt;code&gt;nil&lt;/code&gt;。
它有强类型检查，逼着你不能乱转类型。
它像一个控制欲极强的妈，把刀具（指针）都收起来，把桌角都包上软垫，生怕你伤着自己。&lt;/p&gt;
&lt;p&gt;Objective-C 是一门&lt;strong&gt;自由&lt;/strong&gt;的语言。
它给你一把枪（指针），告诉你枪口不要对着脚，然后就去喝咖啡了。
如果你真的对着脚开了一枪（Crash），那是你自己的问题。
&lt;code&gt;id&lt;/code&gt; 甚至可以容纳一切。&lt;/p&gt;
&lt;h2 id=&#34;122-值类型-vs-引用类型&#34;&gt;12.2 值类型 vs 引用类型
&lt;/h2&gt;&lt;p&gt;Swift 推崇 &lt;strong&gt;Struct&lt;/strong&gt;（值类型）。
你复制一份，就是真的复制了一份。修改 A 不会影响 B。
这减少了很多多线程竞争的问题。&lt;/p&gt;
&lt;p&gt;OC 只有 &lt;strong&gt;Class&lt;/strong&gt;（引用类型）。
所有的对象都在堆（Heap）上。
你传过去的是一个指针。如果不小心，你在 A 线程改了对象的属性，B 线程可能直接崩给你看。
所以 OC 里我们在多线程环境下通过 &lt;code&gt;copy&lt;/code&gt; 属性或锁来保命。&lt;/p&gt;
&lt;h2 id=&#34;123-动态派发-vs-静态派发&#34;&gt;12.3 动态派发 vs 静态派发
&lt;/h2&gt;&lt;p&gt;Swift 默认尽可能使用 &lt;strong&gt;Static Dispatch&lt;/strong&gt;。
方法调用在编译时就确定了地址，速度飞快，编译器能做大量优化（内联）。&lt;/p&gt;
&lt;p&gt;OC 永远是 &lt;strong&gt;Dynamic Dispatch&lt;/strong&gt;（消息发送）。
它慢，但它灵活。
这也是为什么 Swift 的库很难 Mock，而 OC 的库随便 Swizzle 一下就能 Mock 的原因。&lt;/p&gt;
&lt;h2 id=&#34;124-总结&#34;&gt;12.4 总结
&lt;/h2&gt;&lt;p&gt;Swift 是未来，是工业化、标准化的产物。
Objective-C 是过去，是手工艺、即兴发挥的爵士乐。
它们没有谁好谁坏，只有适不适合。
但是在今天，新项目首选 Swift 已经是不争的共识。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十三章：鹊桥会 —— OC 与 Swift 的混编</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/13-bridge/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/13-bridge/</guid>
        <description>&lt;h2 id=&#34;131-两个世界的桥梁&#34;&gt;13.1 两个世界的桥梁
&lt;/h2&gt;&lt;p&gt;虽然 Swift 喊着要杀掉 OC，但 Apple 还是留了一手：&lt;strong&gt;完美的互操作性（Interoperability）&lt;/strong&gt;。
你可以在同一个项目里，左边是 &lt;code&gt;.swift&lt;/code&gt;，右边是 &lt;code&gt;.m&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;132-这一侧swift-调用-oc&#34;&gt;13.2 这一侧：Swift 调用 OC
&lt;/h2&gt;&lt;p&gt;只要你在 &lt;code&gt;Bridging-Header.h&lt;/code&gt; 里把 OC 的头文件 &lt;code&gt;#import&lt;/code&gt; 进去，Swift 就能看见它们。
而且 Swift 会自动把 OC 的 API “翻译”得更 Swift 一点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initWithString:&lt;/code&gt; -&amp;gt; &lt;code&gt;init(string:)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NS_ENUM&lt;/code&gt; -&amp;gt; Swift Enum&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这是最舒服的方向。Swift 就像吃自助餐一样享用现有的海量 OC 库。&lt;/p&gt;
&lt;h2 id=&#34;133-那一侧oc-调用-swift&#34;&gt;13.3 那一侧：OC 调用 Swift
&lt;/h2&gt;&lt;p&gt;这就有点难受了。
首先，Swift 的类必须继承自 &lt;code&gt;NSObject&lt;/code&gt;。
其次，你想暴露给 OC 的属性和方法前，必须加上 &lt;code&gt;@objc&lt;/code&gt; 关键字。
只有这样，Swift 才会为它们生成动态的派发表，OC 才能通过 Runtime 找到它们。&lt;/p&gt;
&lt;h2 id=&#34;134-nullability-的救赎&#34;&gt;13.4 Nullability 的救赎
&lt;/h2&gt;&lt;p&gt;OC 最初是没有 Optional 的概念的。
为了让 Swift 知道 OC 的返回值到底会不会是 &lt;code&gt;nil&lt;/code&gt;，OC 后来引入了标注：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nonnull&lt;/code&gt;: 绝非空。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nullable&lt;/code&gt;: 可能是空。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NS_ASSUME_NONNULL_BEGIN / END&lt;/code&gt;: 宏包围，省得一个个写。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果没写这些，Swift 会把 OC 的对象识别为 &lt;code&gt;Implicitly Unwrapped Optional&lt;/code&gt; (&lt;code&gt;Type!&lt;/code&gt;)，这是一个充满危险的信号。一旦它是空，你访问它，就崩了。&lt;/p&gt;
&lt;h2 id=&#34;135-总结&#34;&gt;13.5 总结
&lt;/h2&gt;&lt;p&gt;混编是目前大型 App 的常态（尤其是国内大厂）。
但是混编会带来编译时间的直线上升，以及调试时的各种莫名其妙的报错。
如果可以，尽量保持模块间的纯净。不要在同一个模块里纠缠不清。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十四章：战况报告 —— OC 还没死，只是在养老院</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/14-status/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/14-status/</guid>
        <description>&lt;h2 id=&#34;141-国内-vs-国外不同的风景&#34;&gt;14.1 国内 vs 国外：不同的风景
&lt;/h2&gt;&lt;p&gt;在中国，Objective-C 的生命力依然顽强得惊人。
原因很简单：&lt;strong&gt;存量巨大&lt;/strong&gt;。
像微信、支付宝、淘宝这种超级 App，底层有着数百万行的 OC 和 C++ 代码。重写？不存在的。哪怕是像字节跳动这样相对年轻的大厂，核心业务线里依然流淌着大量的 OC 血液。&lt;/p&gt;
&lt;p&gt;所以在国内面试，你依然会被问到 &lt;code&gt;RunLoop&lt;/code&gt;、&lt;code&gt;Runtime&lt;/code&gt;、&lt;code&gt;Block&lt;/code&gt; 底层实现。这不仅是考察技术，更是为了确认你能维护那些比你岁数还大的老代码。&lt;/p&gt;
&lt;p&gt;在国外，尤其是硅谷的创业公司，Swift 已经是绝对的主流。
如果你在 2026 年还在用 OC 开新项目，可能会被同行用异样的眼光看着：“伙计，你是穿越来的吗？”&lt;/p&gt;
&lt;h2 id=&#34;142-它是基础设施&#34;&gt;14.2 它是基础设施
&lt;/h2&gt;&lt;p&gt;Objective-C 正在经历它的“COBOL 化”。
它不会消失。它会沉淀到底层。
Foundation 框架、UIKit 框架，它们的内部依然是 OC（或者是 C++）。
只要 Apple 不把 Cocoa Touch 重写一遍（目前看来它们正在用 Swift 重写，比如 SwiftUI），OC 就永远在那里。&lt;/p&gt;
&lt;h2 id=&#34;143-oc-程序员的未来&#34;&gt;14.3 OC 程序员的未来
&lt;/h2&gt;&lt;p&gt;如果你是一个 精通 OC 的程序员，恭喜你，你正在成为&lt;strong&gt;非物质文化遗产传承人&lt;/strong&gt;。
未来，随着懂 OC 的人越来越少，维护老项目的薪水可能会反而变高（参考现在的 COBOL 程序员）。
但请不要只守着 OC。拥抱 Swift，拥抱 Rust，拥抱 AI。
让 OC 成为你压箱底的绝活，而不是你唯一的拐杖。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十五章：给 Swift 原住民的生存指南</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/15-forswiftdevs/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/15-forswiftdevs/</guid>
        <description>&lt;h2 id=&#34;151-别找了没有-var-和-let&#34;&gt;15.1 别找了，没有 &lt;code&gt;var&lt;/code&gt; 和 &lt;code&gt;let&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;在 OC 里，变量就是变量，它总是可变的（除非你用 &lt;code&gt;const&lt;/code&gt;，但很少人用）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swift: &lt;code&gt;let name = &amp;quot;Jack&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;OC: &lt;code&gt;NSString *name = @&amp;quot;Jack&amp;quot;;&lt;/code&gt; (注意那个 &lt;code&gt;*&lt;/code&gt;，那是你的命)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那个星号 &lt;code&gt;*&lt;/code&gt; 意味着这是一个指针。
Swift 帮你隐藏了引用类型的本质，但 OC 把内脏都掏出来给你看。
如果你忘了写 &lt;code&gt;*&lt;/code&gt;，比如 &lt;code&gt;NSString name&lt;/code&gt;，编译器会觉得你想在栈上创建一个对象，然后报错报到你怀疑人生。&lt;/p&gt;
&lt;h2 id=&#34;152-为什么要有两个文件&#34;&gt;15.2 为什么要有两个文件？
&lt;/h2&gt;&lt;p&gt;Swift: &lt;code&gt;class Person { ... }&lt;/code&gt; (一个文件搞定)
OC: &lt;code&gt;Person.h&lt;/code&gt; + &lt;code&gt;Person.m&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;试着去欣赏这种分离。
&lt;code&gt;.h&lt;/code&gt; 是你对外承诺的接口。
&lt;code&gt;.m&lt;/code&gt; 是你不想让人看见的脏乱差的代码。
当你只想知道这个类怎么用时，看 &lt;code&gt;.h&lt;/code&gt; 就够了。这是一种强制的文档化。&lt;/p&gt;
&lt;h2 id=&#34;153-字符串的坑&#34;&gt;15.3 字符串的坑
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Swift: &lt;code&gt;String&lt;/code&gt; 是值类型。&lt;/li&gt;
&lt;li&gt;OC: &lt;code&gt;NSString&lt;/code&gt; 是不可变引用类型，&lt;code&gt;NSMutableString&lt;/code&gt; 是可变引用类型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你把一个 &lt;code&gt;NSMutableString&lt;/code&gt; 传给了一个属性，而那个属性是从 &lt;code&gt;copy&lt;/code&gt; 声明的，那么它变成了一个 &lt;code&gt;NSString&lt;/code&gt;（不可变）。如果你试图修改它，Crash。&lt;/p&gt;
&lt;h2 id=&#34;154-最后的建议&#34;&gt;15.4 最后的建议
&lt;/h2&gt;&lt;p&gt;不要试图把 OC 写成 Swift。
不要到处用点语法（除了属性访问）。
试着去感受“发消息”的禅意。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十六章：给 C/C&#43;&#43; 老兵的战地手册</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/16-forcppdevs/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/16-forcppdevs/</guid>
        <description>&lt;h2 id=&#34;161-别想了没有模板-templates&#34;&gt;16.1 别想了，没有模板 (Templates)
&lt;/h2&gt;&lt;p&gt;OC 的泛型（Generics）是假的。
&lt;code&gt;NSArray&amp;lt;NSString *&amp;gt;&lt;/code&gt; 只是给编译器看的。在运行时，它就是个装满 &lt;code&gt;id&lt;/code&gt; 的数组。
所以，别想着用模板元编程。别想着用 SFINAE。
OC 是动态语言，它的多态靠的是 Duck Typing（鸭子类型）和 Runtime 查找，而不是编译期生成代码。&lt;/p&gt;
&lt;h2 id=&#34;162-智能指针-vs-arc&#34;&gt;16.2 智能指针 vs ARC
&lt;/h2&gt;&lt;p&gt;C++ 11 有 &lt;code&gt;std::shared_ptr&lt;/code&gt;。
OC 有 ARC (Automatic Reference Counting)。
它们在原理上几乎一样：引用计数。&lt;/p&gt;
&lt;p&gt;但是 OC 的对象统一继承自 &lt;code&gt;NSObject&lt;/code&gt;，系统级别内置了计数器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;std::shared_ptr&lt;/code&gt; -&amp;gt; &lt;code&gt;strong&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;&lt;code&gt;std::weak_ptr&lt;/code&gt; -&amp;gt; &lt;code&gt;weak&lt;/code&gt; property (而且 OC 的 weak 指针指向的对象死后会自动置为 &lt;code&gt;nil&lt;/code&gt;，这是最伟大的发明之一，再也不用担心野指针了)。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;163-名字空间不存在的&#34;&gt;16.3 名字空间？不存在的
&lt;/h2&gt;&lt;p&gt;C++: &lt;code&gt;namespace MyLib { ... }&lt;/code&gt;
OC: (没有)&lt;/p&gt;
&lt;p&gt;所以你会看到：&lt;code&gt;NSObject&lt;/code&gt;, &lt;code&gt;UIView&lt;/code&gt;, &lt;code&gt;AFNetworking&lt;/code&gt;。
前缀（Prefix）就是我们的名字空间。
如果你写一个库，请务必加上你的前缀（比如 &lt;code&gt;AGPerson&lt;/code&gt;），否则你会和别人的 &lt;code&gt;AGPerson&lt;/code&gt; 冲突，然后导致 Linker Error。&lt;/p&gt;
&lt;h2 id=&#34;164-拥抱运行时&#34;&gt;16.4 拥抱运行时
&lt;/h2&gt;&lt;p&gt;C++ 的 RTTI (运行时类型识别) 被很多人认为是恶魔。
但在 OC 里，Introspection (内省) 是日常。
&lt;code&gt;isMemberOfClass:&lt;/code&gt;, &lt;code&gt;isKindOfClass:&lt;/code&gt;, &lt;code&gt;respondsToSelector:&lt;/code&gt;。
尽情地问对象它是什么吧。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十七章：OC 讲笑话时间</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/17-jokes/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/17-jokes/</guid>
        <description>&lt;h2 id=&#34;171-史上最长的方法名&#34;&gt;17.1 史上最长的方法名
&lt;/h2&gt;&lt;p&gt;OC 程序员最喜欢的运动：&lt;strong&gt;敲键盘&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Java 程序员觉得他们罗嗦：
&lt;code&gt;AbstractSingletonProxyFactoryBean&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;OC 程序员笑了：
&lt;code&gt;application:didReceiveRemoteNotification:fetchCompletionHandler:&lt;/code&gt;
这还只是个起手式。&lt;/p&gt;
&lt;p&gt;有人在 GitHub 上发起过挑战，寻找 Cocoa 框架里最长的方法名。
冠军通常是 CoreData 或 AVFoundation 的某个 API，长度通常超过 80 个字符。
比如：
&lt;code&gt;constraintsAffectingLayoutForAxis:ofItem:withConstant:priority:&lt;/code&gt;
(其实这个是 AutoLayout 的，还算短的)&lt;/p&gt;
&lt;p&gt;结论：OC 程序员的键盘空格键（用来敲代码补全）通常是最先坏的。&lt;/p&gt;
&lt;h2 id=&#34;172-方括号&#34;&gt;17.2 方括号
&lt;/h2&gt;&lt;p&gt;A: &amp;ldquo;为什么你们 OC 程序员喜欢用方括号？&amp;rdquo;
B: &amp;ldquo;[因为 [我们 [觉得 [这 [很 [酷]]]]]]]&amp;rdquo;&lt;/p&gt;
&lt;p&gt;有传言说，OC 的 parser 实际上就是一个只会数括号的计数器。&lt;/p&gt;
&lt;h2 id=&#34;173-关于-nil&#34;&gt;17.3 关于 nil
&lt;/h2&gt;&lt;p&gt;A: &amp;ldquo;我的程序崩了，因为空指针。&amp;rdquo;
B: (Java/C++ 程序员) &amp;ldquo;NullPointerException? Segmentation Fault?&amp;rdquo;
C: (OC 程序员) &amp;ldquo;崩了？不可能。给 nil 发消息什么都不会发生。除非你把 nil 塞进了 NSArray。&amp;rdquo;&lt;/p&gt;
&lt;p&gt;是的，&lt;code&gt;[NSArray arrayWithObject:nil]&lt;/code&gt; 是 OC 程序员最猝不及防的翻车现场。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>第十八章：结语 —— 永远的 `&lt;objc/runtime.h&gt;`</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/18-epilogue/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/18-epilogue/</guid>
        <description>&lt;h2 id=&#34;181-最后的告别&#34;&gt;18.1 最后的告别
&lt;/h2&gt;&lt;p&gt;如果我们把编程语言比作城市，Objective-C 就像是那座曾经辉煌的老工业基地。
年轻人们搬去了 Swift 那个由玻璃和钢铁建成的现代化新区，那里有类型安全的高速公路，有自动化的内存回收工厂。&lt;/p&gt;
&lt;p&gt;但偶尔，你会怀念老城区。
你会怀念那种可以直接把手伸进机器齿轮里的粗糙感（Runtime），你会怀念那些用铆钉和方括号敲打出来的坚固建筑（Cocoa）。&lt;/p&gt;
&lt;p&gt;Objective-C 也许再也不会有新的特性加入了。
但只要 Apple 的操作系统还在，只要 &lt;code&gt;libobjc.A.dylib&lt;/code&gt; 还在系统里，它就活着。
它活在每一个 iOS App 的底层，活在每一次 &lt;code&gt;objc_msgSend&lt;/code&gt; 的跳动中。&lt;/p&gt;
&lt;h2 id=&#34;182-参考资料&#34;&gt;18.2 参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Objective-C Programming Language&lt;/em&gt; (Apple Documentation Archive)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Effective Objective-C 2.0&lt;/em&gt; by Matt Galloway (必读经典)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Cocoa Design Patterns&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Apple Open Source: &lt;a class=&#34;link&#34; href=&#34;https://opensource.apple.com/source/objc4/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://opensource.apple.com/source/objc4/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;183-后记&#34;&gt;18.3 后记
&lt;/h2&gt;&lt;p&gt;写作本书的过程中，我仿佛又回到了那个对着 Xcode 3 调试内存泄漏的下午。
希望这本书能让你不仅学会语法，更能感受到那代程序员的快乐与痛苦。&lt;/p&gt;
&lt;p&gt;再见，Objective-C。
你好，未来。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(全书完)&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>前言：致那个方括号的时代</title>
        <link>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/00-preface/</link>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.jorne.top/zh-cn/objective-c-%E7%9A%84%E4%BD%99%E6%99%96/00-preface/</guid>
        <description>&lt;p&gt;在这个SwiftUI漫天飞舞、声明式编程大行其道的2026年，你可能会问：&lt;strong&gt;“为什么？为什么要写一本关于Objective-C的书？”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;好问题。这就像是在电动车满街跑的时代，突然有人要把一台满身油污的V12内燃机搬上讲台，然后兴致勃勃地教你如何调整化油器。&lt;/p&gt;
&lt;p&gt;确实，Objective-C（以下简称OC）已经老了。它老到它的很多语法看起来像是在和编译器吵架；它老到它的方括号 &lt;code&gt;[]&lt;/code&gt; 常常让习惯了点语法 &lt;code&gt;.&lt;/code&gt; 的新一代程序员感到手指抽筋；它老到苹果在每年的WWDC上都在用Swift一点点地把它埋进历史的尘埃里。&lt;/p&gt;
&lt;p&gt;但是，朋友，你听说过“余晖”吗？&lt;/p&gt;
&lt;p&gt;OC不仅是一门语言，它是一段传奇。它是乔布斯离开苹果后在NeXT的复仇利剑，它是iPhone改变世界时的幕后功臣。每一个滑动解锁的流畅动画背后，都有一次 &lt;code&gt;objc_msgSend&lt;/code&gt; 的疯狂奔跑；每一个App Store奇迹的背后，都有无数个 &lt;code&gt;[retain]&lt;/code&gt; 和 &lt;code&gt;[release]&lt;/code&gt; 的血泪史。&lt;/p&gt;
&lt;p&gt;我们怀念它，不是因为它完美（天哪，它离完美差得远了），而是因为它&lt;strong&gt;真实&lt;/strong&gt;。它让你直面内存的恐惧，它让你理解什么是“动态运行时”的魔法。在Swift那个安全得像婴儿房的世界里待久了，有时候你会想念OC这片狂野的西部荒野——在那里，你可以随心所欲地把一个对象变成另一个对象（isa swizzling），把一个方法换成另一个方法（method swizzling），只要你胆子够大，编译器就不敢管你。&lt;/p&gt;
&lt;p&gt;这本书不是为了让你用OC去写下一个抖音（虽然你完全可以），而是为了让你看懂移动开发这座大厦的&lt;strong&gt;地基&lt;/strong&gt;。理解了OC，你就理解了iOS的灵魂。&lt;/p&gt;
&lt;p&gt;而且，说实话，我觉得 &lt;code&gt;[receiver message]&lt;/code&gt; 这种发消息的写法，有一种古典的、慢条斯理的优雅。就像在微信秒回的时代，偶尔写一封手写的信。&lt;/p&gt;
&lt;p&gt;所以，请坐好。我们要发车了。目标：1980年代。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;致谢与献词&#34;&gt;致谢与献词
&lt;/h1&gt;&lt;p&gt;献给 &lt;strong&gt;Brad Cox&lt;/strong&gt; 和 &lt;strong&gt;Tom Love&lt;/strong&gt;，感谢你们在那个C++刚刚想要统治世界的年代，选择了另一条名叫Smalltalk的小径。&lt;/p&gt;
&lt;p&gt;献给 &lt;strong&gt;Steve Jobs&lt;/strong&gt;，感谢你把它带回了苹果。&lt;/p&gt;
&lt;p&gt;最重要的是，献给 &lt;strong&gt;&lt;code&gt;nil&lt;/code&gt;&lt;/strong&gt;。
在OC里，向 &lt;code&gt;nil&lt;/code&gt; 发送消息永远是安全的（它只会默默地返回0），不像某些现代语言里的 &lt;code&gt;Optional&lt;/code&gt;，动不动就因为强制解包而崩溃给你看。&lt;code&gt;nil&lt;/code&gt;，你是我们最沉默也最温柔的守护者。&lt;/p&gt;
&lt;p&gt;也献给所有的iOS开发者，无论你是从MRC时代一路 &lt;code&gt;autorelease&lt;/code&gt; 过来的老兵，还是从未见过 &lt;code&gt;*.m&lt;/code&gt; 文件的Swift原生代新人。希望这本书能让你会心一笑，或者至少了解一下，你的前辈们当年都在和什么东西搏斗。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
