2017-04-17 3 views
1

いいえ、UITableViewにカスタムUITableViewCellを作成したいと思います。カスタムUITableViewCellを使用して、ViewControllerで外部データソースとUITableViewを使用する

は、私は、モジュラーと可能な限り再利用可能なようにすべてのコンポーネントを必要とするので、私は別のクラスでそれらすべてを置くことにしました:

私のセットアップは次のようになりますため、私は私のDataSoureのための迅速なファイルを持っているファイルを 私のCustomTableViewCellと私のストーリーボードでは、他のUIVieesの横にUITableViewがあり、カスタムセルを使用すると宣言しました。

ストーリーボードは、次のようになります。

テーブルビュー(属性インスペクタ): storyboard setup and table view attributes inspector

テーブルビュー(アイデンティティインスペクタ): table view identity inspector

テーブルビュー(サイズインスペクタ): table view size inspector

TableViewCell (身元検査官): table view cell identity inspector

TableViewCell(属性インスペクタ): table view cell attributes inspector

TableViewCell(サイズインスペクタ):

import UIKit 

class MyShitViewController: UIViewController, UITableViewDelegate { 

    @IBOutlet weak var importantTableView: UITableView! 
    var importantItems = [ContentItem]() 

    override func viewWillAppear(_ animated: Bool) { 
     super.viewWillAppear(animated) 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Test data 
     importantItems.append(ContentItem(contentType: 1, image: #imageLiteral(resourceName: "ContentIcon"), title: "SQL - Basics", subject: "informatics", grade: 11, progress: 35, action: ContentItem.ACTION_MORE)) 
     importantItems.append(ContentItem(contentType: 1, image: #imageLiteral(resourceName: "ContentIcon"), title: "SQL - Pros", subject: "informatics", grade: 12, progress: 0, action: ContentItem.ACTION_MORE)) 
     // Data source 
     let dataSource = ContentItemDataSource(items: importantItems) 
     importantTableView.rowHeight = 75 
     importantTableView.dataSource = dataSource 
     importantTableView.reloadData() 
    } 

    //MARK: Table view delegate 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     // For debugging, never get's called, when some one clicks on any cell 
     let row = indexPath.row 
     print(row) 
    } 

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     print("height") 
     return 48 
    } 

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { 
     print("estimated height") 
     return 48 
    } 
} 

マイCustomTableViewCellクラス:

table view cell size inspector

私のViewControllerクラスは、このようになります。

import UIKit 

class ContentItemView: UITableViewCell { 

    //MARK: Properties 
    var contentItem: ContentItem? 

    private var contentImageView: UIImageView? 
    private var primaryTextView: UILabel? 
    private var secondaryTextView: UILabel? 
    private var progressView: UILabel? 
    private var actionView: UIButton? 
    private var verifiedIcon: UIImageView? 

    private var layoutConstraints: [NSLayoutConstraint] = [] 

    //MARK: Initialisation 
    func setContent(item: ContentItem) { 
     self.contentItem = item 
     setContent() 
    } 

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
     super.init(style: style, reuseIdentifier: reuseIdentifier) 
     print(style) 
     setUpView() 
    } 

    required init?(coder: NSCoder) { 
     super.init(coder: coder) 
     print("coder") 
     setUpView() 
    } 

    //MARK: Set Up 
    private func setUpView() { 
     self.backgroundView?.backgroundColor = Colors.biology 
     self.textLabel?.text = "Test" 
     // Create views 
     contentImageView = UIImageView() 
     primaryTextView = UILabel() 
     secondaryTextView = UILabel() 
     progressView = UILabel() 
     actionView = UIButton() 
     verifiedIcon = UIImageView() 
     // Add Content to views 
     primaryTextView?.font = getFont(withSize: 14) 
     primaryTextView?.textColor = Colors.toolbarColor 
     secondaryTextView?.font = getFont(withSize: 12) 
     secondaryTextView?.textColor = Colors.toolbarColor 
     progressView?.font = getFont(withSize: 12) 
     progressView?.textColor = Colors.toolbarColor 
     // Add sub views 
     self.contentView.addSubview(contentImageView!) 
     self.contentView.addSubview(primaryTextView!) 
     self.contentView.addSubview(secondaryTextView!) 
     self.contentView.addSubview(progressView!) 
     self.contentView.addSubview(actionView!) 
     self.contentView.addSubview(verifiedIcon!) 
     // Apply Constraints 
     makeViewConstraints() 
    } 

    // MARK: Layout 
    private func setContent() { 
     contentImageView?.image = contentItem?.image 
     primaryTextView?.text = contentItem?.title 
     secondaryTextView?.text = (contentItem?.done)! ? "DONE" : (contentItem?.subject)! + " - " + getLocalizedGrade(_for: (contentItem?.grade)!) 
     progressView?.text = contentItem?.progress != nil ? "\(String(describing: contentItem?.progress))%" : "" 
     if (contentItem?.verified)! { verifiedIcon?.image = #imageLiteral(resourceName: "verified") } 
     else { verifiedIcon?.image = nil } 
     let actionImage = getActionImage() 
     actionView?.setImage(actionImage, for: .normal) 
    } 

    private func makeViewConstraints() { 
     // Clear constraints 
     self.contentView.removeConstraints(layoutConstraints) 
     layoutConstraints.removeAll() 
     // Force elements to exist 
     let imageView = self.contentImageView! 
     let primaryTextView = self.primaryTextView! 
     let secondaryTextView = self.secondaryTextView! 
     let progressView = self.progressView! 
     let actionView = self.actionView! 
     imageView.translatesAutoresizingMaskIntoConstraints = false 
     imageView.widthAnchor.constraint(equalToConstant: 48) 
     imageView.heightAnchor.constraint(equalToConstant: 48) 
     layoutConstraints.append(
      NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal, 
          toItem: self.contentView, attribute: .leading, multiplier: 1, constant: 0)) 
     layoutConstraints.append(
      NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, 
          toItem: self.contentView, attribute: .centerY, multiplier: 1, constant: 0)) 
     primaryTextView.translatesAutoresizingMaskIntoConstraints = false 
     layoutConstraints.append(
      NSLayoutConstraint(item: primaryTextView, attribute: .leading, relatedBy: .equal, 
          toItem: imageView, attribute: .trailing, multiplier: 1, constant: 16)) 
     layoutConstraints.append(
      NSLayoutConstraint(item: primaryTextView, attribute: .top, relatedBy: .equal, 
          toItem: self.contentView, attribute: .top, multiplier: 1, constant: 8)) 
     secondaryTextView.translatesAutoresizingMaskIntoConstraints = false 
     layoutConstraints.append(
      NSLayoutConstraint(item: secondaryTextView, attribute: .leading, relatedBy: .equal, 
          toItem: imageView, attribute: .trailing, multiplier: 1, constant: 16)) 
     layoutConstraints.append(
      NSLayoutConstraint(item: secondaryTextView, attribute: .bottom, relatedBy: .equal, 
          toItem: self.contentView, attribute: .bottom, multiplier: 1, constant: -8)) 
     progressView.translatesAutoresizingMaskIntoConstraints = false 
     layoutConstraints.append(
      NSLayoutConstraint(item: progressView, attribute: .centerX, relatedBy: .equal, 
          toItem: imageView, attribute: .centerX, multiplier: 1, constant: 0)) 
     layoutConstraints.append(
      NSLayoutConstraint(item: progressView, attribute: .centerY, relatedBy: .equal, 
          toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0)) 
     actionView.translatesAutoresizingMaskIntoConstraints = false 
     layoutConstraints.append(
      NSLayoutConstraint(item: actionView, attribute: .trailing, relatedBy: .equal, 
          toItem: self.contentView, attribute: .trailing, multiplier: 1, constant: 0)) 
     layoutConstraints.append(
      NSLayoutConstraint(item: actionView, attribute: .centerY, relatedBy: .equal, 
          toItem: self.contentView, attribute: .centerY, multiplier: 1, constant: 0)) 
     self.contentView.addConstraints(layoutConstraints) 
    } 

