从委托方法传递的值是 nil Swift
Value pass from delegate method is nil Swift
我尝试通过委托将数据从一个视图控制器 (ItenaryVC) 发送到另一个视图控制器 (ItenaryFloatingPanelVC)。发起ItenaryVC的VC是DiscoverVC。当 ItenaryVC 加载时,它将进行 API 调用以获取一些数据,我想将从 API 调用接收到的数据传递给我创建的委托,委托将数据传递给ItenaryFloatingPanelVC。但是没有收到数据,它是零。我实际上还使用 FloatingPanel Library 在 ItenaryVC.
中添加面板
流量
发现VC -> ItenaryVC + ItenaryFloatingPanelVC(作为浮动面板)
DiscoverVC.swift
protocol DiscoverVCDelegate : AnyObject {
func didSendSingleLocationData(_ discoverVC : DiscoverVC , location : Location)
}
class DiscoverVC : UIViewController {
//MARK:- IBOutlets
@IBOutlet weak var collectionView: UICollectionView!
weak var delegate : DiscoverVCDelegate?
private var locationResult = [Location]()
private var selectedAtRow : Int!
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
renderView()
getLocations()
}
private func renderView() {
collectionView.register(UINib(nibName: R.nib.discoverCell.name, bundle: nil), forCellWithReuseIdentifier: R.reuseIdentifier.discoverCell.identifier)
collectionView.delegate = self
collectionView.dataSource = self
}
private func getLocations(location : String = "locations") {
NetworkManager.shared.getLocations(for: location) { [weak self] location in
switch location {
case .success(let locations):
self?.updateDiscoverUI(with: locations)
case .failure(let error):
print(error.rawValue)
}
}
}
private func updateDiscoverUI(with locations : [Location]) {
DispatchQueue.main.async { [weak self] in
self?.locationResult.append(contentsOf: locations)
self?.collectionView.reloadData()
}
}
}
//MARK:- Delegate
extension DiscoverVC : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedAtRow = indexPath.row
self.performSegue(withIdentifier: R.segue.discoverVC.goToDetails, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destinationVC = segue.destination as? ItenaryVC else { return}
destinationVC.locationDetails = locationResult[selectedAtRow]
destinationVC.imageURL = locationResult[selectedAtRow].image
destinationVC.getItenaries(at: locationResult[selectedAtRow].itenaryName)
delegate?.didSendSingleLocationData(self, location: locationResult[selectedAtRow])
// Remove tab bar when push to other vc
destinationVC.hidesBottomBarWhenPushed = true
}
}
ItenaryVC.swift
import UIKit
import FloatingPanel
protocol ItenaryVCDelegate : AnyObject {
func didSendItenaryData(_ itenaryVC : ItenaryVC, with itenary : [[Days]])
}
class ItenaryVC: UIViewController {
@IBOutlet weak var backgroundImage: UIImageView!
var imageURL : URL!
var locationDetails: Location! {
didSet {
getItenaries(at: locationDetails.itenaryName)
}
}
weak var delegate : ItenaryVCDelegate?
var itenaries = [[Days]]()
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
setupCard()
setupView()
}
func getItenaries(at itenaries : String = "Melaka"){
NetworkManager.shared.getItenaries(for: itenaries) { [weak self] itenary in
switch itenary {
case .success(let itenary):
// print(itenary)
DispatchQueue.main.async {
self?.itenaries.append(contentsOf: itenary)
self?.delegate?.didSendItenaryData(self! , with: itenary)
}
print(itenaries.count)
case .failure(let error):
print(error.rawValue)
}
}
}
}
//MARK:- Private methods
extension ItenaryVC {
private func setupView() {
backgroundImage.downloaded(from: imageURL)
backgroundImage.contentMode = .scaleAspectFill
}
private func setupCard() {
guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFloatingPanelVC else { return}
let fpc = FloatingPanelController()
fpc.set(contentViewController: itenaryFlotingPanelVC)
fpc.addPanel(toParent: self)
}
}
ItenaryFloatingPanelVC.swift
import UIKit
class ItenaryFloatingPanelVC: UIViewController{
//MARK:- Outlets
@IBOutlet weak var sloganLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var locDesc: UITextView!
@IBOutlet weak var itenaryTableView: UITableView!
@IBOutlet weak var locDescHC: NSLayoutConstraint!
var itenaries = [[Days]]()
let itenaryVC = ItenaryVC()
let discoverVC = DiscoverVC()
override func viewDidLoad() {
discoverVC.delegate = self
itenaryVC.delegate = self
itenaryTableView.dataSource = self
itenaryTableView.delegate = self
locDescHC.constant = locDesc.contentSize.height
itenaryTableView.register(UINib(nibName: R.nib.itenaryCell.name, bundle: nil), forCellReuseIdentifier: R.nib.itenaryCell.identifier)
}
}
//MARK:- DiscoverVCDelegate
extension ItenaryFloatingPanelVC : DiscoverVCDelegate {
func didSendSingleLocationData(_ discoverVC: DiscoverVC, location: Location) {
print(location)
locationLabel.text = location.locationName
}
}
//MARK:- ItenaryVC Delegate
extension ItenaryFloatingPanelVC : ItenaryVCDelegate {
func didSendItenaryData(_ itenaryVC: ItenaryVC, with itenary: [[Days]]) {
DispatchQueue.main.async {
print(itenary)
self.itenaries.append(contentsOf: itenary)
self.itenaryTableView.reloadData()
print("itenary \(self.itenaries.count)")
}
}
}
ItenaryVC 和 ItenaryFloatingPanel 的图像
我没看到你在 ItenaryVC
给 getItenaries()
打电话。请再次检查。
您的代码不起作用,因为您设置了新创建的 ItenaryVC
实例的委托:
let itenaryVC = ItenaryVC()
// ...
itenaryVC.delegate = self
itenaryVC
这里不是呈现self
的VC,而是ItenaryFloatingPanelVC
。这是你创造的一个全新的。
您可以在 ItenaryVC
中设置代表,而不是那样做,当您即将呈现 ItenaryFloatingPanelVC
:
private func setupCard() {
guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFloatingPanelVC else { return }
let fpc = FloatingPanelController()
// here!
self.delegate = itenaryFlotingPanelVC
fpc.set(contentViewController: itenaryFlotingPanelVC)
fpc.addPanel(toParent: self)
}
self
现在是 ItenaryVC
,而 itenaryFlotingPanelVC
是 self
正在呈现的 VC。
我尝试通过委托将数据从一个视图控制器 (ItenaryVC) 发送到另一个视图控制器 (ItenaryFloatingPanelVC)。发起ItenaryVC的VC是DiscoverVC。当 ItenaryVC 加载时,它将进行 API 调用以获取一些数据,我想将从 API 调用接收到的数据传递给我创建的委托,委托将数据传递给ItenaryFloatingPanelVC。但是没有收到数据,它是零。我实际上还使用 FloatingPanel Library 在 ItenaryVC.
中添加面板流量
发现VC -> ItenaryVC + ItenaryFloatingPanelVC(作为浮动面板)
DiscoverVC.swift
protocol DiscoverVCDelegate : AnyObject {
func didSendSingleLocationData(_ discoverVC : DiscoverVC , location : Location)
}
class DiscoverVC : UIViewController {
//MARK:- IBOutlets
@IBOutlet weak var collectionView: UICollectionView!
weak var delegate : DiscoverVCDelegate?
private var locationResult = [Location]()
private var selectedAtRow : Int!
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
renderView()
getLocations()
}
private func renderView() {
collectionView.register(UINib(nibName: R.nib.discoverCell.name, bundle: nil), forCellWithReuseIdentifier: R.reuseIdentifier.discoverCell.identifier)
collectionView.delegate = self
collectionView.dataSource = self
}
private func getLocations(location : String = "locations") {
NetworkManager.shared.getLocations(for: location) { [weak self] location in
switch location {
case .success(let locations):
self?.updateDiscoverUI(with: locations)
case .failure(let error):
print(error.rawValue)
}
}
}
private func updateDiscoverUI(with locations : [Location]) {
DispatchQueue.main.async { [weak self] in
self?.locationResult.append(contentsOf: locations)
self?.collectionView.reloadData()
}
}
}
//MARK:- Delegate
extension DiscoverVC : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedAtRow = indexPath.row
self.performSegue(withIdentifier: R.segue.discoverVC.goToDetails, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destinationVC = segue.destination as? ItenaryVC else { return}
destinationVC.locationDetails = locationResult[selectedAtRow]
destinationVC.imageURL = locationResult[selectedAtRow].image
destinationVC.getItenaries(at: locationResult[selectedAtRow].itenaryName)
delegate?.didSendSingleLocationData(self, location: locationResult[selectedAtRow])
// Remove tab bar when push to other vc
destinationVC.hidesBottomBarWhenPushed = true
}
}
ItenaryVC.swift
import UIKit
import FloatingPanel
protocol ItenaryVCDelegate : AnyObject {
func didSendItenaryData(_ itenaryVC : ItenaryVC, with itenary : [[Days]])
}
class ItenaryVC: UIViewController {
@IBOutlet weak var backgroundImage: UIImageView!
var imageURL : URL!
var locationDetails: Location! {
didSet {
getItenaries(at: locationDetails.itenaryName)
}
}
weak var delegate : ItenaryVCDelegate?
var itenaries = [[Days]]()
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
setupCard()
setupView()
}
func getItenaries(at itenaries : String = "Melaka"){
NetworkManager.shared.getItenaries(for: itenaries) { [weak self] itenary in
switch itenary {
case .success(let itenary):
// print(itenary)
DispatchQueue.main.async {
self?.itenaries.append(contentsOf: itenary)
self?.delegate?.didSendItenaryData(self! , with: itenary)
}
print(itenaries.count)
case .failure(let error):
print(error.rawValue)
}
}
}
}
//MARK:- Private methods
extension ItenaryVC {
private func setupView() {
backgroundImage.downloaded(from: imageURL)
backgroundImage.contentMode = .scaleAspectFill
}
private func setupCard() {
guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFloatingPanelVC else { return}
let fpc = FloatingPanelController()
fpc.set(contentViewController: itenaryFlotingPanelVC)
fpc.addPanel(toParent: self)
}
}
ItenaryFloatingPanelVC.swift
import UIKit
class ItenaryFloatingPanelVC: UIViewController{
//MARK:- Outlets
@IBOutlet weak var sloganLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var locDesc: UITextView!
@IBOutlet weak var itenaryTableView: UITableView!
@IBOutlet weak var locDescHC: NSLayoutConstraint!
var itenaries = [[Days]]()
let itenaryVC = ItenaryVC()
let discoverVC = DiscoverVC()
override func viewDidLoad() {
discoverVC.delegate = self
itenaryVC.delegate = self
itenaryTableView.dataSource = self
itenaryTableView.delegate = self
locDescHC.constant = locDesc.contentSize.height
itenaryTableView.register(UINib(nibName: R.nib.itenaryCell.name, bundle: nil), forCellReuseIdentifier: R.nib.itenaryCell.identifier)
}
}
//MARK:- DiscoverVCDelegate
extension ItenaryFloatingPanelVC : DiscoverVCDelegate {
func didSendSingleLocationData(_ discoverVC: DiscoverVC, location: Location) {
print(location)
locationLabel.text = location.locationName
}
}
//MARK:- ItenaryVC Delegate
extension ItenaryFloatingPanelVC : ItenaryVCDelegate {
func didSendItenaryData(_ itenaryVC: ItenaryVC, with itenary: [[Days]]) {
DispatchQueue.main.async {
print(itenary)
self.itenaries.append(contentsOf: itenary)
self.itenaryTableView.reloadData()
print("itenary \(self.itenaries.count)")
}
}
}
ItenaryVC 和 ItenaryFloatingPanel 的图像
我没看到你在 ItenaryVC
给 getItenaries()
打电话。请再次检查。
您的代码不起作用,因为您设置了新创建的 ItenaryVC
实例的委托:
let itenaryVC = ItenaryVC()
// ...
itenaryVC.delegate = self
itenaryVC
这里不是呈现self
的VC,而是ItenaryFloatingPanelVC
。这是你创造的一个全新的。
您可以在 ItenaryVC
中设置代表,而不是那样做,当您即将呈现 ItenaryFloatingPanelVC
:
private func setupCard() {
guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFloatingPanelVC else { return }
let fpc = FloatingPanelController()
// here!
self.delegate = itenaryFlotingPanelVC
fpc.set(contentViewController: itenaryFlotingPanelVC)
fpc.addPanel(toParent: self)
}
self
现在是 ItenaryVC
,而 itenaryFlotingPanelVC
是 self
正在呈现的 VC。