ios-base

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

iOS/Swift 核心开发

Core iOS/Swift Development

Swift 编码规范

Swift Coding Specifications

命名规则

Naming Rules

  • 类型名 UpperCamelCase:
    class NetworkManager
    ,
    struct UserProfile
  • 变量/函数 lowerCamelCase:
    var isLoading
    ,
    func fetchUser()
  • Bool 属性用
    is
    /
    has
    /
    should
    /
    can
    前缀:
    isEnabled
    ,
    hasPermission
  • Protocol 描述能力用
    -able
    /
    -ing
    :
    Codable
    ,
    DataProviding
    ;描述角色用名词:
    Delegate
  • 缩写: 首位全小写
    urlString
    ;非首位两字母全大写
    userID
    ,三字母以上首字母大写
    userUrl
  • Type names use UpperCamelCase:
    class NetworkManager
    ,
    struct UserProfile
  • Variables/functions use lowerCamelCase:
    var isLoading
    ,
    func fetchUser()
  • Bool properties use
    is
    /
    has
    /
    should
    /
    can
    prefix:
    isEnabled
    ,
    hasPermission
  • Protocols describing capabilities use
    -able
    /
    -ing
    suffix:
    Codable
    ,
    DataProviding
    ; Protocols describing roles use nouns:
    Delegate
  • Abbreviations: All lowercase if at the start
    urlString
    ; Two-letter abbreviations are all uppercase if not at the start
    userID
    , abbreviations longer than 3 letters capitalize only the first letter
    userUrl

类型选择

Type Selection

  • 默认用 struct,需要引用语义/继承/deinit/ObjC 互操作才用 class
  • 穷举状态用 enum + associated value:
    case loaded(Data)
    ,
    case failed(Error)
  • 常量命名空间用无 case 的 enum:
    enum Constants { static let timeout = 30.0 }
  • Use struct by default, use class only when reference semantics/inheritance/deinit/ObjC interoperability is required
  • Use enum + associated value for exhaustive states:
    case loaded(Data)
    ,
    case failed(Error)
  • Use enum with no cases for constant namespace:
    enum Constants { static let timeout = 30.0 }

访问控制

Access Control

  • 默认最严格:
    private
    >
    fileprivate
    >
    internal
    >
    public
    >
    open
  • 对外 API 显式标注
    public
  • ViewModel 的
    @Published
    属性用
    private(set)
  • SwiftUI 的
    @State
    必须标记为
    private
  • Use the strictest level by default:
    private
    >
    fileprivate
    >
    internal
    >
    public
    >
    open
  • Explicitly mark external APIs with
    public
  • Use
    private(set)
    for
    @Published
    properties in ViewModel
  • SwiftUI
    @State
    must be marked as
    private

错误处理

Error Handling

  • 定义领域错误 enum 遵循
    LocalizedError
    ,实现
    errorDescription
  • throws
    传播错误,避免静默失败
  • 禁止生产代码中
    try!
    /
    as!
    /
    !
    ,除非有绝对安全理由并写注释
  • Define domain error enum that conforms to
    LocalizedError
    , implement
    errorDescription
  • Use
    throws
    to propagate errors, avoid silent failures
  • Forbid
    try!
    /
    as!
    /
    !
    in production code, unless there is an absolutely safe reason and a comment is added

并发 (async/await)

Concurrency (async/await)

  • 优先 async/await 而非回调或 Combine
  • 并行独立任务用
    async let
  • UI 更新必须在
    @MainActor
  • 简单共享状态保持单一写入源;复杂隔离策略交由
    swift-expert
  • ViewModel 类标注
    @MainActor
  • SwiftUI View 中用
    .task
    启动异步任务,自动取消
  • Prioritize async/await over callbacks or Combine
  • Use
    async let
    for parallel independent tasks
  • UI updates must be executed on
    @MainActor
  • Maintain a single write source for simple shared states; hand over complex isolation strategies to
    swift-expert
  • Mark ViewModel classes with
    @MainActor
  • Use
    .task
    to start asynchronous tasks in SwiftUI View, which will be canceled automatically

闭包

Closures

  • 始终用
    [weak self]
    ,然后
    guard let self else { return }
  • 确定被引用对象生命周期更长才用
    [unowned self]
  • Always use
    [weak self]
    , then
    guard let self else { return }
  • Use
    [unowned self]
    only when you confirm the referenced object has a longer lifecycle

代码组织

Code Organization

  • // MARK: - Section
    分区
  • Protocol 实现放 extension
  • 函数不超过 40 行,文件不超过 400 行
  • guard
    提前返回,最多 3 层缩进
  • SwiftUI View body 不超过 40 行,复杂部分提取为 computed property 或子 View
  • Use
    // MARK: - Section
    to partition code
  • Put Protocol implementations in extensions
  • Functions should not exceed 40 lines, files should not exceed 400 lines
  • Use
    guard
    for early return, maximum 3 levels of indentation
  • SwiftUI View body should not exceed 40 lines, extract complex parts as computed properties or sub Views

注释

Comments

  • 公开 API 用
    ///
    文档注释,含参数/返回值/异常说明
  • 注释解释 why,代码本身解释 what
  • 删除被注释掉的代码
  • Use
    ///
    document comments for public APIs, including parameter/return value/exception descriptions
  • Comments explain why, the code itself explains what
  • Delete commented out code

项目结构

Project Structure

默认目录布局

Default Directory Layout

App/                    → AppDelegate, SceneDelegate, 启动配置
Core/                   → 基础设施 (Network, Storage, Extensions, Utilities)
Features/<FeatureName>/ → 功能模块 (Views, ViewModels, Models, Services)
UI/Components/          → 可复用 UI 组件
Resources/              → Assets, Localizable, Info.plist
App/                    → AppDelegate, SceneDelegate, startup configuration
Core/                   → Infrastructure (Network, Storage, Extensions, Utilities)
Features/<FeatureName>/ → Feature modules (Views, ViewModels, Models, Services)
UI/Components/          → Reusable UI components
Resources/              → Assets, Localizable, Info.plist

架构选择

Architecture Selection

  • SwiftUI 默认: View + ViewModel (@Observable) + Model + Service
  • UIKit 默认: MVVM + Coordinator(中型以上项目)
  • 复杂 SDK/大型项目用 Clean Architecture: Domain → Data → Presentation
  • Default for SwiftUI: View + ViewModel (@Observable) + Model + Service
  • Default for UIKit: MVVM + Coordinator (for medium and above projects)
  • Use Clean Architecture for complex SDK/large projects: Domain → Data → Presentation

依赖注入

Dependency Injection

  • 通过 init 注入,不直接引用单例
  • 定义 Protocol 抽象,注入协议类型
  • SwiftUI 用
    @Environment
    或 custom EnvironmentKey
  • UIKit 通过 Coordinator 或 init 注入
  • Inject through init, do not reference singletons directly
  • Define Protocol abstraction, inject protocol types
  • Use
    @Environment
    or custom EnvironmentKey for SwiftUI
  • Inject through Coordinator or init for UIKit

模块化

Modularization

  • 用 SPM 拆分本地模块
  • Core 模块零外部依赖
  • Feature 模块依赖 Core,不互相依赖
  • 每个模块有独立 Tests target
  • Split local modules with SPM
  • Core module has zero external dependencies
  • Feature modules depend on Core, do not depend on each other
  • Each module has an independent Tests target

文件规则

File Rules

  • 一文件一主类型,文件名与类型名一致
  • Extension 文件:
    String+Validation.swift
  • 测试文件:
    UserServiceTests.swift
  • One main type per file, file name matches the type name
  • Extension files:
    String+Validation.swift
  • Test files:
    UserServiceTests.swift

SwiftUI 核心规则

SwiftUI Core Rules

状态管理

