前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Combine-常见使用场景

Combine-常见使用场景

作者头像
YungFan
发布于 2025-05-23 02:14:20
发布于 2025-05-23 02:14:20
10100
代码可运行
举报
文章被收录于专栏:学海无涯学海无涯
运行总次数:0
代码可运行

介绍

在现代 iOS 开发中,响应式编程日益重要。Apple 推出的 Combine 框架为开发者提供了强大的声明式 API,用于处理异步事件流。本文将结合常见场景,逐一展示 Combine 的实际用法,包括网络请求、输入控制、定时器、通知监听、异步任务处理以及视图控制器之间的逆向传值。

网络请求

通过 Combine 可以优雅地封装网络请求流程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let url = URL(string: "https://api.example.com/data")!
// Publisher
let publisher = URLSession.shared.dataTaskPublisher(for: url)
    .map { $0.data }
    .decode(type: Response.self, decoder: JSONDecoder())
    .eraseToAnyPublisher()
// 订阅
let cancellable = publisher
    .sink(receiveCompletion: { completion in
        switch completion {
        case .failure(let error):
            print("Error: \(error)")
        case .finished:
            break
        }
    }, receiveValue: { response in
        print("Response: \(response)")
    })

控制输入

结合 @Published 和 debounce,可以高效地处理用户输入,避免频繁触发操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ViewController: UIViewController {
    @Published var text = ""
    private var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        $text
            .debounce(for: 0.5, scheduler: DispatchQueue.main)
            .sink { [weak self] value in
                guard let self = self else { return }
                self.processInput(value)
            }
            .store(in: &cancellables)
    }

    func processInput(_ input: String) {
        // 处理输入内容
        print("Input: \(input)")
    }
}

定时器

使用 Combine 的 Timer.publish 可以轻松创建定时器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private var subscription: AnyCancellable?

subscription = Timer
            .publish(every: 1, on: .main, in: .common)
            .autoconnect()
            .scan(0) { count, _ in // 累加,count为闭包最后一次返回的值
                count + 1
            }
            .sink(receiveCompletion: { _ in
                print("finish")
            }, receiveValue: { [weak self] count in // 操作UI时,[weak self]不可少
                guard let self = self else { return }
                self.countLbl.text = count.format
            })

通知

借助 NotificationCenter 和 Combine,可以优雅地响应通知事件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private var subscriptions = Set<AnyCancellable>()

NotificationCenter
            .default
            .publisher(for: UITextField.textDidChangeNotification, object: inputTxtField) // 监听输入
            .compactMap { ($0.object as? UITextField)?.text } // 此时的publisher是通知
            .map { "The user entered: \($0)" }
            .assign(to: \.text, on: textLbl)
            .store(in: &subscriptions)

异步

通过 Future 可以将传统的回调封装为 Combine 的 Publisher。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Publisher
func authorize() -> AnyPublisher<Bool, Error> {
        // 延期Publisher等待订阅
        Deferred {
            // 任何异步操作都可以包进Future
            Future { promise in
                UNUserNotificationCenter
                    .current()
                    .requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
                        // Promise处理
                        if let error = error {
                            // AnyPublisher的第2个参数
                            promise(.failure(error))
                        } else {
                            // AnyPublisher的第1个参数
                            promise(.success(granted))
                        }
                    }
            }
        }
        .eraseToAnyPublisher()
    }
    
private var subscriptions = Set<AnyCancellable>()
// 订阅
authorize() // AnyPublisher
            .replaceError(with: false) // 异常处理
            .receive(on: DispatchQueue.main)
            .sink { [weak self] val in
                guard let self = self else { return }
                self.permissionLbl.text = "Status: \(val ? "Granted" : "Denied")"
            }
            .store(in: &subscriptions)

UIViewController逆向传值

当需要从下一个页面传值回当前页面时,Combine 提供了比 delegate 更优雅的方式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 接收值的UIViewController
let nextViewController = NextViewController()
let publisher = PassthroughSubject<String, Never>()
nextViewController.publisher = publisher