    // MARK: Additional Helpers 
    private func getActionImage() -> UIImage? { 
     if contentItem?.action == ContentItem.ACTION_MORE { 
      return #imageLiteral(resourceName: "ic_more_horiz_white") 
     } 
     if contentItem?.action == ContentItem.ACTION_ADD { 
      return #imageLiteral(resourceName: "ic_add_circle_outline_white") 
     } 
     if contentItem?.action == ContentItem.ACTION_REMOVE { 
      return #imageLiteral(resourceName: "ic_remove_circle_outline_white") 
     } 
     return nil 
    } 
} 

そして最後に、私のデータソース:

import UIKit 

class ContentItemDataSource: NSObject, UITableViewDataSource { 
    var items = [ContentItem]() 

    init(items: [ContentItem]) { 
     self.items = items 
    } 

    // MARK: - Table view data source 

    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return 1 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return items.count 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let item = items[indexPath.row] 
     guard let cell = tableView.dequeueReusableCell(withIdentifier: Config.CONTENT_ITEM_CELL, for: indexPath) as? ContentItemView else { 
      fatalError("The dequeued cell is not an instance of ContentItemView.") 
     } 
     cell.setContent(item: item) 
     return cell 
    } 
} 

私はそれが動作しない理由は、おそらく、DataSourceが期待どおりに動作またはテーブルビューにデータソースを割り当てることはありませんわかりません...

前回と同じように、CustomTableViewCellは問題ありません。ビューを追加するコードをself.contentViewに変更しました。

実際の出力: actual output

予想される出力: expected output

+0

あなたは、再利用可能なコンポーネントをコーディングすることに興味があるように見えます。おそらく、このリンクはあなたのために興味があります:http://stackoverflow.com/a/43426337/6595536 – ObjectAlchemist

+0

これは、アプリケーションをコーディングするための本当に興味深い方法です:D 私は次のプロジェクトのために念頭に置いておきます:) –

答えて

1

データソースが弱いように定義されます。

weak open var dataSource: UITableViewDataSource? 

あなたのコード:あなたは

let dataSource = ContentItemDataSource(items: importantItems) 
importantTableView.dataSource = dataSource 

参照を保持しないので、メソッドの終了後に再びnilになります。

解決策:クラスvarを定義し、必要なだけ長く保持します。

var dataSource: UITableViewDataSource! 

と:

let dataSource = ContentItemDataSource(items: importantItems) 
importantTableView.dataSource = dataSource 
self.dataSource = dataSource 
+0

そしてところで、あなたは 'importantTableView.delegate = self'を設定しません。 – ObjectAlchemist

+0

オハイオ州よい点:D私はそこにそれを持っていました:)しかし、私は他のプロジェクトでそれを見たように、問題を解決するかもしれないと思ったので、代わりにコンセントを使用しました。何を推測する:それはなかった –

+0

ありがとう、私はその事実についても考えなかった。あなたは私が最終的に私のために働いたので、私は私の部屋をスイングジャンプを作った:D –

関連する問題