[英]How to send clicked item of Table View to other view controller when datasource and delegate are separate from View Controller
我是來自Android背景的iOS初學者,並且剛剛了解了表視圖(對我來說,這是一個Android ListView)。 我正在嘗試從視圖控制器中分離數據源和委托。 我找到了一些有關如何執行此操作的教程,但仍堅持弄清楚如何將單擊的項目發送到另一個視圖控制器。 代碼如下:
class PictureTableViewController: UIViewController {
@IBOutlet weak var pictureTableView: UITableView!
private let picsDataSource: PicturesDataSource
required init?(coder aDecoder: NSCoder) {
self.picsDataSource = PicturesDataSource()
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
pictureTableView.dataSource = picsDataSource
pictureTableView.reloadData()
pictureTableView.delegate = picsDataSource
}
}
class PicturesDataSource: NSObject, UITableViewDataSource, UITableViewDelegate{
private var pictureModels = [PictureModel]()
override init(){
let picModelsDataController = PictureModelsDataController()
pictureModels = picModelsDataController.pictureModels
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pictureModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PictureCell.self)) as! PictureCell
let picModel = pictureModels[indexPath.row]
cell.pictureName = picModel.pictureName
cell.imageItem = picModel.imageItem
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//1 - try loading the "Detail" view controller and typecasting it to be DetailViewController
if let detailViewController = storyboard.instantiateViewController(withIdentifier: "PictureDetailView") as? PictureDetailViewController {
//2 - success! set its selecteImage property
detailViewController.selectedImgName = pictureModels[indexPath.row].pictureName
//3 - now push it onto the navigation controller
navigationController?.pushViewController(detailViewController, animated: true)
}
}
}
Error in: func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ }
。 由於PicturesDataSource類中沒有“ storyboard”和“ navigationController”,如何將單擊的項目(圖片名稱)發送到DetailsViewController
有關於分離數據源和委托的StackOverflow答案,但沒有解決我的問題。
使用:Xcode 8.3 beta 6
您可以在表視圖事件處理程序中包含對主視圖控制器的引用。 以下是我從您的示例中得出的游樂場代碼:
import UIKit
// MARK: - Model
struct Picture {
let title: String
let image: UIImage
}
struct PictureModelsDataSource {
let pictures = [
Picture(title: "exampleTitle", image: UIImage(named: "exampleImage")!),
Picture(title: "exampleTitle", image: UIImage(named: "exampleImage")!)
]
}
// MARK - View
class PictureCell: UITableViewCell {
@IBOutlet weak var pictureTitleLabel: UILabel!
@IBOutlet weak var pictureImage: UIImageView!
}
// MARK: - Controller
class PictureTableViewController: UIViewController {
// MARK: - Properties
@IBOutlet weak var pictureTableView: UITableView!
private var pictureListController: PictureListController?
// MARK: - View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
pictureListController = PictureListController()
pictureListController?.viewController = self
pictureTableView.dataSource = pictureListController
pictureTableView.delegate = pictureListController
pictureTableView.reloadData()
}
}
class PictureDetailViewController: UIViewController {
var selectedPictureTitle: String?
}
class PictureListController: NSObject, UITableViewDataSource, UITableViewDelegate {
// MARK: - Properties
weak var viewController: PictureTableViewController?
private let pictures: [Picture] = {
let pictureModelsDataSource = PictureModelsDataSource()
return pictureModelsDataSource.pictures
}()
// MARK: - View setup
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// MARK: - Event handling
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pictures.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PictureCell.self)) as? PictureCell else {
return UITableViewCell()
}
let picture = pictures[indexPath.row]
cell.pictureTitleLabel.text = picture.title
cell.pictureImage.image = picture.image
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pictureTitle = pictures[indexPath.row].title
let storyboard = UIStoryboard(name: "exampleStoryboard", bundle: nil)
if let pictureDetailViewController = storyboard.instantiateViewController(withIdentifier: "PictureDetailView") as? PictureDetailViewController {
pictureDetailViewController.selectedPictureTitle = pictureTitle
viewController?.navigationController?.pushViewController(pictureDetailViewController, animated: true)
}
}
}
使用此方法可以獲取StoryBoard
對象
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
現在,您的第二個問題是關於如何獲取導航控制器的。 這意味着在您的情況下如何獲取currentViewController
。 這可以通過下面的代碼獲得
func getCurrentViewController() -> UIViewController? {
if let rootController = UIApplication.shared.keyWindow?.rootViewController {
var currentController: UIViewController! = rootController
while( currentController.presentedViewController != nil ) {
currentController = currentController.presentedViewController
}
return currentController
}
return nil
}
現在您的didSelectRowAt
代碼將如下所示
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let detailViewController = storyboard.instantiateViewController(withIdentifier: "PictureDetailView") as? PictureDetailViewController
detailViewController.selectedImgName = pictureModels[indexPath.row].pictureName
self.getCurrentViewController()!.pushViewController(detailViewController, animated: true)
}
您正在嘗試遵守MVC,但是您卻混淆了實際的數據源。
PicturesDataSource
不是您的數據源 。 它是告訴您表如何設置自身的代碼。
PictureModelsDataController()
是從中獲取實際填充該表的數據的源。
您發布的所有代碼都應在同一類中:
class PictureTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
更改這些行:
pictureTableView.dataSource = picsDataSource
pictureTableView.delegate = picsDataSource
至
pictureTableView.dataSource = self // Note use of self because this is now the dataSource, not another class
pictureTableView.delegate = self // Note use of self because this is now the delegate, not another class
並刪除:
private let picsDataSource: PicturesDataSource
required init?(coder aDecoder: NSCoder) {
self.picsDataSource = PicturesDataSource()
super.init(coder: aDecoder)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.