Created
October 30, 2019 05:07
-
-
Save marty-suzuki/161564002b05cde13cd98fb0f773be3e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Generic<T> { | |
fileprivate let base: T | |
} | |
extension Generic where T == UICollectionView { | |
fileprivate init(_ base: UICollectionView) { | |
self.base = base | |
} | |
func register<View: UIView & Reusable>(_: View.Type) { | |
let identifier = String(describing: CollectionViewCell<View>.self) | |
base.register(CollectionViewCell<View>.self, forCellWithReuseIdentifier: identifier) | |
} | |
func dequeue<View: UIView & Reusable>(_: View.Type, for indexPath: IndexPath) -> CollectionViewCell<View> { | |
let identifier = String(describing: CollectionViewCell<View>.self) | |
return base.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! CollectionViewCell<View> | |
} | |
} | |
extension UICollectionView { | |
var generic: Generic<UICollectionView> { | |
return Generic(self) | |
} | |
} | |
extension Generic where T == UITableView { | |
fileprivate init(_ base: UITableView) { | |
self.base = base | |
} | |
func register<View: UIView & Reusable>(_: View.Type) { | |
let identifier = String(describing: TableViewCell<View>.self) | |
base.register(TableViewCell<View>.self, forCellReuseIdentifier: identifier) | |
} | |
func dequeue<View: UIView & Reusable>(_: View.Type, for indexPath: IndexPath) -> TableViewCell<View> { | |
let identifier = String(describing: TableViewCell<View>.self) | |
return base.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as! TableViewCell<View> | |
} | |
} | |
extension UITableView { | |
var generic: Generic<UITableView> { | |
return Generic(self) | |
} | |
} | |
// MARK: - Protocols | |
protocol ViewInitializable: AnyObject { | |
init(frame: CGRect) | |
} | |
protocol Reusable: AnyObject { | |
static func make() -> Self | |
func prepareForReuse() | |
} | |
extension Reusable where Self: ViewInitializable { | |
static func make() -> Self { | |
return .init(frame: .zero) | |
} | |
} | |
extension Reusable where Self: Nibable { | |
static func make() -> Self { | |
return makeFromNib() | |
} | |
} | |
protocol Nibable: AnyObject { | |
static var nibName: String { get } | |
static var nib: UINib { get } | |
static func makeFromNib() -> Self | |
} | |
extension Nibable where Self: UIView { | |
static var nibName: String { | |
return String(describing: self) | |
} | |
static var nib: UINib { | |
return UINib(nibName: String(describing: self), bundle: nil) | |
} | |
static func makeFromNib() -> Self { | |
return nib.instantiate(withOwner: nil, options: nil).first as! Self | |
} | |
} | |
typealias ReusableView = UIView & Reusable & ViewInitializable | |
typealias ReusableNibView = UIView & Reusable & Nibable | |
// MARK: - Cells | |
final class CollectionViewCell<View: UIView & Reusable>: UICollectionViewCell { | |
let view = View.make() | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
view.frame = bounds | |
view.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
addSubview(view) | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
view.frame = bounds | |
view.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
addSubview(view) | |
} | |
override func prepareForReuse() { | |
super.prepareForReuse() | |
view.prepareForReuse() | |
} | |
} | |
final class TableViewCell<View: UIView & Reusable>: UITableViewCell { | |
let view = View.make() | |
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
super.init(style: style, reuseIdentifier: reuseIdentifier) | |
view.frame = bounds | |
view.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
addSubview(view) | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
view.frame = bounds | |
view.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
addSubview(view) | |
} | |
override func prepareForReuse() { | |
super.prepareForReuse() | |
view.prepareForReuse() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment