iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘

struct vs class:值类型与引用类型的"江湖地位"

swift 复制代码
// 值类型:struct
struct Point {
    var x: Int
    var y: Int
}
var p1 = Point(x: 0, y: 0)
var p2 = p1          // 复制一份全新内存
p2.x = 10
print(p1.x) // 0  ✅ 原值不动

// 引用类型:class
class Button {
    var title: String = "OK"
}
let btn1 = Button()
let btn2 = btn1      // 指向同一块堆内存
btn2.title = "Cancel"
print(btn1.title) // Cancel ❗️共享修改

结论

  • 需要"拷贝"语义 → struct(线程安全、写时复制)
  • 需要"共享"或继承 → class

iOS 应用生命周期

iOS 13 之后分两块:

  • AppDelegate:进程级事件(启动、终止、后台下载)
  • SceneDelegate:窗口级事件(多窗口支持)
swift 复制代码
// AppDelegate.swift
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 初始化 SDK、注册推送
    return true
}

// SceneDelegate.swift
func sceneDidBecomeActive(_ scene: UIScene) {
    // 刷新 UI、重启定时器
}

记忆口诀:Launch → Foreground → Active → Background → Suspended → Terminate

strong / weak / unowned

修饰符 是否增加引用计数 是否可选 场景
strong 默认所有权
weak delegate、父→子
unowned 生命周期同步(如闭包捕获 self)

循环引用实战

swift 复制代码
class Person {
    var pet: Pet?
    deinit { print("Person 释放") }
}
class Pet {
    // 错误:strong 互相持有
    // var owner: Person?
    // 正确:
    weak var owner: Person?
    deinit { print("Pet 释放") }
}

闭包场景:

swift 复制代码
class Net {
    var completion: (() -> Void)?
    func load() {
        // 捕获列表破局
        completion = { [weak self] in
            self?.updateUI()
        }
    }
}

口诀:双向强引用 = 死锁;weak / unowned 拆链

MVC → MVVM

  • MVC:C 既管 UI 又管业务 → MassiveViewController
  • MVVM:VM 负责"数据→视图"的格式化,易测试、可绑定
swift 复制代码
final class ArticleVM: ObservableObject {
    @Published var title = ""
    func fetch() {
        // 纯逻辑,无 UIKit
    }
}

SwiftUI + Combine 让 MVVM 成为"官方亲儿子"

Combine 入门

  • Publisher:发信号
  • Subscriber:收信号
  • Operator:加工信号
swift 复制代码
let vm = TimerVM()
class TimerVM: ObservableObject {
    @Published var seconds = 0
    private var bag = Set<AnyCancellable>()
    init() {
        Timer.publish(every: 1, on: .main, in: .common)
            .autoconnect()
            .assign(to: \.seconds, on: self)
            .store(in: &bag)
    }
}

优势:类型安全、内存管理自动、与 SwiftUI 无缝

GCD:async vs sync

swift 复制代码
// 异步:不阻塞当前线程
DispatchQueue.global(qos: .userInitiated).async {
    let data = try? Data(contentsOf: url)
    DispatchQueue.main.async {
        self.imageView.image = UIImage(data: data!)
    }
}

// 同步:阻塞等待(死锁高危)
// DispatchQueue.main.sync { }  // ❌主线程等待主线程→死锁

最佳实践:UI 更新 main.async;耗时任务 global().async

网络层选型

方案 优点 缺点
URLSession 官方、0 依赖 样板多
Alamofire 链式、自动验证、上传友好 增加 500 KB
swift 复制代码
// URLSession 原生 async/await
let (data, _) = try await URLSession.shared.data(from: url)
let model = try JSONDecoder().decode(User.self, from: data)

数据持久化矩阵

场景 技术 示例
小配置 UserDefaults flag、score
大结构化 CoreData / Realm 离线文章
文件 FileManager 缓存图片
敏感 Keychain token、password

SwiftUI 属性包装器

  • @State:View 内部私有状态
  • @Binding:父子双向引用
  • @ObservedObject:外部可观察对象
  • @EnvironmentObject:全局注入
swift 复制代码
struct PlayerView: View {
    @State private var isPlaying = false          // ① 局部
    @Binding var progress: Double                // ② 父级传入
    @ObservedObject var vm: PlayerVM             // ③ 引用类型
    @EnvironmentObject var appSet: AppSettings   // ④ 全局
}

UIView 几何三兄弟

  • frame:父坐标系 → 布局
  • bounds:自身坐标系 → 绘图、子视图布局
  • center:父坐标系中心点 → 动画平移
swift 复制代码
print(view.frame)   // (x=20,y=100,width=200,height=50)
print(view.bounds)  // (x=0,y=0,width=200,height=50)
print(view.center)  // (x=120,y=125)

DiffableDataSource

告别 performBatchUpdates 崩溃:

swift 复制代码
enum Section { case main }
typealias Snapshot = NSDiffableDataSourceSnapshot<Section, Article>

var dataSource: UITableViewDiffableDataSource<Section, Article>!

func apply(_ items: [Article]) {
    var snap = Snapshot()
    snap.appendSections([.main])
    snap.appendItems(items)
    dataSource.apply(snap, animatingDifferences: true)
}

优势:一致性、动画自动、线程安全

静态库 vs 动态库

维度 静态 Framework 动态 Framework
链接时机 编译期 运行时
包大小 增大 IPA 多 App 共享可降体积
启动速度 略快 略慢
热更新 ✅(App Store 政策外)

官方建议:系统级用动态;小 SDK / 启动敏感用静态

MVVM 优劣大辩论

✅ 测试友好、UI 逻辑分离、SwiftUI 原生绑定

❌ 文件数翻倍、初学者绑定语法易踩坑

适用:中大型项目、单元测试覆盖率要求高

AutoLayout:从 Frame 到约束

swift 复制代码
// 代码约束
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
])

口诀:先关 mask,再激活;Anchor 链式可读性高

Combine vs RxSwift

维度 Combine RxSwift
官方
iOS 版本 ≥13 ≥9
运算符 50+ 200+
跨平台 仅 Apple Android / Web

结论:新纯 iOS 项目 Combine;多平台或复杂流 RxSwift

URLSession 实战封装

swift 复制代码
struct APIClient {
    static func request<T: Decodable>(_ endpoint: String) async throws -> T {
        guard let url = URL(string: endpoint) else { throw URLError(.badURL) }
        let (data, response) = try await URLSession.shared.data(from: url)
        guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw URLError(.badServerResponse) }
        return try JSONDecoder().decode(T.self, from: data)
    }
}
// 使用
let user: User = try await APIClient.request("https://api.xxx.com/user")

Alamofire 优势

  • 链式参数封装
  • 自动 Validation(statusCode 200..<300)
  • Multipart 上传一行代码
  • RequestInterceptor 刷新 Token 无感重试

API 认证三板斧

  1. OAuth2:AccessToken + RefreshToken,标准但流程重
  2. APIKey:Header 内传 key,简单却易泄漏
  3. JWT:自包含签名+过期,无需服务端状态,注意 Payload 别放敏感

存储:全进 Keychain;HTTPS 必须;吊销策略后端控制

安全 checklist

✅ HTTPS + SSL Pinning

✅ 不落日志、不埋 Git

✅ 输入校验 + 输出转义

✅ 限流 / 防重放

✅ 定期轮换密钥

相关推荐
叽哥12 小时前
Flutter Riverpod上手指南
android·flutter·ios
用户091 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan1 天前
iOS26适配指南之UIColor
ios·swift
权咚2 天前
阿权的开发经验小集
git·ios·xcode
用户092 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间2 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918412 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张3 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h3 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa