阅读视图

发现新文章,点击刷新页面。

Homebrew 5.0:并行加速、MCP 加持,与 Intel 的最后倒计时 - 肘子的 Swift 周报 #111

几天前,我像往常一样在输入 `brew update` 后顺手执行了 `brew upgrade`。出乎意料的是,终端里突然出现了从未见过的画面——大量组件与工具并行下载、整齐排列、同时推进。短暂的惊讶之后,我才从新闻中得知:Homebrew 已经发布了 5.0 版本

老司机 iOS 周报 #358 | 2025-11-17

ios-weekly
老司机 iOS 周报,只为你呈现有价值的信息。

你也可以为这个项目出一份力,如果发现有价值的信息、文章、工具等可以到 Issues 里提给我们,我们会尽快处理。记得写上推荐的理由哦。有建议和意见也欢迎到 Issues 提出。

新闻

objc4-950 源码更新

Runtime 的源码发布新版本,主要更新的是 Xcode26 的 objc_storeStrong 的逻辑,有兴趣可以自行查看。

App Store Mini App Partner Program 隆重推出

参与计划的开发者在销售符合条件的 App 内购买项目时,可享受 15% 的收益抽成减免。需要适配 Advanced Commerce API (ACA) 。微信已经发公告预计会进行接入,期待后续更多中国公司都能同样谈成优惠,让更多增值业务在 iOS 端上线。

文章

🌟 🐢 Optimize your app's speed and efficiency | Meet with Apple

@Smallfly:该视频围绕应用性能优化展开,结合苹果开发中心的实践场景,系统讲解了从 Swift UI 渲染到数据流管理的多维度优化策略。核心内容包括:

  • 工具与调试:通过 Xcode 实时观察界面渲染状态(黄色闪烁标记),使用功耗分析工具量化优化效果;推荐 Instruments 分析视图更新效率,明确性能瓶颈。
  • 技术实践:针对 Swift UI 提出减少视图更新的关键方法——避免存储闭包、初始化时预计算视图结果;利用 Observable 类优化数据流,降低卡片视图对状态变量的依赖。
  • 性能指标:强调监控启动时间、镜头应用延迟等关键指标,通过自动化测试发现问题;结合 Snap 的实践案例,说明团队协作与指标导向对维护应用健康的重要性。

视频通过代码演示与数据对比,为开发者提供了从工具使用到工程实践的全链路优化指南,特别提到 Liquid Glass 和 SwiftUI 的优化,推荐有兴趣的同学按需观看。

🐕 何时组建计算机性能工程团队(2025 年)第 1 部分(共 2 部分

@含笑饮砒霜:作者在文章中分享了非厂商性质技术密集型企业组建性能工程团队的核心建议,指出该团队能通过基础设施成本节约、延迟降低、可扩展性与可靠性提升、工程速度加快实现显著投资回报(如初期可减半基础设施成本,长期每年目标 5%-10% 成本节约),详细说明了性能工程师在新产品测试调优、内部工具开发、瓶颈分析、参数优化等十大核心职责,并给出组建时机与团队规模的参考规则(基础设施年支出超 100 万美元配 1 名工程师,后续每 1000-2000 万美元增 1 名;团队支出应不低于可观测性监测支出;延迟或可靠性阻碍增长时需组建),同时提及部分企业已有相关专职人员可纳入考量,后续第二部分将补充职位描述、潜在陷阱等内容。

🐕 TN3193: Managing the on-device foundation model’s context window

@JonyFang: Apple 在这篇技术说明中系统讲解了设备端基础模型的上下文窗口限制以及开发者应如何应对。文章强调:本地模型不会自动截断超长输入,超过窗口会直接报错,因此必须在应用设计中主动“预算”与管理上下文。Apple 建议使用三类策略来保持对话连续性同时不溢出窗口:

  • 滑动窗口:只保留最新内容,旧内容逐步丢弃;
  • 机会型摘要:上下文接近上限时触发自动总结,把详细内容压缩成短摘要继续对话;
  • 选择性保留 / 层级压缩:按重要性保留关键信息,把次要内容丢弃或按主题分层压缩,需要时再检索。

整体来看,TN3193 的核心信息是:Apple 设备端模型的上下文有限,开发者必须自行设计“记忆管理策略”,否则会遇到输入过长错误。通过“滑动 + 摘要 + 保留”组合策略,可在有限窗口内维持长对话与复杂任务的质量。

🐕 Demystifying AI Coding Agents in Swift

@Cooper Chen:这篇文章不仅手把手带你构建了一个可工作的 Swift AI Coding Agent,更重要的是,它用非常清晰、务实的方式揭开了 "AI 编码助理" 背后的底层原理。作者强调:这些看似强大的智能行为,其实都是从「语言模型 + 工具 + 循环」这三件极其简单的事组合而成,让人一下子从使用者变成真正理解者。

文章最大的价值在于 去魅 + 实操。它不讲虚的,不堆概念,而是用不到 300 行的 Swift 代码,就实现了一个能读文件、写代码、重构逻辑、与用户来回对话的 Coding Agent,让读者第一次意识到 Cursor、Claude Code 这类产品背后并没有不可思议的魔法。
与此同时,作者也展示了真实工程中会遇到的问题:上下文膨胀、循环保护、安全、错误处理、工具设计等,让内容不仅能“跑起来”,还具备工程实用性。

如果你想理解 Coding Agent 的本质,或者想自己打造一个轻量但功能完整的 Swift Agent,这篇文章绝对值得一读。它让复杂的概念变得透明,让看似神秘的 AI 能力真正变成可掌握、可自行构建的技术。

🐢 Roadmap for Improving the Type Checker

@AidenRao:你是否也曾被 the compiler is unable to type-check this expression in reasonable time 的错误困扰?Swift 编译器团队最近发布了一份详细的路线图,旨在系统性地解决这一由来已久的问题。文章深入浅出地解释了类型检查慢的根源——由类型推导和重载解析带来的指数级复杂度。
路线图不仅展示了近期 Swift 6.2 和 6.3 在编译速度上取得的显著成果(真实项目检查时间从 42 秒降至 10 秒),还规划了未来的改进方向:包括加速大型集合字面量检查、移除历史性能 Hack,乃至引入更先进的 SAT 求解技术。如果你对 Swift 编译性能的未来走向感兴趣,这篇文章值得一读。

🐎 来了解一下,为什么你的 Flutter WebView 在 iOS 26 上有点击问题?

@david-clang:iOS 26 上 WebView 点击失效,核心仍是 iOS 18.2 起 WKWebView 的手势状态缓存问题。

当 WebView 被 Flutter overlay 遮挡时,Flutter 通过 delayingGestureRecognizer 延迟 overlay 下方的 UIKit recognizer,使其暂时不触发,从而让 overlay 接管触摸。但 iOS 18.2 起 WKWebView 的手势状态缓存问题导致 overlay 消失后,WKWebView 内部的点击 recognizer 状态仍停留在延迟状态,未能恢复到 recognized,tap 或 JS click 无法派发,元素只能高亮却无法响应点击。

解决方案:

  • 短期规避:使用 pointer_interceptor 在 WebView 上方覆盖一个透明层,阻止 overlay 引发的手势中断,从而避免点击失效。
  • 长期方案:Flutter 官方正在弃用 delayingRecognizer,改为基于 hitTest + FFI 同步判断 的手势体系,在触点处直接判断是否应拦截手势,从根本解决 WebView、AdMob 等 PlatformView 的手势冲突问题。

代码

🐢 Swift Binary Parsing

@阿权:Apple 官方开源的二进制解析库,使用纯 Swift 编写,旨在构建安全、高效的二进制解析。该库提供了一系列用于安全解析二进制数据的工具,同时管理类型和内存安全,以消除常见的基于值的未定义行为,例如类型溢出。

Swift 一直致力于将不安全的内存操作尽可能安全地让用户访问、修改,此库跟 Swift 的思想如出一辙,本来之前 Apple 强推用 Swift 替代 C/C++ 直接操作内存,包括嵌入式也是这个切入点,此库一出如同如虎添翼了,也算是给内存操作提供一套完整的最佳实践了。

内推

重新开始更新「iOS 靠谱内推专题」,整理了最近明确在招人的岗位,供大家参考

具体信息请移步:https://www.yuque.com/iosalliance/article/bhutav 进行查看(如有招聘需求请联系 iTDriverr)

关注我们

我们是「老司机技术周报」,一个持续追求精品 iOS 内容的技术公众号,欢迎关注。

关注有礼,关注【老司机技术周报】,回复「2024」,领取 2024 及往年内参

同时也支持了 RSS 订阅:https://github.com/SwiftOldDriver/iOS-Weekly/releases.atom

说明

🚧 表示需某工具,🌟 表示编辑推荐

预计阅读时间:🐎 很快就能读完(1 - 10 mins);🐕 中等 (10 - 20 mins);🐢 慢(20+ mins)

iOS 社招 - Runtime 相关知识点

核心概念 本质:runtime是 oc 的一个运行时库(libobjc.A,dylib),它为 oc 添加了 面向对象的能力 以及 运行时的动态特性。 面向对象的能力:rutime用 C 语言实现了类

Grow on iOS 26:UIKit + SwiftUI 混合架构下的 Liquid Glass 适配实战

Grow 是一款在 173 个国家和地区获得 App Store 编辑推荐、拥有超过 18 万五星评价的健康管理应用。在适配 iOS 26 的 Liquid Glass 设计语言时,团队遇到了不少挑战:如何在 UIKit + SwiftUI 混合架构下实现原生的 morph 效果?如何精确控制 Scroll Edge Effect?如何处理自定义导航栏元素的动态尺寸?我邀请了 Grow 的开发者之一 Shuhari,分享团队在这次适配过程中的实战经验。文章涵盖 Sheet、Navigation、Popover 等场景的改造方案,深入探讨 UIBarButtonItem 尺寸计算、CABackdropLayer 副作用处理等底层细节,还展示了如何利用 Core Text 创造“玻璃文字”效果。

SwiftUI-WebView 全面指南

SwiftUI 7.0 通过 WebKit 模块,可以轻松实现网页加载、导航控制以及 JavaScript 交互功能。本文将循序渐进,全面介绍 SwiftUI 中的 WebView 用法。

SwiftUI 导航

SwiftUI 提供了多种导航方式,让我为你详细介绍主要的导航模式和相关组件。

1. NavigationStack (iOS 16+)

基本用法

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("前往详情页", value: "详情内容")
                NavigationLink("设置", value: "设置页面")
            }
            .navigationDestination(for: String.self) { value in
                DetailView(content: value)
            }
        }
    }
}

struct DetailView: View {
    let content: String
    
    var body: some View {
        Text("详情: \(content)")
            .navigationTitle("详情页")
    }
}

多类型导航

enum Route: Hashable {
    case product(Int)
    case category(String)
    case settings
}

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                NavigationLink("产品123", value: Route.product(123))
                NavigationLink("电子产品", value: Route.category("electronics"))
                NavigationLink("设置", value: Route.settings)
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .product(let id):
                    ProductView(productId: id)
                case .category(let name):
                    CategoryView(category: name)
                case .settings:
                    SettingsView()
                }
            }
        }
    }
}

2. NavigationView (iOS 13-16)

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: DetailView()) {
                    Label("详情页面", systemImage: "star")
                }
                NavigationLink(destination: SettingsView()) {
                    Label("设置", systemImage: "gear")
                }
            }
            .navigationTitle("主页面")
        }
    }
}

3. 编程式导航

使用 NavigationPath

struct ContentView: View {
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack(spacing: 20) {
                Button("跳转到产品页") {
                    navigationPath.append(Route.product(456))
                }
                
                Button("跳转到分类页") {
                    navigationPath.append(Route.category("books"))
                }
                
                Button("多层级跳转") {
                    navigationPath.append(Route.category("electronics"))
                    navigationPath.append(Route.product(789))
                }
                
                Button("返回根页面") {
                    navigationPath.removeLast(navigationPath.count)
                }
                
                Button("上一步") {
                    guard !navigationPath.isEmpty else { return }
                    navigationPath.removeLast()
                }
            }
            .navigationDestination(for: Route.self) { route in
                // 路由处理...
            }
        }
    }
}

