英文:
Delegate not working, data isn't being passed to view controller from selecting cell
问题
Movie Library VC
protocol LibraryVCDelegate {
func didGetMovie(movie: String)
}
var movieDelegate: LibraryVCDelegate!
// 当点击单元格时,打印电影的URL图像
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let movieName = dataSource.itemIdentifier(for: indexPath) else {
return
}
movieDelegate.didGetMovie(movie: movieName.image.original)
print(movieName.image.original)
let detailsVC = DetailsViewController()
let navController = UINavigationController(rootViewController: detailsVC)
present(navController, animated: true)
}
Movie DetailsVC
// ViewDidLoad 中获取委托
let libraryVC = LibraryVC()
libraryVC.movieDelegate = self
extension DetailsViewController: LibraryVCDelegate {
func didGetMovie(movie: String) {
movieImage.image = UIImage(named: movie)
}
}
接收到 nil 并且数据没有被传递。
英文:
I have a movie app that fetches an API and I'm trying to get set the movie image on the other view controller when I click on the cell. But the delegate is coming back as nil and nothing is happening.
If anyone knows how to fix this please help me out!
Movie Library VC
protocol LibraryVCDelegate {
func didGetMovie(moive: String)
}
var movieDelegate: LibraryVCDelegate!
//Movie tapped, prints out the movie URL Image
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let movieName = dataSource.itemIdentifier(for: indexPath) else {
return
}
movieDelegate.didGetMovie(moive: movieName.image.original)
print(movieName.image.original)
let detailsVC = DetailsViewController()
let navController = UINavigationController(rootViewController: detailsVC)
present(navController, animated: true)
}
Movie DetailsVC
// View did load I'm getting the delegate
let librayVC = LibraryVC()
librayVC.movieDelegate = self
//
extension DetailsViewController: LibraryVCDelegate {
func didGetMovie(moive: String) {
movieImage.image = UIImage(named: moive)
}
}
Receiving nil and data isn't being passed.
答案1
得分: 1
通常我们应该在ViewController B上创建协议函数,并通过代理将任何更新的UI值传递给ViewController A。例如,考虑LibraryVC作为A,DetailsVC作为B。因此,您需要在DetailsVC上定义如下协议:
protocol DetailsVCDelegate: AnyObject {
func didGetMovie(movie: String)
}
然后声明代理变量:
weak var delegate: DetailsVCDelegate?
然后在需要的地方触发它:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.didGetMovie(movie: movieName.image.original)
}
但在定义协议函数之前,您应该在ViewController A上进行如下扩展:
extension LibraryViewController: DetailsVCDelegate {
func didGetMovie(movie: String) {
movieImage.image = UIImage(named: movie)
}
}
然后,您应该在导航过程中分配权限给ViewController A,即LibraryVC:
let details = DetailsVC()
details.delegate = self
这是在两个视图控制器之间传递任何值的正确方式。但在您的情况下,我认为您想要在DetailsViewController上更新电影名称,而不是在库视图控制器上。因此,您应该通过在DetailsViewController上创建自定义初始化器来传递数据:
class DetailsViewController: UIViewController {
var imageName: String?
// 这是一种方便的方法来创建这个视图控制器,不带有imageName
convenience init() {
self.init(imageName: nil)
}
init(image: String?) {
self.imageName = imageName
super.init(nibName: nil, bundle: nil)
}
// 如果这个视图控制器是从故事板加载的,imageName将为nil
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
movieImage.image = UIImage(named: self.imageName)
}
}
英文:
Normally we should create protocol functions on ViewController B and should pass any updated UI value via delegates to ViewController A. For example consider LibraryVC as A, DetailsVC as B. So you need define protocols on DetailsVC like below,
protocol DetailsVCDelegate: AnyObject {
func didGetMovie(movie: String)
}
Then declare delegate variable.
weak var delegate: DetailsVCDelegate?
Then triggered it where you need it.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.didGetMovie(movie: movieName.image.original)
}
But before you defined that protocol function on ViewController A.
extension LibraryViewController: DetailsVCDelegate {
func didGetMovie(movie: String) {
movieImage.image = UIImage(named: moive)
}
}
And you should assign power during your navigation process on ViewController A as LibraryVC,
let details = DetailsVC()
details.delegate = self
This the proper way of passing any values between two view controllers. But in your case seems in your code, I think you want to update movies name on DetailsViewController instead of library view controller. So you should pass data by creating custom initialiser on DetailsViewController.
class DetailsViewController: UIViewController {
var imageName: String?
// this is a convenient way to create this view controller without a imageName
convenience init() {
self.init(imageName: nil)
}
init(image: String?) {
self.imageName = imageName
super.init(nibName: nil, bundle: nil)
}
// if this view controller is loaded from a storyboard, imageName will be nil
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
override func viewDidLoad() {
super.viewDidLoad()
movieImage.image = UIImage(named: self.imageName)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论