Swift入门教程:iOS开发第一步

堆上种月亮
2025-12-19 09:34
阅读 1295

上周五晚上十点半,我瘫在工位上盯着Xcode里一堆红得发亮的编译错误,脑子里只有一个念头:“我一个35岁还在写Rust的老后端,怎么就被拉去搞iOS了?”

这事得从头说起。我们组原本是做后端服务的,主要维护一个高并发的交易系统。但去年双11前,产品那边突然扔过来一个需求:要做一个配套的iOS App,用来提升用户粘性和转化率。产品经理小王拍着胸脯说:“前端就你们几个老手带一带,Swift现在很成熟了,上手快!”——说得好像我们是变形金刚,随时能切换形态似的。

更离谱的是,领导居然点头了。理由很现实:团队里没人懂原生iOS开发,外包又贵又不好控,不如内部培养。于是,作为组里年龄最大(也最不会拒绝人)的那个,我被“委以重任”:带头啃下Swift,两周内跑通第一个Demo。


为什么是Swift?而不是React Native或者Flutter?

我知道很多人看到“iOS开发”第一反应是跨平台方案。说实话,我也想过直接上Flutter——毕竟我们后端用Rust,对性能和内存安全有执念,而Flutter的Dart语言虽然不咋地,但至少不用碰Objective-C那坨祖传代码。

但这次不行。产品方明确要求:必须符合Apple的设计规范,动画要丝滑,交互要原生。而且他们还偷偷告诉我,这个App未来要上App Store做付费功能,审核不能出岔子。跨平台框架在审核时容易踩坑,尤其是涉及支付、隐私权限这些敏感模块。

再加上,公司最近在推“技术纵深”文化——别光会调API,得深入平台底层。所以,学Swift成了唯一选项。


别被“入门”两个字骗了

市面上号称“Swift零基础入门”的书籍一抓一大把,但很多都是2016年写的,还在讲var view: UIView!这种过时写法。我翻了三本,最后发现最靠谱的反而是Apple官方的《The Swift Programming Language》——免费、更新及时、例子全是SwiftUI。

不过说实话,光看书真不够。Swift这语言表面温柔(语法简洁、类型安全),背地里坑不少。比如:

  • Optional 看似防崩溃,但新手一不小心就!强制解包,上线后Crash报告堆成山。
  • 值类型 vs 引用类型 搞不清,闭包里retain cycle(循环引用)悄无声息地吃掉内存。
  • 异步编程completion handler 切到 async/await,老项目兼容性直接裂开。

我第一天写了个简单的网络请求,结果因为没处理URLSession的强引用,在模拟器跑得好好的,真机一测——内存暴涨到800MB。当时真的想砸MacBook(还好忍住了,毕竟分期还没还完)。


我的第一个SwiftUI项目:不是Todo,是“防产品乱改需求”工具

为了快速验证可行性,我没按套路写Todo List,而是搞了个内部工具:需求变更追踪器。产品经理每次提新需求,必须通过这个App录入,自动关联Jira ticket,并记录修改时间。顺便还能统计他每周“返工”次数——当然,这部分UI没给他看 😏。

关键代码:用SwiftUI搭骨架

SwiftUI最大的好处是声明式语法,UI和逻辑耦合度低。以下是我首页的核心代码(已简化):

import SwiftUI

struct RequirementListView: View {
    @StateObject private var viewModel = RequirementViewModel()
    
    var body: some View {
        NavigationView {
            List(viewModel.requirements) { req in
                VStack(alignment: .leading, spacing: 8) {
                    Text(req.title)
                        .font(.headline)
                    Text("提出时间: \(req.createdAt, formatter: dateFormatter)")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
                .swipeActions {
                    Button(role: .destructive) {
                        viewModel.delete(id: req.id)
                    } label: {
                        Label("删除", systemImage: "trash")
                    }
                }
            }
            .navigationTitle("需求池")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    NavigationLink("新增") {
                        NewRequirementView()
                    }
                }
            }
            .task {
                // iOS 15+ 推荐用 task 替代 onAppear 做异步加载
                await viewModel.loadRequirements()
            }
        }
    }
    
    private let dateFormatter: DateFormatter = {
        let df = DateFormatter()
        df.dateStyle = .medium
        df.timeStyle = .short
        return df
    }()
}

几个值得注意的安全实践:

  1. @StateObject管理ViewModel生命周期,避免重复初始化导致的数据竞争。
  2. task modifier 替代 onAppear:后者在Navigation跳转时可能多次触发,引发重复请求。
  3. Swipe Actions 做删除:符合Apple人机交互指南(HIG),比放个“删除按钮”更安全(防误触)。
  4. 日期格式化器提前初始化:避免在body里创建,否则每次重绘都新建对象,性能杀手。

安全意识:别让App变成漏洞发射器

