GenericなUITableViewCellを使う
P.S この記事の内容は古くなりました。
iOS14にて、よく利用するセルのパターンとそのカスタマイズのためにUIContentConfigurationというオブジェクトが提供されました。
まずそちらを参考にしてください。
まえがき
TwitterのTLで少し前に「UITableViewCellのサブクラスを毎回作るのではなく、GenericsなTableViewCellにUIViewを載せて対応する」という方針を採用されておられる方がいて、良いなぁと思ったので作ってみました。
やったこと
GenericなUITableViewCellをつくる/つかう
@dynamicMemberLookup public class GenericTableViewCell<View : UIView>: UITableViewCell {
public let customView: View = .init(frame: .zero)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
public subscript<U>(dynamicMember keyPath: ReferenceWritableKeyPath<View, U>) -> U {
get {
customView[keyPath:keyPath]
}
set {
customView[keyPath:keyPath] = newValue
}
}
private func commonInit() {
contentView.addSubview(customView)
customView.translatesAutoresizingMaskIntoConstraints = false
customView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
customView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
customView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
customView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
}
この構造のメリット
UITableViewCell
をサブクラスしてViewを構築していく時の問題として、例えば表示内容は全く同じなのにUICollectionView
を利用した別の画面を作る必要が出た時に移行がすごく面倒です。
なので、普段からUIView
ベースでViewを作成してGenericなTableViewCellに載せる構成にしておくことで、プロジェクトの変更・拡張に対してロバストです。
この構造のデメリット
Viewスタックが一層余分に増え、そのままではアクセスもcustomView
プロパティ経由になるので少し冗長になります。
なので、後者の問題を消すためにdynamicMemberLookup
を採用し、直接内部Viewへのアクセス可能にしています。
使い方
TableViewへのセルの登録
Register.swift
tableView.register(GenericTableViewCell<YourCustomView>.self, forCellReuseIdentifier: "Cell")
セルの表示
Use.swift
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GenericTableViewCell<YourCustomView>
CollectionViewCellでは?
tableView.register(GenericTableViewCell<YourCustomView>.self, forCellReuseIdentifier: "Cell")
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GenericTableViewCell<YourCustomView>
CollectionViewCell
でも同じような仕組みを作る事ができます。実装はほぼ変わりません。
追記
コメントで頂いたのですが、この記事では
public let customView: View = .init(frame: .zero)
としていますが、これではNib経由でのUIViewのインスタンス化が出来ません。
Nib経由でのインスタンス化に対する柔軟性が欲しい場合は、<View: UIView>
とせずに生成は別の具体型に任せるFactoryMethodのようなデザインにすると良いでしょう。
詳しくはコメント欄をチェックしてみてください!
Author And Source
この問題について(GenericなUITableViewCellを使う), 我々は、より多くの情報をここで見つけました https://qiita.com/yosshi4486/items/9cf4c9f97af015702d84著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .