原生 iOS 与 Android 基础:Swift / Kotlin、生命周期与构建系统
0. 元信息
- 主题路径:
docs/topics/mobile-cross-platform/subtopics/native-mobile-foundations/README.md - 父主题:
mobile-cross-platform - 主分类:前端与客户端
- 辅助分类:工程技术
- 适合对象:会 React/Python、想做移动端、能用命令行与 IDE 的开发者
- 建议周期:1~2 周(每周 8~10 小时,重点是真机/模拟器实验)
- 前置知识:
mobile-cross-platform父主题 §0;Xcode 15+ 与 Android Studio Hedgehog+ - 最终目标:能用 SwiftUI / UIKit 与 Jetpack Compose 各实现一个含列表 + 网络 + 详情页的最小原生 App,并讲清 iOS ViewController 与 Android Activity 的生命周期差异
1. 学习路线
Swift 语法(可选类型 / 闭包 / ARC / async-await)
→ UIKit 与 SwiftUI 范式(ViewController / NavigationStack)
→ Kotlin 语法(空安全 / 协程 / data class)
→ Activity / Fragment / Compose 三种 Android 范式
→ Xcode / Android Studio 调试、Logcat、Instruments / Profiler
→ 双端最小可用 App:列表 + 网络 + 详情
→ 抓包与 SSL Pinning、签名与真机部署
先 iOS 一周、Android 一周,最后对比。
2. 阶段周数分配(46 周,每天 1.52 小时)
精简子主题按 iOS 一周、Android 一周、综合对比一周推进,再加一个综合项目周。
| 阶段 | 主题 | 周数 | 备注 |
|---|---|---|---|
| 1 | Swift 语法与 UIKit 范式 | 1 周 | 含可选类型 / 闭包 / ARC / async-await |
| 2 | SwiftUI 与 NavigationStack | 0.5 周 | 与 UIKit 对照 |
| 3 | Kotlin 语法与 Activity / Fragment | 1 周 | 含空安全 / 协程 / Compose |
| 4 | Android Studio 调试与 Profiler | 0.5 周 | Logcat / Layout Inspector |
| 5 | 双端最小 App:列表 + 网络 + 详情 | 0.5 周 | 真机部署 |
| 6 | 抓包 / SSL Pinning / 签名 | 0.5 周 | 真机与证书 |
| 7 | 综合项目(双端对比 demo) | 1 周 | 含 README + 复盘 |
选 4 周方案时把第 5/6/7 阶段压成 1 周;选 6 周方案时按上表节奏。每周留 0.5 天复盘。
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 可观察学会标准 |
|---|---|---|---|
| 1 | Swift 语法基础 | 一个 SwiftPM 命令行小工具 | 能解释可选类型 / 值类型 / 引用类型 / ARC |
| 2 | UIKit + SwiftUI | SwiftUI 列表 App | 真机跑通;理解 @State / @Binding / @EnvironmentObject |
| 3 | Xcode 工具链 | 用 Instruments / Debugger 抓一次掉帧 | 能用 po / lldb 看对象 |
| 4 | Kotlin 语法基础 | Kotlin 命令行小工具 | 能解释空安全 / data class / sealed class |
| 5 | Activity / Fragment / Compose | Compose 列表 App | 真机跑通;理解 remember / LaunchedEffect |
| 6 | Android Studio 工具链 | 用 Profiler / Layout Inspector 看一次内存 | 能解释 Leak / Strict Mode |
| 7 | 网络与 JSON | URLSession / Retrofit 双端联调 | 跑通真实 API |
| 8 | 抓包与 ATS | Charles + Wireshark | 能解释 ATS / cleartext / SSL Pinning |
| 9 | 签名与真机部署 | Provisioning / Keystore + 真机安装 | 能解释签名链与升级约束 |
关键陷阱:把 iOS 与 Android 的「生命周期」当同义词;忽略 ARC 与 GC 差异;网络请求塞主线程;签名用 long-lived 私钥。
4. 第一周任务
| 日 | 任务 | 当天交付 |
|---|---|---|
| Day 1 | 装 Xcode 15+ / Android Studio Hedgehog+ / JDK 17;xcodebuild -version、adb devices 自检 | 环境清单 |
| Day 2 | 用 SwiftUI 写最小 iOS:Text + Button + NavigationStack,真机跑 | iOS 工程 + 截图 |
| Day 3 | 用 Compose 写最小 Android:Text + Button + NavHost,真机跑 | Android 工程 + 截图 |
| Day 4 | 用 SwiftUI 写 List + URLSession + JSON 解码 | iOS 列表 Demo |
| Day 5 | 用 Compose 写 LazyColumn + Retrofit + Kotlinx Serialization | Android 列表 Demo |
| Day 6 | 用 viewDidLoad / onCreate / onResume 打日志,对比生命周期时序 | 时序图 |
| Day 7 | 步骤 A:跑通双端原生「列表 → 详情 → 网络」最小可用;步骤 B:补齐 4 类边界(iOS ATS 拒明文 / Android cleartext、屏幕旋转、empty 数据、权限拒绝) | 双端 Demo + 边界测试记录 |
5. 阶段通用验收
- 不看答案独立重写 iOS 与 Android 最小工程;
- 用自己的话解释 ARC / GC、
viewDidLoad/onCreate、URLSession / OkHttp 差异; - 画一张图:iOS 与 Android 生命周期对比;
- 测试正常路径、生命周期异常、空数据、权限拒绝、网络 5xx;
- 至少准备 3 组自定义数据并贴出实际渲染;
- 记录冷启动、内存峰值、网络耗时;
- 能修改既有 App 加网络层 / 加路由 / 加权限。
6. 最终验收
- 独立画出 iOS / Android 生命周期对比表;
- 完成至少 10 个实验:iOS 5 个 + Android 5 个;
- 双端最小原生 App 跑得通,并能上真机;
- 能用 10 分钟讲清 ARC vs GC、SwiftUI vs UIKit、Compose vs View 三组取舍。
7. 综合项目
实现「GitHub Repo 浏览器」原生双端 Demo:iOS SwiftUI + Android Compose + REST API + 详情页 + 收藏功能。成果合入父主题「跨端 Todo / 电商 / IM」综合项目。
本主题贡献
原生 iOS 与 Android 的真正基础是 Swift / Kotlin 的范式选择 + 生命周期模型,不是 IDE 熟练度。本子主题把「Swift 可选类型 + ARC」对照「Kotlin 空安全 + 协程」、把 UIKit 命令式 / SwiftUI 声明式、Android Fragment / Compose 范式、把 Instruments / Android Studio Profiler 作为调试抓手,串成一条主线。
3 职责
- 用同一份”列表 + 网络 + 详情”需求,Swift 一份(SwiftUI + UIKit 互调)+ Kotlin 一份(Compose + Fragment 互调)各实现一遍,对比代码量与心智成本。
- 把 Swift 可选类型(
if let/guard let/??+ ARCweak/[weak self])对照 Kotlin 空安全(?./?:+ 协程CoroutineScope/viewModelScope.launch)讲清,把双向循环引用与lateinit误用导致的泄漏点列全。 - 在
viewDidLoad/viewWillAppear/viewDidAppear与Activity的onCreate/onStart/onResume/onPause各打日志,绘出旋转屏 / 后台 / 回前台三种场景时序图,配 Android Fragment 重建 +SavedStateHandle数据保留策略。
4 交付物
- 一份 SwiftUI 最小 App(
NavigationStack+List+URLSessionasync-await),含 UIKit 互调桥,真机/模拟器跑通,配 Swift 可选类型(if let/guard let)+@State/@Binding用法说明。 - 一份 Jetpack Compose 最小 App(
NavHost+LazyColumn+ Retrofit + Kotlin 协程viewModelScope.launch),含 Android Fragment 互调,真机/模拟器跑通,配remember/LaunchedEffect+ViewModel用法说明。 - 一份生命周期时序对比图:
viewDidLoad/viewWillAppear/viewDidAppearvsActivity的onCreate/onStart/onResume/onPause,含旋转屏 Activity 销毁重建 +SavedStateHandle数据保留方案 + FragmentsetRetainInstance边界。 - 一份抓包与签名记录:Xcode Instruments Allocations 跑一次 + Android Studio Profiler 跑一次,含 ARC Leaks / LeakCanary 报警 + Provisioning Profile / Keystore 真机签名链路(long-lived keystore + 签名过期两个常见陷阱)。
3 指标
- 双端 Demo 冷启动 < 1.5 s(Xcode Instruments Time Profiler 与 Android Studio Profiler 启动 trace 各跑一次,截 trace 图)。
- 列表滚动 P99 帧时间 < 16 ms(iOS
CADisplayLink监听 + AndroidChoreographer.FrameCallback与 GPU Profile 三路同测)。 - 真机 ARC 循环引用 / Fragment Leak 数为 0(Instruments Leaks 全程记录 + LeakCanary 报警 0 条;保留 1 个故意制造的 ARC 循环引用反例截图作为教具)。
Apple Developer Documentation、Android Developers、Hacking with Swift、Now in Android。复制前核对 LICENSE。
8. 推荐资料
Apple Developer Documentation、Android Developers、Hacking with Swift、Now in Android。复制前核对 LICENSE。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
原生 iOS 与 Android 是任何跨端方案的「最终真相来源」。RN / Flutter 通过 JSI 或 Platform Channel 调用的就是这套原生 API;不理解原生层,永远只能照搬文档。SwiftUI 与 Jetpack Compose 是 2019 年后两端并行的声明式 UI 范式,逐步取代 UIKit 与 XML 布局。
9.2 概念地图
flowchart LR
iOS[Swift / UIKit / SwiftUI] --> VC[ViewController]
iOS --> Nav[NavigationStack / UINavigationController]
iOS --> Combine[Combine / async-await]
Android[Kotlin / Activity / Fragment / Compose] --> Lifecycle[Lifecycle / ViewModel]
Android --> Nav2[NavHost / Navigation Component]
Android --> Coroutine[Coroutine / Flow]
Xcode --> Instruments
AS[Android Studio] --> Profiler
9.3 基础知识讲解
9.3.1 论文 / 规范
| 资料 | 用法 |
|---|---|
| Apple, The Swift Programming Language | 语法 + ARC |
| Apple, SwiftUI Essentials | 声明式 UI |
| Google, Jetpack Compose docs | Compose 范式 |
| Google, Android Lifecycle | 生命周期组件 |
| Apple, App Programming Guide for iOS | App 启动 / 后台 |
9.3.2 书
| 书 | 用法 |
|---|---|
| Matt Neuburg, iOS 16 Programming Fundamentals | UIKit / Swift 入门 |
| Paul Hudson, Hacking with Swift 系列 | SwiftUI 实战 |
| Mark L. Murphy, The Busy Coder’s Guide to Android | Android 入门 |
| Chet Haase, Jetpack Compose internals | Compose 原理 |
9.3.3 博客 / 文档
| 资料 | 用法 |
|---|---|
| SwiftUI Lab | SwiftUI 案例 |
| Android Developers Blog | Compose 新特性 |
| Hacking with Swift | Swift 教程 |
| Now in Android | Compose 工程范式 |
9.3.4 人物
| 人物 | 关注点 |
|---|---|
| Paul Hudson | Swift 教程 |
| Chet Haase | Android Graphics / Compose |
| Salman Naseer | Jetpack |
| Sean Allen | iOS 实战 |
9.3.5 方法
- Pair-program with both sides:同一份需求两端各实现,对比代码量与心智成本。
- Log every lifecycle:在
viewDidLoad/onCreate/onResume打日志,理解时序。 - Profile on real device:模拟器不算数,至少每周上真机一次。
9.3.6 重点训练材料
- Apple Human Interface Gui
- Material Design 3
- Now in Android 源码
- SwiftUI Sample Apps
9.4 经典问题与经典案例
| # | 问题 | 最简答案 |
|---|---|---|
| 1 | Swift 可选类型怎么解 | if let / guard let / ?? |
| 2 | Kotlin 空安全 vs Java NPE | 类型系统强制处理 null |
| 3 | iOS ARC 循环引用怎么破 | weak / unowned |
| 4 | Android Activity 旋转屏重建 | ViewModel + SavedStateHandle |
| 5 | iOS 异步网络怎么写 | URLSession.shared.dataTask + async-await |
| 6 | Android 网络怎么写 | Retrofit + OkHttp + Coroutine |
| 7 | iOS 抓包为什么需要 ATS 例外 | 默认禁明文 HTTP |
| 8 | Android 抓包为什么需要 network_security_config | API 28+ 默认禁明文 |
| 9 | iOS 真机签名怎么管 | Provisioning Profile + Certificate |
| 10 | Android 真机签名怎么管 | Keystore + Play App Signing |
9.5 学习难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| ARC vs GC | 引用计数心智模型 | 用 Instruments 看 retain cycle |
Compose remember / LaunchedEffect | 习惯 XML 生命周期 | 跑一次 recomposition 流程 |
| iOS Navigation 三种范式 | NavigationStack / UINavigationController / Coordinator | 用 SwiftUI NavigationStack 起步 |
| Android ViewModel 边界 | 不清楚保存范围 | 用 SavedStateHandle |
| ATS / cleartext 配置 | 默认禁明文 | 配 NSAppTransportSecurity / network_security_config |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 | 组织 | 状态 / 可访问性 |
|---|---|---|---|
| Swift | 5.9+ | Apple | 持续演进 |
| Kotlin | 1.9+ | JetBrains | 持续演进 |
| SwiftUI | iOS 14+ | Apple | 持续演进 |
| Jetpack Compose | 1.5+ | 活跃 | |
| Xcode | 15+ | Apple | 活跃 |
| Android Studio | Hedgehog+ | 活跃 |
9.6.2 Scope
原生层负责系统调用、生命周期、性能关键路径。SwiftUI / Compose 是声明式 UI 范式;UIKit / View 是命令式范式。
9.6.3 Structure
iOS 工程:App + Scene + View + ViewController;Android 工程:Application + Activity + Composable。必会接口:URLSession、Retrofit、onCreate、onResume、viewDidLoad、viewDidAppear。
9.6.4 Ecosystem
Xcode + Instruments + TestFlight;Android Studio + Profiler + Play Console。生态库:Combine / async-await、Coroutines / Flow。
9.6.5 Depth Tiers
| 层级 | 能力 |
|---|---|
| L0 | 知道 Swift / Kotlin 语法 |
| L1 | 能读懂 UIKit / SwiftUI / View / Compose |
| L2 | 能写一个完整原生 App |
| L3 | 能用 Instruments / Profiler 调优 |
| L4 | 能设计组件库 |
本子主题目标:L2。
9.6.6 Source
- Swift
- Kotlin
- SwiftUI
- Jetpack Compose
- 引用版本快照日期:2026-07-30。
10. 常见误区
- 把 UIKit / Compose 当同义词;
- 网络请求塞主线程;
- 用 long-lived Keystore / p12;
- 签名 Profile 过期不更新;
- 模拟器测完就上线;
- iOS 抓包忘记配 ATS;
- Android 抓包忘记配
network_security_config; - 旋转屏 Activity 被销毁,数据丢;
- ARC 循环引用导致内存泄露;
- 不打日志调试,全靠 println。
11. 所有知识点分类(统一规则)
- 编程语言;2. 数据结构与算法;3. 计算机基础;4. 工程技术;5. Web 与后端;6. 前端与客户端;7. 数据与人工智能;8. 项目与职业能力;9. 安全与可靠性。
本计划归属:前端与客户端 主 + 工程技术 辅。
代码块 1:SwiftUI 最小 App
import SwiftUI
struct CounterView: View {
@State private var count = 0
var body: some View {
NavigationStack {
VStack(spacing: 16) {
Text("Count: \(count)").font(.title)
Button("Increment") { count += 1 }
}
.navigationTitle("Demo")
}
}
}
@main
struct DemoApp: App {
var body: some Scene {
WindowGroup { CounterView() }
}
}
代码块 2:Compose 最小 App
package com.example.demo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.navigation.compose.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { DemoApp() }
}
}
@Composable
fun DemoApp() {
val nav = rememberNavController()
NavHost(nav, "home") {
composable("home") { HomeScreen(nav) }
}
}
@Composable
fun HomeScreen(nav: NavHostController) {
var count by remember { mutableStateOf(0) }
Column {
Text("Count: $count")
Button(onClick = { count++ }) { Text("Increment") }
}
}
代码块 3:生命周期时序图
sequenceDiagram
participant App
participant VC as iOS ViewController
participant Act as Android Activity
App->>VC: init / loadView
VC->>VC: viewDidLoad
VC->>VC: viewWillAppear
VC->>VC: viewDidAppear
App->>Act: onCreate
Act->>Act: onStart
Act->>Act: onResume
Note over VC,Act: 用户切换后台
VC->>VC: viewWillDisappear
Act->>Act: onPause / onStop
Note over VC,Act: 回到前台
VC->>VC: viewDidAppear
Act->>Act: onRestart / onResume