State Management

  • 优先
    @Observable
    而非
    ObservableObject
    (iOS 17+)
  • @State
    必须标记
    private
    ,用于 View 拥有的状态
  • @State
    +
    @Observable
    class 替代
    @StateObject
  • @Binding
    仅用于子视图需要修改父状态
  • @Bindable
    用于注入的
    @Observable
    对象需要绑定时
  • 只读值用
    let
    ,不要用
    @State
    @Binding
  • @Observable
    类必须标注
    @MainActor
  • Prioritize
    @Observable
    over
    ObservableObject
    (iOS 17+)
  • @State
    must be marked
    private
    , used for states owned by the View
  • @State
    +
    @Observable
    class replaces
    @StateObject
  • @Binding
    is only used when the child view needs to modify the parent state
  • @Bindable
    is used when the injected
    @Observable
    object needs to be bound
  • Use
    let
    for read-only values, do not use
    @State
    or
    @Binding
  • @Observable
    classes must be marked with
    @MainActor

现代 API(必须使用)

Modern APIs (Mandatory Usage)

  • foregroundStyle()
    而非
    foregroundColor()
  • clipShape(.rect(cornerRadius:))
    而非
    cornerRadius()
  • NavigationStack
    而非
    NavigationView
  • navigationDestination(for:)
    实现类型安全导航
  • Tab
    API(iOS 18+)而非
    tabItem()
  • .onChange(of:) { old, new in }
    双参数版本
  • .task
    而非
    .onAppear
    启动异步任务
  • Button
    而非
    onTapGesture
    (除非需要位置/次数)
  • foregroundStyle()
    instead of
    foregroundColor()
  • clipShape(.rect(cornerRadius:))
    instead of
    cornerRadius()
  • NavigationStack
    instead of
    NavigationView
  • Implement type-safe navigation with
    navigationDestination(for:)
  • Tab
    API (iOS 18+) instead of
    tabItem()
  • Dual parameter version of
    .onChange(of:) { old, new in }
  • Use
    .task
    instead of
    .onAppear
    to start asynchronous tasks
  • Use
    Button
    instead of
    onTapGesture
    (unless position/click count is needed)

性能优化

Performance Optimization

  • 只传递 View 需要的具体值,避免传整个大对象
  • 避免热路径中的冗余状态更新(检查值变化再赋值)
  • ForEach 必须用稳定 ID,禁止
    .indices
    (动态内容)
  • 大列表用
    LazyVStack
    /
    LazyHStack
  • 避免在 ForEach 中内联过滤,预先过滤并缓存
  • View body 保持纯净,无副作用或复杂逻辑
  • 复杂性能剖析(热路径量化、复制开销建模)交由
    swift-expert
  • Only pass specific values needed by the View, avoid passing the entire large object
  • Avoid redundant state updates in hot paths (check value changes before assignment)
  • ForEach must use stable ID, forbid
    .indices
    (for dynamic content)
  • Use
    LazyVStack
    /
    LazyHStack
    for large lists
  • Avoid inline filtering in ForEach, filter and cache in advance
  • Keep View body pure, no side effects or complex logic
  • Hand over complex performance profiling (hot path quantification, copy overhead modeling) to
    swift-expert

动画

Animations

  • .animation(_:value:)
    而非已废弃的
    .animation(_:)
  • 按钮点击用
    withAnimation
  • 动画修饰符放在被动画属性之后
  • 过渡用
    .transition()
    +
    withAnimation
  • Use
    .animation(_:value:)
    instead of the deprecated
    .animation(_:)
  • Use
    withAnimation
    for button clicks
  • Place animation modifiers after the properties being animated
  • Use
    .transition()
    +
    withAnimation
    for transitions

UIKit 核心规则

UIKit Core Rules

ViewController 结构

ViewController Structure

按顺序组织:Properties → UI Components → Lifecycle → Setup → Methods → Actions → Protocol Extensions
Organize in order: Properties → UI Components → Lifecycle → Setup → Methods → Actions → Protocol Extensions

布局

