Skip to content

Instantly share code, notes, and snippets.

@everlof
Created January 19, 2020 12:05
Show Gist options
  • Save everlof/28b1addd92a66f2cd67b627e5653d674 to your computer and use it in GitHub Desktop.
Save everlof/28b1addd92a66f2cd67b627e5653d674 to your computer and use it in GitHub Desktop.
Key-value view
enum Keys: String, CaseIterable {
case nicknames = "Nicknames"
case calendars = "Calendars"
case born = "Born"
}
let kvView = KVView<Keys>()
kvView[.nicknames].value = event.aggregatedNicknamesDescription
kvView[.calendars].value = event.aggregatedCalendarsDescription
kvView[.born].value = formatter.string(from: birthdate)
import UIKit
class KVRow<Key>: UIStackView where Key: CaseIterable, Key: RawRepresentable, Key.RawValue == String {
let key: Key
var value: String? {
get {
valueLabel.text
}
set {
valueLabel.text = newValue
}
}
private let keyLabel = UILabel()
private let valueLabel = UILabel()
private let valueStackView = UIStackView()
private let drawDebug: Bool
init(key: Key, drawDebug: Bool) {
self.key = key
self.drawDebug = drawDebug
super.init(frame: .zero)
axis = .horizontal
keyLabel.font = UIFont.preferredFont(for: .subheadline, trait: nil, weight: .regular)
keyLabel.textColor = .lightGray
keyLabel.textAlignment = .left
keyLabel.text = key.rawValue
valueLabel.font = UIFont.preferredFont(for: .subheadline, trait: nil, weight: .regular)
valueLabel.textColor = .darkText
valueLabel.textAlignment = .right
addArrangedSubview(keyLabel)
addArrangedSubview(valueStackView)
valueStackView.axis = .horizontal
valueStackView.spacing = 3.0
let spacer = UIView()
spacer.setContentHuggingPriority(.defaultLow, for: .horizontal)
valueStackView.addArrangedSubview(spacer)
valueStackView.addArrangedSubview(valuePrefixContainerView)
valueStackView.addArrangedSubview(valueLabel)
if drawDebug {
keyLabel.backgroundColor = UIColor.systemRed
valueLabel.backgroundColor = UIColor.systemBlue
}
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private lazy var valuePrefixContainerView = UIView()
private var _valuePrefixView: UIView?
public var valuePrefixView: UIView? {
get {
_valuePrefixView
}
set {
_valuePrefixView?.removeFromSuperview()
_valuePrefixView = newValue
if let newValue = newValue {
newValue.translatesAutoresizingMaskIntoConstraints = false
valuePrefixContainerView.addSubview(newValue)
if let button = newValue as? UIButton {
let edges: CGFloat = 4.0
button.contentEdgeInsets = UIEdgeInsets(top: edges, left: edges, bottom: edges, right: edges)
}
NSLayoutConstraint.activate([
valuePrefixContainerView.leftAnchor.constraint(equalTo: newValue.leftAnchor),
valuePrefixContainerView.topAnchor.constraint(equalTo: newValue.topAnchor),
valuePrefixContainerView.rightAnchor.constraint(equalTo: newValue.rightAnchor),
valuePrefixContainerView.bottomAnchor.constraint(equalTo: newValue.bottomAnchor)
])
}
}
}
}
class KVView<Key>: UIStackView where Key: CaseIterable, Key: RawRepresentable, Key.RawValue == String {
private let rows: [Key.RawValue: KVRow<Key>]
private let drawDebug: Bool
init(drawDebug: Bool = false) {
self.drawDebug = drawDebug
rows = Key.allCases.reduce(into: [:]) { result, key in
result[key.rawValue] = KVRow(key: key, drawDebug: drawDebug)
}
super.init(frame: .zero)
axis = .vertical
spacing = 4.0
distribution = .fillEqually
Key.allCases.forEach { key in
let row = rows[key.rawValue]!
self.addArrangedSubview(row)
}
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
subscript(key: Key) -> KVRow<Key> {
rows[key.rawValue]!
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment