iOS页面传值异常:AgentDetailVC至AbilitiesDetailsVC传值为空
iOS页面传值问题排查:AgentDetailVC到AbilitiesDetailsViewController传值为空
问题描述
在iOS开发中,从AgentDetailVC向AbilitiesDetailsViewController传递数据时,所有传递的数据均为nil或空字符串。此前已成功实现AgentListVC到AgentDetailVC的传值,请求排查代码并解决问题。
涉及代码
AgentListVC代码
import UIKit class AgentListVC: UIViewController { var agentsReference = ValorantReferenceApp().agents @IBOutlet var tableView: UITableView! override func viewDidLoad() { self.tableView.rowHeight = 100 tableView.delegate = self tableView.dataSource = self super.viewDidLoad() configureNavigationBar() } //MARK: - Configure Navigation Bar func configureNavigationBar() { self.navigationController?.navigationBar.prefersLargeTitles = true if var textAttributes = navigationController?.navigationBar.titleTextAttributes { textAttributes[NSAttributedString.Key.foregroundColor] = UIColor.red navigationController?.navigationBar.titleTextAttributes = textAttributes } } } //MARK: - Table View Methods extension AgentListVC: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return agentsReference.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! AgentCellVC let agent = agentsReference[indexPath.row] cell.agentNameLAbel.text = agent.name cell.agentImageview.image = agent.iconAgent return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { performSegue(withIdentifier: "toSecondVC", sender: nil) } //MARK: - Prepare Segue override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let destinationVC = segue.destination as! AgentDetailVC if let indexPath = tableView.indexPathForSelectedRow { let agent = agentsReference[indexPath.row] destinationVC.agentDetailVariables.choosenFlagImage = agent.agentFlagImage destinationVC.agentDetailVariables.choosenAgentIconImage = agent.iconAgent destinationVC.agentDetailVariables.choosenAgentType = agent.type.rawValue destinationVC.agentDetailVariables.choosenAgentName = agent.name destinationVC.choosenAgentAbilities = agent.abilities destinationVC.agentDetailVariables.choosenAgentAbilitiesImages = agent.agentAbilitiesImage destinationVC.choosenAgentVideoLink = agent.skillAbilitiesLink } } }
AgentDetailVC代码
import UIKit class AgentDetailVC: UIViewController { @IBOutlet var typeLabel: UILabel! @IBOutlet var characterImageView: UIImageView! @IBOutlet var flagImageView: UIImageView! @IBOutlet var tableView: UITableView! @IBOutlet var agentTypeImageView: UIImageView! var agentDetailVariables = AgentDetailVariables() var agentsReference = ValorantReferenceApp().agents var choosenAgentAbilities = [String]() var viewController = AbilitiesDetailsViewController() var choosenAgentVideoLink = [String]() override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self tableView.dataSource = self viewLoad() print(choosenAgentAbilities) } //MARK: - ViewLoad Function. func viewLoad() { flagImageView.image = agentDetailVariables.choosenFlagImage characterImageView.image = agentDetailVariables.choosenAgentIconImage typeLabel.text = agentDetailVariables.choosenAgentType title = agentDetailVariables.choosenAgentName tableView.rowHeight = 65 tableView.separatorStyle = .none agentTypeImageView.image = UIImage(named: "\(agentDetailVariables.choosenAgentType)") } } //MARK: - TableView Methods extension AgentDetailVC : UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return choosenAgentAbilities.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! AgentDetailsCellVC let agentAbilities = choosenAgentAbilities[indexPath.row] let skillImages = agentDetailVariables.choosenAgentAbilitiesImages[indexPath.row] print(agentAbilities) cell.skillNameLabel.text = agentAbilities cell.skillImageView.image = skillImages return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) performSegue(withIdentifier: "toYoutubeVideos", sender: nil) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "toYoutubeVideos" { let destinationVC = segue.destination as! AbilitiesDetailsViewController if let indexPath = tableView.indexPathForSelectedRow { let agent = agentsReference[indexPath.row] let link = choosenAgentVideoLink[indexPath.row] print(link) destinationVC.agentAbilitiesVideoURL = link destinationVC.choosenAgentSkillName = choosenAgentAbilities[indexPath.row] } } } }
AbilitiesDetailsViewController代码
import UIKit import AVKit import AVFoundation import MediaPlayer import MobileCoreServices import YoutubePlayer_in_WKWebView class AbilitiesDetailsViewController: UIViewController, AVPlayerViewControllerDelegate { @IBOutlet var skillDetailsLabel: UILabel! @IBOutlet var skillNameLabel: UILabel! @IBOutlet var heroIconImageView: UIImageView! var agentAbilitiesVideoURL = "" var choosenAgentSkillName = "" override func viewDidLoad() { skillNameLabel.text = choosenAgentSkillName super.viewDidLoad() } @IBAction func playVideoUsingURL(_ sender: Any) { playGlobalVideo() } func playGlobalVideo() { guard let videoURL = URL(string: agentAbilitiesVideoURL ?? "sad") else { return } let player = AVPlayer(url: videoURL) let vc = AVPlayerViewController() vc.player = player present(vc, animated: true) { player.play() } } func playAbilitiesVideos() { let player = AVPlayer(url: URL(string: "https://assets.contentstack.io/v3/assets/bltb6530b271fddd0b1/bltf4e7a6525fe6ec42/625f2c7cfd9afd4b1fe300ee/C-Prowler_video.mp4")!) let controller = AVPlayerViewController() present(controller, animated: true) { } controller.player = player addChild(controller) view.addSubview(controller.view) controller.view.frame = CGRect(x: 50 , y: 50, width: 300, height: 300) controller.player = player controller.showsPlaybackControls = true player.isClosedCaptionDisplayEnabled = false player.play() } }
结构体代码
struct Agent: Hashable{ let name: String let type: AgentType let origin: String let abilities: [String] let iconAgent : UIImage let agentFlagImage : UIImage let agentAbilitiesImage: [UIImage] let skillAbilitiesLink: [String] } enum AgentType:String{ case controller = "Controller" case sentinel = "Sentinel" case initiator = "Initiator" case duelist = "Duelist" }
ValorantReferenceApp代码
struct ValorantReferenceApp { static var agentIconImages = AgentIconImages() static var agentFlagImages = AgentFlagImages() static var agentAbilitiesImages = AgentAbilitiesImages() var agents: [Agent] = [ Agent(name: "Brimstone", type: .controller, origin: "United States", abilities: ["Incendiary", "Stim Beacon", "Sky Smoke", "Orbital Strike"], iconAgent: agentIconImages.iconBrimstone!, agentFlagImage: agentFlagImages.flagBrimstone!, agentAbilitiesImage: agentAbilitiesImages.abilitiesBrimstone, skillAbilitiesLink: ["https://assets.contentstack.io/v3/assets/bltb6530b271fddd0b1/blte2b9eb1923ef64fa/5ecad7d0f5bd13348a6cac75/Brimstone_Q_v001_web.mp4", "https://assets.contentstack.io/v3/assets/bltb6530b271fddd0b1/bltc34c3d692ea83f41/5ecad7d0177c51692beb1fe4/Brimstone_C_v001_web.mp4", "https://assets.contentstack.io/v3/assets/bltb6530b271fddd0b1/bltcf4359fed083686b/5ecad7d198f79d6925dbee07/Brimstone_E_v001_web.mp4", "https://assets.contentstack.io/v3/assets/bltb6530b271fddd0b1/blt3d19d83ba51eb18f/5ecad7d297b46c1911ad1868/Brimstone_X_v001_web.mp4" ]) ] }
问题根源与修复方案
1. 核心问题:传值时错误获取Agent数据
在AgentDetailVC的prepare(for:sender:)方法中,你错误地通过agentsReference[indexPath.row]获取Agent实例,但这里的indexPath是技能列表的行索引,不是Agent列表的索引。当前AgentDetailVC展示的是单个Agent的技能列表,无需重新从Agent列表中取数据,直接使用已有的choosenAgentVideoLink和choosenAgentAbilities数组即可。
2. 次要问题:字符串可选绑定错误
AbilitiesDetailsViewController的playGlobalVideo()方法中,agentAbilitiesVideoURL是默认空字符串的非可选类型,不需要用?? "sad"进行可选绑定,直接传入即可。
修复后的关键代码
修复AgentDetailVC的prepare(for:sender:)方法
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "toYoutubeVideos" { let destinationVC = segue.destination as! AbilitiesDetailsViewController if let indexPath = tableView.indexPathForSelectedRow { // 直接使用当前VC已保存的技能数据 let link = choosenAgentVideoLink[indexPath.row] print(link) destinationVC.agentAbilitiesVideoURL = link destinationVC.choosenAgentSkillName = choosenAgentAbilities[indexPath.row] } } }
修复AbilitiesDetailsViewController的playGlobalVideo()方法
func playGlobalVideo() { guard let videoURL = URL(string: agentAbilitiesVideoURL) else { print("无效视频链接:\(agentAbilitiesVideoURL)") return } let player = AVPlayer(url: videoURL) let vc = AVPlayerViewController() vc.player = player present(vc, animated: true) { player.play() } }
额外优化建议
- 删除
AgentDetailVC中冗余的var viewController = AbilitiesDetailsViewController()声明,该实例不会被Segue使用,属于无效代码。 - 可以将
agentAbilitiesVideoURL和choosenAgentSkillName改为可选类型(如String?),避免空字符串引发的潜在问题。
内容的提问来源于stack exchange,提问作者7mach
相关产品推荐
相关产品推荐

