RxSwift结合Alamofire与SwiftyJSON使用问题及代码调试咨询
看起来你已经摸到了RxSwift的门,但在响应式思维上有点走偏了——咱们先拆解下你的问题,再一步步修正实现方式。
核心问题分析
你当前代码的问题出在这行:
let myObserver = Observable.from(myArray)
Observable.from创建的是冷Observable序列:它会在你订阅的瞬间,把当前myArray里的所有元素(此时是空数组)一次性发送出去,紧接着就触发completed事件。而普通的Swift数组不是响应式容器,后续你对myArray的修改(比如解析完成后append元素),这个Observable根本感知不到——这就是为什么你看到completed立刻执行,后续数组更新却没触发订阅的原因。
RxSwift的核心价值,是把异步操作(比如网络请求)包装成可订阅的Observable序列,让你在订阅的回调里处理异步结果,而不是用传统闭包修改普通变量再试图监听它。
正确实现方式
我们需要把「网络请求+JSON解析」的整个异步流程,完整包装成一个Observable<[People]>序列,然后通过订阅这个序列来获取解析好的数据。
完整代码示例
import RxSwift import Alamofire import SwiftyJSON // 先确保你的People结构定义正确 struct People { var name: String = "" var job: String = "" } let disposeBag = DisposeBag() // 1. 把网络请求+解析逻辑包装成Observable<[People]> let fetchPeopleObservable = Observable<[People]>.create { observer in guard let requestURL = URL(string: "https://api.myjson.com/bins/e5gjk") else { // URL无效时,发送错误事件 let invalidURLError = NSError( domain: "RequestError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求URL"] ) observer.onError(invalidURLError) return Disposables.create() } // 发起Alamofire请求 let request = Alamofire.request(requestURL, method: .get) .validate() // 自动验证HTTP状态码 .responseJSON { response in switch response.result { case .success(let rawJSON): let json = JSON(rawJSON) var peopleList = [People]() // 注意:这里要用0..<count,避免数组越界(你的原代码用0...会报错) for index in 0..<json["employees"].count { var person = People() person.name = json["employees"][index]["firstName"].stringValue person.job = json["employees"][index]["job"].stringValue peopleList.append(person) } // 解析完成,发送结果给订阅者 observer.onNext(peopleList) // 发送完成事件,标记序列结束 observer.onCompleted() case .failure(let error): // 请求失败,发送错误事件 observer.onError(error) } } // 返回一个Disposable,用于在订阅销毁时取消请求 return Disposables.create { request.cancel() } } // 2. 订阅这个Observable,处理结果 fetchPeopleObservable .subscribe( onNext: { peopleArray in // 这里拿到解析好的完整数组,做你需要的业务操作 print("解析完成,共获取到\(peopleArray.count)条数据:") for person in peopleArray { print("姓名:\(person.name),职位:\(person.job)") } }, onError: { error in print("请求或解析出错:\(error.localizedDescription)") }, onCompleted: { print("请求与解析流程已完成") }, onDisposed: { print("订阅已销毁") } ) .disposed(by: disposeBag)
关键知识点解释
用
Observable.create包装异步操作:
这个方法让你手动控制Observable的事件发送——请求成功就发送onNext传递解析结果,失败就发送onError,完成后发送onCompleted。同时返回的Disposable可以在订阅销毁时取消网络请求,避免内存泄漏。抛弃普通数组,直接在订阅中处理结果:
不需要维护全局的myArray,因为Rx的理念是通过序列传递数据,订阅者只需要关心序列发送的结果即可,这样代码逻辑更清晰,也避免了状态混乱。纠正数组遍历的越界问题:
你的原代码中for i in 0...json["employees"].count会导致索引越界,因为数组的有效索引范围是0到count-1,所以要用0..<json["employees"].count。
对你疑问的解答
我认为Rx的作用应该是在解析完成后,在onNext中使用数据,对吗?
完全正确!RxSwift的核心就是把异步操作转化为可订阅的序列,让你在onNext中处理异步返回的结果,onError处理异常,onCompleted标记流程结束,以此替代传统的回调嵌套,让代码更易读、易维护。
或者,是否应该将整个JSON处理和解析放在onNext中?
不是把解析放在订阅的onNext里,而是把「请求+解析」的整个过程包装成Observable,当解析完成后,把结果通过onNext发送给订阅者——订阅者的onNext只负责接收结果并做业务处理,这样职责更清晰。
内容的提问来源于stack exchange,提问作者screenMonkey MonkeyMan

