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

使用Alamofire、SwiftJSON配合@escaping闭包解析数据并加载至TableView

实现方案

第一步:定义测试用轻量数据模型

你当前方法声明的回调返回[WelcomeElement],首先要定义对应层级的模型结构存储解析出的字段,测试阶段可以只保留你需要用到的属性即可:

// 下注选项模型
struct Outcome {
    let name: String
    let coefficient: String
}

// 下注类型模型
struct BetType {
    let name: String
    let outcomesCounter: Int?
    let outcomes: [Outcome]
}

// 赛事模型
struct Event {
    let team1: String
    let team2: String
    let score1: String
    let score2: String
    let betTypes: [BetType]
}

// 联赛模型
struct League {
    let name: String
    let events: [Event]
}

// 根元素模型 对应你方法中的WelcomeElement
struct WelcomeElement {
    let name: String
    let betTypes: [BetType]
    let leagues: [League]
}

第二步:修改网络请求解析逻辑

你原有代码中遍历拿到的字段没有做存储,且存在循环变量重名、强制解析容易崩溃的问题,修改后的代码如下:

class Network {
    let baseUrl = URL(string:"https://ppbet-327310.appspot.com/api/games")
    func getCity(completion: @escaping([WelcomeElement]) -> ()) {
        guard let url = baseUrl else {
            completion([])
            return
        }
        AF.request(url, method: .get).responseJSON { (response) in
            switch response.result {
            case .success:
                guard let data = response.data else {
                    completion([])
                    return
                }
                // 替换强制解析为do-catch捕获错误
                do {
                    let json = try JSON(data: data)
                    var resultArray = [WelcomeElement]()
                    let arrayCount = json.array?.count ?? 0
                    // 遍历根数组
                    for rootIndex in 0..<arrayCount {
                        let rootItem = json[rootIndex]
                        let gameName = rootItem["name"].string ?? "N/A"
                        
                        // 解析根层级betTypes
                        var rootBetTypes = [BetType]()
                        if let betTypesArr = rootItem["betTypes"].array {
                            for betIndex in 0..<betTypesArr.count {
                                let betItem = betTypesArr[betIndex]
                                let outcomesCounter = betItem["outcomesCounter"].int
                                let betName = betItem["name"].string ?? "未知下注类型"
                                // 解析下注选项
                                var outcomes = [Outcome]()
                                if let outcomesArr = betItem["outcomes"].array {
                                    for outcomeIndex in 0..<outcomesArr.count {
                                        let outcomeItem = outcomesArr[outcomeIndex]
                                        let outcomeName = outcomeItem["name"].string ?? "未知选项"
                                        let coefficient = outcomeItem["coefficient"].string ?? "1.0"
                                        outcomes.append(Outcome(name: outcomeName, coefficient: coefficient))
                                    }
                                }
                                rootBetTypes.append(BetType(name: betName, outcomesCounter: outcomesCounter, outcomes: outcomes))
                            }
                        }
                        
                        // 解析联赛数组
                        var leagues = [League]()
                        if let leaguesArr = rootItem["leagues"].array {
                            for leagueIndex in 0..<leaguesArr.count {
                                let leagueItem = leaguesArr[leagueIndex]
                                let leagueName = leagueItem["name"].string ?? "未知联赛"
                                // 解析赛事数组
                                var events = [Event]()
                                if let eventsArr = leagueItem["events"].array {
                                    for eventIndex in 0..<eventsArr.count {
                                        let eventItem = eventsArr[eventIndex]
                                        let team1 = eventItem["team1"].string ?? "未知队伍1"
                                        let team2 = eventItem["team2"].string ?? "未知队伍2"
                                        let score1 = eventItem["score1"].string ?? "0"
                                        let score2 = eventItem["score2"].string ?? "0"
                                        // 解析赛事下注类型
                                        var eventBetTypes = [BetType]()
                                        if let eventBetArr = eventItem["betTypes"].array {
                                            for eventBetIndex in 0..<eventBetArr.count {
                                                let eventBetItem = eventBetArr[eventBetIndex]
                                                let betName = eventBetItem["name"].string ?? "未知下注类型"
                                                // 解析下注选项
                                                var outcomes = [Outcome]()
                                                if let outcomesArr = eventBetItem["outcomes"].array {
                                                    for outcomeIndex in 0..<outcomesArr.count {
                                                        let outcomeItem = outcomesArr[outcomeIndex]
                                                        let outcomeName = outcomeItem["name"].string ?? "未知选项"
                                                        let coefficient = outcomeItem["coefficient"].string ?? "1.0"
                                                        outcomes.append(Outcome(name: outcomeName, coefficient: coefficient))
                                                    }
                                                }
                                                eventBetTypes.append(BetType(name: betName, outcomesCounter: nil, outcomes: outcomes))
                                            }
                                        }
                                        events.append(Event(team1: team1, team2: team2, score1: score1, score2: score2, betTypes: eventBetTypes))
                                    }
                                }
                                leagues.append(League(name: leagueName, events: events))
                            }
                        }
                        // 组装根元素加入结果数组
                        let element = WelcomeElement(name: gameName, betTypes: rootBetTypes, leagues: leagues)
                        resultArray.append(element)
                    }
                    DispatchQueue.main.async {
                        completion(resultArray)
                    }
                } catch {
                    print("JSON解析错误:\(error)")
                    DispatchQueue.main.async {
                        completion([])
                    }
                }
            case .failure(let error):
                print("请求错误:\(error)")
                DispatchQueue.main.async {
                    completion([])
                }
            }
        }
    }
}

第三步:ViewController中接收数据渲染TableView

  1. 首先在ViewController中声明数据源数组和TableView相关属性:
class GameListViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    // 存储解析后的完整数据
    var gameDataList = [WelcomeElement]()
    // 如果需要平铺开展示所有赛事,可以额外声明一个赛事数组
    var allEvents = [Event]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        // 发起网络请求
        loadData()
    }
    
    private func loadData() {
        Network().getCity { [weak self] result in
            guard let self = self else { return }
            self.gameDataList = result
            // 如果需要展示所有赛事,遍历组装赛事数组
            self.allEvents = result.flatMap { $0.leagues.flatMap { $0.events } }
            // 刷新列表
            self.tableView.reloadData()
        }
    }
}
  1. 实现TableView数据源方法,按需展示对应层级的数据即可,以平开展示所有赛事为例:
extension GameListViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return allEvents.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "GameCell", for: indexPath) as! GameCell
        let event = allEvents[indexPath.row]
        cell.team1Label.text = event.team1
        cell.team2Label.text = event.team2
        cell.scoreLabel.text = "\(event.score1) : \(event.score2)"
        return cell
    }
}

内容的提问来源于stack exchange,提问作者Pavel Zaruckov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:54:00