如何以编程方式从 UICollectionView 中的 "didSelectItemAt" 推送 UIViewController(使用单独的文件)?
How to push a UIViewController programmatically from "didSelectItemAt" in UICollectionView (using separate files)?
我在单独的 swift 文件中设置了一个 UICollectionView,该文件显示在 HomeViewController 上。我想在集合视图单元格 selected 时推送 DetailViewController。我想在没有故事板的情况下以编程方式执行此操作。我一直使用 "navigationController.pushViewController(vc, animated: true)" 推送 ViewController,但我无法从 UICollectionView 的 "didSelectItemAt" 函数中访问 navigationController。如果重要的话,我确实有一个自定义的 UICollectionViewCell 设置并用于单元格。
我怎样才能完成这项工作? collectionView 显示正确,当我 select 一个单元格时,我知道 didSelectItemAt 正在 运行 正如我的打印语句 "Did select item at..." 在控制台中显示的那样。
经过几个小时的谷歌搜索,我无法弄明白。我仍在学习 M-V-C 结构,因此我可能在所有设置方面存在根本缺陷。我还看到我可能需要创建一个自定义委托来处理这个问题,但我觉得我缺少一些更简单的东西,因为 didSelectItemAt 函数就在那里。
这是我的 UICollectionView swift 文件中的相关代码:
class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did select item at...")
// this is where I am trying to push the DetailViewController
}
}
这是我的 HomeViewController:
class HomeViewController: UIViewController {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 30
layout.sectionInset.top = 20
layout.sectionInset.bottom = 20
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = UIColor(named: "background")
cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
return cv
}()
let dataController: HomeDataController = {
let dataController = HomeDataController()
return dataController
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self.dataController
collectionView.delegate = self.dataController
view.addSubview(collectionView)
}
}
class HomeViewController: UIViewController {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 30
layout.sectionInset.top = 20
layout.sectionInset.bottom = 20
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = UIColor(named: "background")
cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
return cv
}()
lazy var dataController: HomeDataController = {
let dataController = HomeDataController(controller: self)
dataController.didSelectionCompletion = { indexPath in
print("Called...")
}
dataController.delegate = self
return dataController
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self.dataController
collectionView.delegate = self.dataController
view.addSubview(collectionView)
}
}
//MARK: - HomeDataControllerDelegate
extension HomeViewController : HomeDataControllerDelegate {
func homeDataController(_ controller: HomeDataController, didSelectItemAt: IndexPath) {
print("Called..")
}
}
HomeDataController.swift
protocol HomeDataControllerDelegate {
func homeDataController(_ controller : HomeDataController, didSelectItemAt : IndexPath)
}
class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
private var controller : UIViewController? = nil
var delegate : HomeDataControllerDelegate? = nil
var didSelectionCompletion : ((IndexPath) -> (Void))? = nil
override init() {
super.init()
}
init(controller : UIViewController) {
super.init()
self.controller = controller
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did select item at...")
// this is where I am trying to push the DetailViewController
/* Method1 - using property*/
let detialController = UIViewController()
controller?.navigationController?.pushViewController(detialController, animated: true)
/* Method2 - delegate */
delegate?.homeDataController(self, didSelectItemAt: indexPath)
/* Method3 - Block */
self.didSelectionCompletion?(indexPath)
}
}
使用方法 1(使用 属性)存在局限性,即 HomeDataController
始终只推送一个细节控制器。它变得依赖 class。还有选项 pass destination controller into init
method of HomeDataController
再次变得更加复杂。但是如果你有修复 detailViewController 那么你可以使用这个方法。但它不是针对任何特定更改请求的可扩展代码。
块和委托是更标准和可扩展的选项。使用这种方法,我们可以完全控制 UIController 和任何操作。
希望对你有所帮助。
我在单独的 swift 文件中设置了一个 UICollectionView,该文件显示在 HomeViewController 上。我想在集合视图单元格 selected 时推送 DetailViewController。我想在没有故事板的情况下以编程方式执行此操作。我一直使用 "navigationController.pushViewController(vc, animated: true)" 推送 ViewController,但我无法从 UICollectionView 的 "didSelectItemAt" 函数中访问 navigationController。如果重要的话,我确实有一个自定义的 UICollectionViewCell 设置并用于单元格。
我怎样才能完成这项工作? collectionView 显示正确,当我 select 一个单元格时,我知道 didSelectItemAt 正在 运行 正如我的打印语句 "Did select item at..." 在控制台中显示的那样。
经过几个小时的谷歌搜索,我无法弄明白。我仍在学习 M-V-C 结构,因此我可能在所有设置方面存在根本缺陷。我还看到我可能需要创建一个自定义委托来处理这个问题,但我觉得我缺少一些更简单的东西,因为 didSelectItemAt 函数就在那里。
这是我的 UICollectionView swift 文件中的相关代码:
class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did select item at...")
// this is where I am trying to push the DetailViewController
}
}
这是我的 HomeViewController:
class HomeViewController: UIViewController {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 30
layout.sectionInset.top = 20
layout.sectionInset.bottom = 20
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = UIColor(named: "background")
cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
return cv
}()
let dataController: HomeDataController = {
let dataController = HomeDataController()
return dataController
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self.dataController
collectionView.delegate = self.dataController
view.addSubview(collectionView)
}
}
class HomeViewController: UIViewController {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 30
layout.sectionInset.top = 20
layout.sectionInset.bottom = 20
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = UIColor(named: "background")
cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
return cv
}()
lazy var dataController: HomeDataController = {
let dataController = HomeDataController(controller: self)
dataController.didSelectionCompletion = { indexPath in
print("Called...")
}
dataController.delegate = self
return dataController
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self.dataController
collectionView.delegate = self.dataController
view.addSubview(collectionView)
}
}
//MARK: - HomeDataControllerDelegate
extension HomeViewController : HomeDataControllerDelegate {
func homeDataController(_ controller: HomeDataController, didSelectItemAt: IndexPath) {
print("Called..")
}
}
HomeDataController.swift
protocol HomeDataControllerDelegate {
func homeDataController(_ controller : HomeDataController, didSelectItemAt : IndexPath)
}
class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
private var controller : UIViewController? = nil
var delegate : HomeDataControllerDelegate? = nil
var didSelectionCompletion : ((IndexPath) -> (Void))? = nil
override init() {
super.init()
}
init(controller : UIViewController) {
super.init()
self.controller = controller
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did select item at...")
// this is where I am trying to push the DetailViewController
/* Method1 - using property*/
let detialController = UIViewController()
controller?.navigationController?.pushViewController(detialController, animated: true)
/* Method2 - delegate */
delegate?.homeDataController(self, didSelectItemAt: indexPath)
/* Method3 - Block */
self.didSelectionCompletion?(indexPath)
}
}
使用方法 1(使用 属性)存在局限性,即 HomeDataController
始终只推送一个细节控制器。它变得依赖 class。还有选项 pass destination controller into init
method of HomeDataController
再次变得更加复杂。但是如果你有修复 detailViewController 那么你可以使用这个方法。但它不是针对任何特定更改请求的可扩展代码。
块和委托是更标准和可扩展的选项。使用这种方法,我们可以完全控制 UIController 和任何操作。
希望对你有所帮助。