subscription = publisher.sink { [weak self] info in
    guard let self = self else { return }
    // 处理info
}

present(nextViewController, animated: true)

// 传递值的UIViewController
var publisher: PassthroughSubject<String, Never>?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    publisher?.send("传值")
    dismiss(animated: true) {
        self.publisher?.send(completion: .finished)
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
聊聊 Combine 和 async/await 之间的合作
在 Xcode 13.2 中,苹果完成了 async/await 的向前部署(Back-deploying)工作,将最低的系统要求降低到了 iOS 13(macOS Catalina),这一举动鼓舞了越来越多的人开始尝试使用 async/await 进行开发。当大家在接触了异步序列(AsyncSequence)后,会发现它同 Combine 的表现有些接近,尤其结合近两年 Combine 框架几乎没有什么变化,不少人都提出了疑问:苹果是否打算使用 AsyncSequence 和 AsyncStream 替代 Combine。
东坡肘子
2022/07/28
9410
Combine 基本概念
订阅者调用request(_:_)来告知愿意接受更多的值,从一个最大的值,到无限制。
小刀c
2022/09/21
3130
Combine-实践
Combine 既可以在 SwiftUI 中使用,也可以在 UIKit 中使用。下面分别实践一下。
YungFan
2020/05/18
1.4K0
Combine-Foundation中的Publisher
为了方便使用,Foundation 为 iOS 开发中的几个常见操作提供了直接获取 Publisher 的方式。
YungFan
2020/03/24
1.3K0
Combine-Subscriber
Publisher 根据 Subscriber 的请求提供数据。如果没有任何订阅请求,Publisher 不会提供任何数据。所以可以这样说,Subscriber负责向 Publisher 请求数据并接收数据(或失败)。
YungFan
2020/04/16
1K0
Combine-Subscriber
基于Combine的响应式UIControl
iOS开发中UIKit中控件的交互方式默认是Target-Action,这种方式简单且直观。不过,一个问题在于编码方式太过于繁琐,需要定义一个方法,然后调用addTartget方式进行绑定;在复杂页面交互,需要跨多级数据传递的时候,就变得异常繁琐。
用户8438817
2023/04/21
1.1K0
iOS开发之网络代码进化史
目前,iOS 原生网络请求数据共有 4 种方式,分别是传统 Completion 回调、Completion 回调 + Result、Combine 框架与Swift Concurrency (async/await)。本文以下载图片为例,详细讲解 4 种网络请求的差异。
YungFan
2025/03/11
1140
Combine-Future
前面我们用过Just,其数据的发布和订阅是同步行为。如果希望数据的发布和订阅是异步的,可以使用Future。Future可以创建一个接收未来数据与事件的 Publisher。Future定义如下:
YungFan
2020/05/20
8360
架构之路 (六) —— VIPER架构模式(二)
源码 1. Swift 首先看下工程组织结构 下面就是源码了 1. SceneDelegate.swift import SwiftUI class SceneDelegate: UIRespond
conanma
2021/09/04
1.3K0
干货 | 深入浅出Apple响应式框架Combine
Combine.framework 是Apple在2019 WWDC 上基于Swift推出的函数响应框架(Functional Reactive Programming),支持Apple全平台的操作系统(iOS13+,macOS 10.15+等)。函数式响应框架无论在哪个平台早已流行泛滥,开源的Rx更是实现了各种语言的响应式编程框架。Apple在这个时候推出响应式框架,无疑是对自己护城河的进一步巩固。事实上SwiftUI的数据驱动就是依赖Combine。
携程技术
2020/11/04
4.5K0
干货 | 深入浅出Apple响应式框架Combine
Combine-Subject
Subject是一种特殊的 Publisher,最大的特点是可以手动发送数据。定义如下:
YungFan
2020/05/09
7470
如何判断 ScrollView、List 是否正在滚动中
判断一个可滚动控件( ScrollView、List )是否处于滚动状态在某些场景下具有重要的作用。比如在 SwipeCell[3] 中,需要在可滚动组件开始滚动时,自动关闭已经打开的侧滑菜单。遗憾的是,SwiftUI 并没有提供这方面的 API 。本文将介绍几种在 SwiftUI 中获取当前滚动状态的方法,每种方法都有各自的优势和局限性。
东坡肘子
2022/12/16
4.1K0
如何判断 ScrollView、List 是否正在滚动中
用Async/Await重建SwiftU的Redux-like状态容器
经过两年多的时间,SwiftUI发展到当前的3.0版本,无论SwiftUI的功能还是Swift语言本身在这段时间里都有了巨大的提升。是时候使用Async/Await来重构我的的状态容器代码了。
东坡肘子
2022/07/28
2K0
用Async/Await重建SwiftU的Redux-like状态容器
Combine-AnyPublisher
Publisher 中的 Output 和 Failure 两个关联类型如果进行多次嵌套会让类型变得非常复杂,难以阅读,而实际开发中往往需要经过多次的操作才能得到合适的 Publisher。 对于 Subscriber 来说,只需要关心 Publisher 的 Output 和 Failure 两个类型就能顺利订阅,它并不需要具体知道这个 Publisher 是如何得到、如何嵌套的。 为了对复杂类型的 Publisher 进行类型抹消,Combine 提供了eraseToAnyPublisher()方法将复
YungFan
2020/05/09
2K0
Combine-Scheduler
如果说 Publisher 决定了发布什么样的 (what) 数据的话,Scheduler(调度器) 所要解决的就是两个问题:在什么地方 (where),以及在什么时候 (when) 来发布数据和接收数据。我们都知道,在 iOS 开发中如果需要更新 UI,需要保证相关操作发生在主线程。在 Combine 中如果数据流前面的 Publisher 是在后台线程进行操作,那么在订阅时,当状态的变化会更新 UI 时,需要将数据流中接收数据的线程切换到主线程。
YungFan
2020/05/18
6010
戴铭的 Swift 小册子
越来越多同学打算开始用 Swift 来开发了,可很多人以前都没接触过 Swift。这篇和我以前文章不同的是,本篇只是面向 Swift 零基础的同学,内容主要是一些直接可用的小例子,例子可以直接在工程中用或自己调试着看。
Swift社区
2021/12/06
2.4K0
戴铭的 Swift 小册子
了解 Swift 调度器
iOS 应用开发中最常见的错误之一是线程错误,当开发者试图从一个闭包中更新用户界面时,会出现这种错误。为了解决这个问题,我们可以使用 DispatchQueue.main 和 threads。
Swift社区
2021/11/26
2.8K0
Swift-MVVM 简单演练(二)
Swift-MVVM 简单演练(一) Swift-MVVM 简单演练(三) Swift-MVVM 简单演练(四) 处理下拉刷新逻辑 根据接口文档,下拉刷新是返回ID比since_id大的微博(即比since_id时间晚的微博)。因此,我们需要在网络请求方法里增加两个参数。since_id和max_id,分别对应下拉刷新所需参数和上拉加载所需参数。 既然要修改网络请求方法,当然是从我们自己抽取的HQNetWorkManager+Extension和HQStatusListViewModel这两个地方入手考虑。
用户1890628
2018/05/10
2.4K0
在 Text 中实现基于关键字的搜索和定位
前些日子,一位网友在聊天室中就如下的 问题[3] 与大家进行了交流与探讨 —— 如何通过 Text + AttributedString 实现类似文章关键字检索的功能,并可通过按钮在搜索结果中进行滚动切换?
东坡肘子
2022/12/16
4.6K0
在 Text 中实现基于关键字的搜索和定位
架构之路 (五) —— VIPER架构模式(一)
VIPER架构模式是MVC或MVVM的另一种选择。虽然SwiftUI和Combine框架创建了一个强大的组合,可以快速构建复杂的ui和在应用程序中移动数据,但它们也面临着各自的挑战和对架构的看法。
conanma
2021/09/04
18.4K0
相关推荐
聊聊 Combine 和 async/await 之间的合作
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验