4. Sheet 和 FullScreenCover

模态展示

struct ContentView: View {
    @State private var showingSheet = false
    @State private var showingFullScreen = false
    
    var body: some View {
        VStack(spacing: 20) {
            Button("显示 Sheet") {
                showingSheet = true
            }
            
            Button("全屏显示") {
                showingFullScreen = true
            }
        }
        .sheet(isPresented: $showingSheet) {
            SheetView()
        }
        .fullScreenCover(isPresented: $showingFullScreen) {
            FullScreenView()
        }
    }
}

struct SheetView: View {
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        NavigationView {
            Text("这是 Sheet 视图")
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button("完成") {
                            dismiss()
                        }
                    }
                }
        }
    }
}

5. TabView 标签导航

struct MainTabView: View {
    var body: some View {
        TabView {
            HomeView()
                .tabItem {
                    Label("首页", systemImage: "house")
                }
            
            SearchView()
                .tabItem {
                    Label("搜索", systemImage: "magnifyingglass")
                }
            
            ProfileView()
                .tabItem {
                    Label("我的", systemImage: "person")
                }
        }
    }
}

6. 复杂导航示例

带导航栏的完整示例

struct MainView: View {
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            ProductListView()
                .navigationTitle("产品列表")
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button("设置") {
                            navigationPath.append(AppRoute.settings)
                        }
                    }
                }
                .navigationDestination(for: AppRoute.self) { route in
                    route.destination
                }
        }
    }
}

enum AppRoute: Hashable {
    case productDetail(Product)
    case category(String)
    case settings
    case profile
    
    @ViewBuilder
    var destination: some View {
        switch self {
        case .productDetail(let product):
            ProductDetailView(product: product)
        case .category(let category):
            CategoryView(category: category)
        case .settings:
            SettingsView()
        case .profile:
            ProfileView()
        }
    }
}

自定义导航栏

struct CustomNavigationView: View {
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        NavigationView {
            Text("自定义导航栏")
                .navigationTitle("标题")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    // 左侧按钮
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("取消") {
                            dismiss()
                        }
                    }
                    
                    // 右侧按钮
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button("保存") {
                            // 保存操作
                        }
                        .bold()
                    }
                }
        }
    }
}

7. 导航状态管理

class NavigationManager: ObservableObject {
    @Published var path = NavigationPath()
    
    func navigateToProduct(_ id: Int) {
        path.append(Route.product(id))
    }
    
    func navigateToCategory(_ name: String) {
        path.append(Route.category(name))
    }
    
    func popToRoot() {
        path.removeLast(path.count)
    }
}

struct AppView: View {
    @StateObject private var navManager = NavigationManager()
    
    var body: some View {
        NavigationStack(path: $navManager.path) {
            ContentView()
                .navigationDestination(for: Route.self) { route in
                    // 路由处理
                }
        }
        .environmentObject(navManager)
    }
}

主要特点总结

  1. NavigationStack: iOS 16+ 推荐使用,支持类型安全的路由
  2. 编程式导航: 通过状态管理控制导航流程
  3. 模态展示: Sheet 和 FullScreenCover 用于临时内容
  4. 标签导航: TabView 用于主要功能模块切换
  5. 灵活的路由系统: 支持复杂导航逻辑和深度链接

这些导航方式可以组合使用,创建出符合你应用需求的完整导航体验。

❌