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

如何在Alamofire请求完成后返回DataModel并传递至ViewController供segue使用

实现方案:异步回调传值

最直接的实现方式是用逃逸闭包做异步回调,把请求得到的PlayerModel实例回传给主ViewController,再通过segue传递到目标页面,具体步骤如下:


步骤1:修改PlayerRequestManager的请求方法,添加回调参数

给fetchPlayerByName新增逃逸闭包作为完成回调,请求完成后无论成功失败都通过闭包把结果回传给调用方:

class PlayerRequestManager {
    let baseURL = "https://public-api.tracker.gg/v2/csgo/standard/profile/steam/"
    
    // 新增completion回调,@escaping标记为逃逸闭包,参数为Result枚举区分成功/失败状态
    func fetchPlayerByName(_ playerName: String, completion: @escaping (Result<PlayerModel, Error>) -> Void) {
        let headers : HTTPHeaders = [
            "TRN-Api-Key": "my secret api key",
            "Accept": "application/json",
            "Accept-Encoding": "gzip"
        ]
        
        let fullURL = "\(baseURL)\(playerName)"
        
        AF.request("\(fullURL)", headers: headers).response {
            (responseData) in
            guard let data = responseData.data else {
                // 无返回数据时回调错误
                completion(.failure(NSError(domain: "PlayerRequestError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无返回数据"])))
                return
            }
            
            do{
                let player = try JSONDecoder().decode(PlayerData.self, from: data)
                let playerObject = PlayerModel(playerUsername: player.data.platformInfo.platformUserHandle ?? "Error loading data", playerUserID: player.data.platformInfo.platformUserId ?? "Error loading data", avatarURL: player.data.platformInfo.avatarUrl ?? "Error loading data", playerTimePlayed: player.data.segments[0].stats.timePlayed.displayValue ?? "Error loading data", playerKills: player.data.segments[0].stats.kills.displayValue ?? "Error loading data", playerDeaths: player.data.segments[0].stats.deaths.displayValue ?? "Error loading data", playerKD: player.data.segments[0].stats.kd.displayValue ?? "Error loading data", playerDamage: player.data.segments[0].stats.damage.displayValue ?? "Error loading data", playerHeadshots: player.data.segments[0].stats.headshots.displayValue ?? "Error loading data", playerShotsFired: player.data.segments[0].stats.shotsFired.displayValue ?? "Error loading data", playerShotsHit: player.data.segments[0].stats.shotsHit.displayValue ?? "Error loading data", playerShotsAccuracy: player.data.segments[0].stats.shotsAccuracy.displayValue ?? "Error loading data", playerHeadshotPct: player.data.segments[0].stats.headshotPct.displayValue ?? "Error loading data", playerMaychesPlayed: player.data.segments[0].stats.matchesPlayed.displayValue ?? "Error loading data", playerWins: player.data.segments[0].stats.wins.displayValue ?? "Error loading data", playerLosses: player.data.segments[0].stats.losses.displayValue ?? "Error loading data", playerTies: player.data.segments[0].stats.ties.displayValue ?? "Error loading data", playerMVPs: player.data.segments[0].stats.mvp.displayValue ?? "Error loading data", playerMoneyEarned: player.data.segments[0].stats.moneyEarned.displayValue ?? "Error loading data", playerBombsPlanted: player.data.segments[0].stats.bombsPlanted.displayValue ?? "Error loading data", playerBombsDefused: player.data.segments[0].stats.bombsDefused.displayValue ?? "Error loading data", playerHostagesRescued: player.data.segments[0].stats.hostagesRescued.displayValue ?? "Error loading data", playerRoundsPlayed: player.data.segments[0].stats.roundsPlayed.displayValue ?? "Error loading data", playerWLPercentage: player.data.segments[0].stats.wlPercentage.displayValue ?? "Error loading data")
                // 解码成功,回调player实例
                completion(.success(playerObject))
            }catch {
                // 解码失败,回调错误信息
                completion(.failure(error))
            }
        }
    }
}

步骤2:主ViewController接收回调,存储数据并触发跳转

首先在主ViewController中声明一个全局存储属性,用于后续segue传值:

// 主ViewController新增属性,存储请求到的玩家数据
var targetPlayer: PlayerModel?

修改搜索按钮点击逻辑,调用请求方法时接收回调,拿到数据后触发跳转:

@IBAction func searchButtonPressed(_ sender: Any) {
    guard let searchedName = searchField.text, !searchedName.isEmpty else {
        print("no name entered.")
        return
    }
    playerRequestManager.fetchPlayerByName(searchedName) { [weak self] result in
        // 切到主队列执行UI相关操作,避免线程错误
        DispatchQueue.main.async {
            guard let self = self else { return }
            switch result {
            case .success(let playerObject):
                // 把请求到的玩家对象赋值给全局属性
                self.targetPlayer = playerObject
                // 触发segue跳转,替换为你自己定义的segue标识符
                self.performSegue(withIdentifier: "JumpToPlayerDetailSegue", sender: nil)
            case .failure(let error):
                print("请求失败: \(error.localizedDescription)")
                // 可在这里添加用户可见的错误提示
            }
        }
    }
}

重写主ViewController的prepare(for:sender:)方法,把数据传递给目标ViewController:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // 匹配segue标识符,避免误处理其他跳转
    if segue.identifier == "JumpToPlayerDetailSegue" {
        // 替换为你的目标页面类名
        guard let detailVC = segue.destination as? PlayerDetailViewController else { return }
        // 把存储的玩家对象赋值给目标页面对应属性
        detailVC.receivedPlayer = self.targetPlayer
    }
}

其他可选实现方式

  • 代理模式:给PlayerRequestManager定义代理协议,主ViewController作为代理接收回调,适合回调逻辑多、场景复杂的项目
  • 通知中心:通过NotificationCenter发送携带player对象的通知,主VC监听通知接收数据,适合一对多数据传递的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:24:03