Swift语法精讲:从基础到进阶——一个杭州自由开发者的深夜复盘

开发者小宇宙
2025-12-16 03:54
阅读 524

大家好,我是阿哲,一个在杭州当了两年自由开发者的“野生码农”。坐标西湖区文新街道某老小区,去年咬牙付了首付,买了一个52平的小两房(其实是老破小改造),现在每个月还着4800块的房贷,外加物业费、水电、宽带,日子过得紧巴巴但踏实。白天写代码,晚上陪老婆追剧(她总吐槽我敲键盘的声音比电视剧还响),周末偶尔去西溪湿地骑个共享单车,假装自己是个“都市隐士”。

今天这篇文章,其实源于上周五晚上的一次“社死”经历。


一、凌晨两点,面试题把我问懵了

事情是这样的:上周五晚上11点,我正窝在沙发上改一个SwiftUI的动画bug(客户急着下周上线),手机突然弹出一条微信消息:

“Hi,看到你简历投过来了,方便明天上午10点视频面试吗?我们是做跨境电商App的,主技术栈Swift + Combine。”

我一看,这公司薪资范围写的是22k-30k,比我目前接单的平均时薪高不少。心想:“干了!反正自由职业嘛,多面几家不亏。”于是秒回:“OK,谢谢!”

结果第二天上午,面试官上来就问:

“你能说说Swift中classstruct的区别吗?再深入一点,比如内存管理、值类型与引用类型的语义差异,还有在并发场景下的表现?”

我脑子“嗡”一下。表面稳如老狗:“嗯…struct是值类型,class是引用类型…” 内心却在疯狂OS:“不是,大哥,我天天用struct写ViewModel,但真没系统梳理过啊!”

更狠的还在后面:

“那如果我现在让你实现一个线程安全的计数器,用struct怎么写?用class呢?为什么struct在这种场景下反而可能更安全?”

我支支吾吾,最后勉强说了个actor,但明显露怯。面试结束,HR礼貌地说“我们会综合评估”,我知道——凉了。

挂掉视频后,我瘫在椅子上,看着窗外阴雨绵绵的杭州天空,心里有点堵。明明写了两年Swift,项目也做了七八个,怎么一到深挖底层,就原形毕露?

那天中午,老婆看我蔫蔫的,递来一碗片儿川:“又面试挂了?没事,大不了继续接外包,反正房贷还能撑半年。”
我苦笑:“不是钱的问题…是感觉自己像个‘API调用员’,只会用现成的东西,不懂原理。”

那一刻,我决定:重新啃一遍Swift语法,从最基础的开始,直到能自信回答任何面试题挑战。


二、开发心得:别把“会用”当成“懂”

说实话,在成为自由开发者之前,我在一家传统企业做iOS开发,月薪15k。那时候写代码就是“复制粘贴+Stack Overflow”,需求来了,找轮子,改改参数,跑通就行。直到去年三月,公司裁员,我被迫“毕业”。

刚开始接单时,为了快速交付,我依然沿用老套路。客户要个登录页?直接套用GitHub上那个高仿抖音的模板;要做个网络请求?Alamofire一把梭。表面上效率很高,实际上地基全是沙子。

转折点发生在去年十月。有个客户让我优化App启动速度,说用户流失率太高。我一顿操作猛如虎:删无用库、延迟加载、预渲染……结果启动时间只降了0.3秒。客户很失望。

后来请教了一位前阿里P7大佬(通过朋友介绍,花了500块请他喝了一顿茶),他只问了一句:

“你知道Swift的静态派发和动态派发区别吗?你的初始化代码里有多少是在主线程同步执行的?”

我哑口无言。

那次之后,我意识到:自由职业者的护城河,不是“能干活”,而是“知道为什么这么干”。

于是,我开始系统性地重学Swift。每天早上6点起床(趁老婆没醒,省电省网),泡杯速溶咖啡,在阳台的小桌子上敲代码、画思维导图。晚上复盘当天学到的知识点,甚至录成语音发给自己听。


三、Swift语法精讲:从“Hello World”到“面试题杀手”

下面是我这两个月整理的核心知识点,结合了真实开发场景 + 高频面试题,希望能帮到和我一样曾经“表面光鲜,内里空虚”的兄弟们。

1. 值类型 vs 引用类型:别再傻傻分不清

基础概念:

  • structenum值类型(Value Type):赋值时拷贝整个值。
  • class引用类型(Reference Type):赋值时拷贝的是引用(指针)。

开发心得: 我以前觉得“用struct更安全”,但不知道为什么。直到有一次,我在一个多人协作的项目里,用class写了一个配置管理器:

class AppConfig {
    var themeColor: UIColor = .blue
}

let config1 = AppConfig()
let config2 = config1
config2.themeColor = .red
print(config1.themeColor) // 输出.red!??

结果UI全乱了。因为config1config2指向同一个对象!

换成struct

struct AppConfig {
    var themeColor: UIColor = .blue
}

var config1 = AppConfig()
var config2 = config1
config2.themeColor = .red
print(config1.themeColor) // 输出.blue ✅

