You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxSwift结合Alamofire与SwiftyJSON使用问题及代码调试咨询

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)

关键知识点解释

  1. 用Observable.create包装异步操作:
    这个方法让你手动控制Observable的事件发送——请求成功就发送onNext传递解析结果,失败就发送onError,完成后发送onCompleted。同时返回的Disposable可以在订阅销毁时取消网络请求,避免内存泄漏。

  2. 抛弃普通数组,直接在订阅中处理结果:
    不需要维护全局的myArray,因为Rx的理念是通过序列传递数据,订阅者只需要关心序列发送的结果即可,这样代码逻辑更清晰,也避免了状态混乱。

  3. 纠正数组遍历的越界问题:
    你的原代码中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:17:28