作为老程序员,我最怕的就是“功能跑通了,结果被安全团队打回来”。iOS开发尤其要注意几点:

1. 网络请求别裸奔

早期我图省事,直接用URLSession.shared.data(from:),结果被安全扫描工具标红:“明文HTTP请求”。赶紧改成:

// 启用ATS(App Transport Security)
// 在Info.plist中确保:
// <key>NSAppTransportSecurity</key>
// <dict>
//     <key>NSAllowsArbitraryLoads</key>
//     <false/>
// </dict>

// 代码层强制HTTPS
let url = URL(string: "https://api.internal.company.com/requirements")!
let (data, _) = try await URLSession.shared.data(from: url)

记住:iOS默认禁止HTTP! 除非你明确配置例外(强烈不建议)。

2. 用户数据别乱存

一开始我把token存在UserDefaults,测试同事一句话让我冷汗直冒:“你这App卸载重装还能自动登录?那是不是别人借你手机也能进?”

赶紧换成Keychain

import Security

enum KeychainError: Error {
    case noData
    case unexpectedData
}

func saveToken(_ token: String, forKey key: String) throws {
    let data = token.data(using: .utf8)!
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data
    ]
    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    guard status == errSecSuccess else { throw KeychainError.unexpectedData }
}

虽然代码啰嗦点,但安全无小事。产品可以妥协,安全不能。

3. 权限申请要克制

有次我为了调试方便,在Info.plist里把所有权限都加上了(相机、位置、通讯录……)。结果提审被拒,理由是:“App声明了访问通讯录权限,但未在二进制中使用相关API”。

后来学乖了:只在真正需要时才申请权限,并且在弹窗前先给用户解释“为什么要这个权限”。Apple现在对隐私极其敏感,乱要权限=直接拒审。


避坑指南:那些书里不告诉你但会坑死你的事

Xcode版本地狱

我们组有人用Xcode 14,有人用15,结果Swift语法支持不一致。比如if let的新写法(if let x { ... })在14里报错。最后统一规定:所有成员必须用最新稳定版Xcode,并在CI脚本里加版本检查。

模拟器 vs 真机

有个Bug特别诡异:在iPhone 14 Pro模拟器上一切正常,真机一跑就卡死。查了半天,发现是用了.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)),但在后台时通知没移除,导致闭包持有self形成循环引用。

教训:重要功能必须真机测试! 模拟器省电,但不保命。

App Store审核玄学

第一次提审,三天就被拒。理由是:“App截图包含占位文本‘Lorem ipsum’”。我心想这不就是模板吗?结果人家说:“所有UI元素必须反映真实功能”。

第二次,因为没提供隐私政策URL,又被拒。

第三次,终于过了——但审核花了整整7天。建议:预留至少两周审核时间,别卡deadline!


学习资源推荐(亲测有效)

资源类型 名称 为什么推荐
书籍 《Swift Programming: The Big Nerd Ranch Guide》 实战导向,每章都有练习,适合从0到1
官方文档 Apple Developer Documentation 最权威,更新快,带可运行代码片段
视频 Sean Allen 的YouTube频道 讲解清晰,侧重最佳实践和避坑
社区 Swift Forums Apple工程师亲自答疑,适合问深度问题

别再看那些“7天精通Swift”的毒鸡汤了。真正的精通,来自一次次被Xcode折磨后的顿悟。


写在最后:35岁学Swift,晚吗?

经常有年轻同事问我:“哥,你都35了还折腾新语言,不累吗?”

累啊!每天通勤1小时(北京地铁10号线早高峰懂的都懂),回家还得陪娃,只能熬夜敲代码。但我觉得值。

  • 技术广度决定职业寿命:只会一门语言,在35+的职场太危险。
  • Swift的设计哲学很对我胃口:安全、高效、表达力强——跟Rust有点像,只是没那么“严格”。
  • 做出能摸到的产品:后端日志再漂亮,也不如看到自己写的App在同事手机上跑起来爽。

上周,那个“防产品乱改需求”工具正式在团队内部上线。产品经理小王用了两天后跑来问我:“能不能加个功能,让他自动把我的需求转给隔壁组?”

我笑了笑,默默在代码里加了一行注释:

// TODO: 拒绝甩锅功能 - by 老程序员 at 2024-06-15

如果你也正准备入坑iOS开发,记住三点:

  1. 别信“简单入门”——Swift易学难精,安全细节藏在魔鬼里。
  2. 尊重Apple生态——它的规则看似繁琐,实则是帮你避开无数坑。
  3. 动手,再动手——看十本书不如写一个能上架的App。

共勉。毕竟,在这个卷成麻花的行业,能活到35岁还在写代码的,都是狠人

评论 0

最热最新
暂无评论
堆上种月亮Lv.1
0
影响力
0
文章
0
粉丝