Layout

  • 优先 SnapKit(如可用)或
    NSLayoutConstraint.activate([])
  • 优先
    UIStackView
    减少约束
  • 复杂列表用
    UICollectionViewCompositionalLayout
    +
    DiffableDataSource
  • Prioritize SnapKit (if available) or
    NSLayoutConstraint.activate([])
  • Prioritize
    UIStackView
    to reduce constraints
  • Use
    UICollectionViewCompositionalLayout
    +
    DiffableDataSource
    for complex lists

内存管理

Memory Management

  • Delegate 必须
    weak
  • 闭包捕获
    [weak self]
  • Timer/观察者在 deinit 中清理
  • Delegate must be
    weak
  • Closures capture
    [weak self]
  • Clean up Timer/observers in deinit

专项参考

Special References

深入学习特定主题时,查阅以下详细指南:
  • SwiftUI 开发 - 状态管理、现代 API、列表性能、动画、布局最佳实践
  • UIKit 开发 - ViewController 结构、布局、Cell 复用、自定义控件
  • 导航架构 - Coordinator Pattern(UIKit)、NavigationStack + Router(SwiftUI)、深度链接
  • 动画系统 - SwiftUI 动画(隐式/显式/过渡)、UIKit 动画、性能优化
  • 性能优化 - SwiftUI 热路径优化、UIKit 视图层级优化、内存管理
  • 组件设计 - 自定义组件、可配置 API、可复用模式
  • 内存管理 - 循环引用、泄漏预防、weak/unowned 使用
When learning specific topics in depth, refer to the following detailed guides:
  • SwiftUI Development - State management, modern APIs, list performance, animations, layout best practices
  • UIKit Development - ViewController structure, layout, Cell reuse, custom controls
  • Navigation Architecture - Coordinator Pattern (UIKit), NavigationStack + Router (SwiftUI), deep links
  • Animation System - SwiftUI animations (implicit/explicit/transition), UIKit animations, performance optimization
  • Performance Optimization - SwiftUI hot path optimization, UIKit view hierarchy optimization, memory management
  • Component Design - Custom components, configurable APIs, reusable patterns
  • Memory Management - Circular references, leak prevention, weak/unowned usage

与其他技能的关系

Relationship with Other Skills

  • 默认 iOS 业务开发优先使用本技能
  • 当任务进入以下任一场景时切换
    swift-expert
    • 需要协议导向深度抽象(PAT、类型擦除、复杂泛型约束)
    • 需要并发隔离设计(
      Sendable
      、actor 边界、重入与取消策略)
    • 需要基于可观测数据的深入性能与内存剖析
    • 需要跨平台(iOS/macOS/watchOS/tvOS)可用性差异设计
  • Priority is given to using this skill for default iOS business development
  • Switch to
    swift-expert
    when the task enters any of the following scenarios:
    • Requires protocol-oriented deep abstraction (PAT, type erasure, complex generic constraints)
    • Requires concurrency isolation design (
      Sendable
      , actor boundaries, reentrancy and cancellation policies)
    • Requires in-depth performance and memory profiling based on observable data
    • Requires cross-platform (iOS/macOS/watchOS/tvOS) availability difference design

✅ Sentinel(Skill 使用自检)

✅ Sentinel (Skill Usage Self-Check)

当且仅当你确定本 Skill 已被加载并用于当前任务时,在回复末尾追加:
// skill-used: ios-base
规则:
  • 只能输出一次
  • 如果不确定是否加载,禁止输出 sentinel
  • 输出 sentinel 代表你已遵守本 Skill 的硬性规则与交付格式
  • 只有当任务与本 skill 的 description 明显匹配时才允许输出 sentinel
When and only when you confirm that this Skill has been loaded and applied to the current task, append the following at the end of your reply:
// skill-used: ios-base
Rules:
  • Output only once
  • If you are not sure whether it is loaded, do not output the sentinel
  • Outputting the sentinel means that you have complied with the mandatory rules and delivery format of this Skill
  • You are allowed to output the sentinel only when the task clearly matches the description of this skill