面试题挑战:

Q:为什么Swift推荐优先使用struct?
A:除了线程安全(每个实例独立)、性能(栈分配更快)、可预测性(无共享状态)外,更重要的是——它天然契合函数式编程思想,减少副作用。


2. Optional:不只是“有或没有”

很多人觉得Optional就是“防止崩溃”,但其实它的设计哲学远不止于此。

进阶用法:

// 别再写 if let 了,试试 map 和 compactMap
let usernames: [String?] = ["Alice", nil, "Bob"]
let validNames = usernames.compactMap { $0 } // ["Alice", "Bob"]

// 用 ?? 提供默认值
let score = user.score ?? 0

// 用 guard let 提早退出
guard let token = UserDefaults.standard.string(forKey: "token") else {
    showLogin()
    return
}

开发心得: 我曾经在一个支付模块里,因为没处理Optional,导致用户点击支付按钮后App闪退。客户差点把我拉黑。从那以后,我对Optional产生了“PTSD”,所有可能为nil的地方都加判断。

面试题挑战:

Q:Optional的本质是什么?
A:它其实是一个枚举(enum Optional<Wrapped> { case none, case some(Wrapped) })。所以你可以对它进行模式匹配、map、flatMap等操作。理解这一点,就能写出更优雅的链式调用。


3. 协议(Protocol)与泛型(Generics):组合优于继承

Swift不是OOP语言,而是协议导向编程(POP) 的典范。

真实案例: 我之前写网络层,习惯用基类BaseRequest,子类继承。结果每次加新字段都要改基类,耦合严重。

后来改用协议:

protocol Requestable {
    var path: String { get }
    var method: HTTPMethod { get }
    func encode() -> Data?
}

struct LoginRequest: Requestable {
    let email: String
    let password: String
    
    var path: String { "/login" }
    var method: HTTPMethod { .post }
    
    func encode() -> Data? {
        // 编码逻辑
    }
}

好处:

  • 各请求完全解耦
  • 可以组合多个协议(比如Cachable & Loggable
  • 测试时 mock 超级方便

面试题挑战:

Q:如何用协议实现“依赖注入”?
A:定义协议作为接口,具体实现在运行时注入。比如:

protocol AnalyticsService {
    func log(event: String)
}

class AppCoordinator {
    let analytics: AnalyticsService
    init(analytics: AnalyticsService) {
        self.analytics = analytics
    }
}

这样,测试时传入MockAnalytics,生产环境传入FirebaseAnalytics,完美解耦。


4. 并发:从GCD到async/await,再到Actor

去年WWDC后,我花了一周时间把旧项目里的GCD全迁到async/await。结果发现一个坑:

// 错误示范:在非隔离上下文中访问可变状态
class Counter {
    private var count = 0
    func increment() {
        count += 1 // ⚠️ 数据竞争风险!
    }
}

正确做法是用actor

actor Counter {
    private var count = 0
    func increment() {
        count += 1 // ✅ 自动串行化访问
    }
}

开发心得:
自由开发者最怕并发bug,因为没法靠团队Code Review兜底。actor是Swift送给我们的“线程安全保险”,虽然性能略低,但胜在简单可靠。

面试题挑战:

Q:为什么struct在并发中更安全?
A:因为它是值类型,每次传递都是拷贝。即使多个线程同时修改,也只是修改各自的副本,不会互相干扰。而class的引用共享,天然存在竞态条件。


四、从“被问倒”到“主动出题”:我的转变

经过两个月的恶补,我不仅重新梳理了Swift知识体系,还开始在GitHub上写《Swift面试题挑战》系列(目前已更新37题,star 200+)。

更惊喜的是,上个月,我收到一家出海公司的offer,月薪22k转正,远程办公。面试时,面试官问我:“你觉得Swift最被低估的特性是什么?”

我笑着说:“是它的渐进式安全性。从Optional防崩溃,到值类型防共享状态,再到actor防数据竞争——它一步步把程序员从‘救火队员’变成‘建筑师’。”

他点点头:“不错,下周来聊聊架构吧。”


五、写给同样在路上的你

回到开头那个问题:自由开发者,到底靠什么吃饭?

不是靠会几个框架,也不是靠GitHub星星多,而是靠对语言本质的理解,和解决问题的系统性思维。

我在杭州这个52平的小房子里,经历过焦虑、自我怀疑,也享受过深夜debug成功后的那杯冰可乐的爽快。技术这条路,没有捷径,但每一步都算数。

如果你也在准备面试,或者像我一样想夯实基础,不妨从今天开始:

  1. 每天精读一段Swift源码(比如Optional的实现)
  2. 把项目里的class尝试改成struct,看看是否可行
  3. 主动给自己出面试题,并写下答案(我建了个Notion库,欢迎私信要链接)

最后,分享一句我贴在显示器边的话:

“不要做API的搬运工,要做语言的诗人。”

共勉。

—— 阿哲,于杭州家中,2024年6月的一个雨夜
(房贷还剩298期,但心里踏实多了)

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