2017-09-10 15 views
0

私はAndroidのバックグラウンドからiOSの初心者です。私はビューコントローラからデータソース&デリゲートを分離しようとしています。どのように行うかについてのチュートリアルをいくつか見つけましたが、クリックされたアイテムを別のビューコントローラに送信する方法を理解していました。コードは次のとおりです。データソースとデリゲートがView Controllerと別の場合に、Table Viewのクリックしたアイテムを他のView Controllerに送信する方法

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) 
     } 
    } 

}  

です。 「ストーリーボード」&「navigationController」以来はPicturesDataSourceクラスでは使用できません、どのように私はDetailsViewControllerにクリックされたアイテム(画像名)送信することができます

あり、データソースとデリゲートを分離についてStackOverflowの答えがありますが、私の問題を解決しませんでした。

使用

:Xcodeの8.3ベータ版は6

+0

のように見えるのだろうか?この 'storyboardを利用してstoryBoardオブジェクトを作成することができます:UIStoryboard = UIStoryboard(名前:" Main "、バンドル:なし)' –

+0

@Aditya、navigationControllerはどうですか? –

+0

私の答えはあなたのために働くことを望む –

答えて

1

はあなたがあなたのテーブルビューのイベントハンドラでは、メインビューコントローラへの参照を含めることができます。以下は、私はあなたの例から派生遊び場コードは次のとおりです。

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) 
    } 
    } 
} 
+0

私はあなたの提案を理解しています。私はAndroidで(必要な時に)これをやった。私は、データソース内でクリックイベントを処理するか、デリゲート用の別のクラス(Ie PictureTableDelegate)を作成し、そこでクリックイベントを処理したい(PictureTableDelegate内)。委任パターン以外の方法はありますか? –

+0

あなたのコメントに基づいて投稿を編集しました。 @HassanTareq – CodeCrackPot

+0

Androidとして機能しますが、エレガントではありません。 Androidでは、List Adapter&Passアクティビティ参照(this)をコンストラクタ経由でAdapterに渡します。したがって、List Adapterですべてを利用できます。プロパティの代わりにDataSourceにコンストラクタ経由でView Controllerの参照を渡すことが可能ですか(プロパティで行った) –

-1

あなたは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) 
} 
+0

PictureModelsDataControllerからすべてのコードをPicturesDataSourceに入れるとどうなりますか? –

+0

これは問題ありません。ビューコントローラにテーブルビューが含まれているだけなので、ビューコントローラはテーブルビューのデータソースとそのデリゲートです。テーブルに移入する実際のデータは、カスタムクラスから得られます。 – Shades

+0

これは非常に質の低い回答です。 –

1

StoryBoardオブジェクトがこの

let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 

を使用することによって得ることができる今、あなたの2番目の質問は、ナビゲーションコントローラを取得する方法についてです参照してください。あなたのケースでは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コードがstoryboard`が利用できないのはなぜ `この

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) 
} 
+0

うまくいかない'' 'getCurrentViewController()' ''はnilを返します。 –

+0

@HassanTareq私は自分のプロジェクトで同じメソッドを使用していますが、正常に動作しています –

関連する問題