All AirCollection
views (include cells) based on protocols. View able to implement several protocols to describe needed functionality
Protocol needed for implement unique view identifier and defines only one property viewIdentifier
. By default this property is equal to String(describing: self)
public protocol IdentificableView: class {
static var viewIdentifier: String { get }
}
Protocol needed for implement view nib instantiate and defines only one property viewNib
public protocol NibLoadableView: class {
static var viewNib: UINib { get }
}
This protocol has default implementation for view which implement IdentificableView
protocol. So when you use both protocols you don't need implement any properties by default
static var viewNib: UINib {
let nibName = self.viewIdentifier
let bundle = Bundle(for: Self.self)
return UINib(nibName: nibName, bundle: bundle)
}
Abstract protocol needed for implement configure view method and defines one method configure(_:)
. You shouldn't use this protocol for your views (include cells) implementation, but you able to create additional protocol that implement default implementation. Read about ModelConfigurableView for additional information
public protocol ConfigurableView: class {
func configure(_ model: Any)
}
Base ConfigurableView
protocol implementation and defines new one safe method configure(model:)
based on predefined associated Model
type. You should use this protocol for your views (include cells) implementation instead ConfigurableView
public protocol ModelConfigurableView: ConfigurableView {
associatedtype Model
func configure(model: Model)
}
Child ModelConfigurableView
protocol implementation and defines new property textInputView
and associated TextInputView
type. Use this protocol when you need observe some text input subview (e.g. UITextField
or UITextView
) inside your reusable view. Important! This protocol is able to implement only for Model
which implement TextInputConfigurableModel.
public protocol TextInputConfigurableView: ModelConfigurableView where Model: TextInputConfigurableModel {
associatedtype TextInputView: UIView
var textInputView: TextInputView { get }
}
Aditional protocol for ConfigurableView.Model
that defines new property textInputConfiguration
and associated Configuration
type. Read topics below for aditional information
public protocol TextInputConfigurableModel {
associatedtype Configuration: TextInputConfiguration
var textInputConfiguration: Configuration { get }
}
Use this protocol for ConfigurableView.Model
and implement textInputConfiguration
with type that you need. e.g. TextFieldConfiguration
:
struct Model: TextInputConfigurableModel {
let textInputConfiguration: TextFieldConfiguration
}
Abstract protocol needed for implement TextInputConfigurableView
that defines one method configure(textInputView:)
and associated TextInputView
type. You shouldn't use this protocol for your views (include cells) implementation, but you able to create additional protocol that implement default implementation. Read topics below for aditional information.
public protocol TextInputConfiguration {
associatedtype TextInputView: UIView
func configure(textInputView: TextInputView)
}
You are able to use already created implementation. But if you won't find anything suitable could create it or write to author.
Configuration for UITextField
with keyboard and some basic configurations. Use it both with TextFieldDelegate
public protocol TextFieldDelegate: class {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool
func textFieldDidBeginEditing(_ textField: UITextField)
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool
func textFieldDidEndEditing(_ textField: UITextField)
func textField(_ textField: UITextField, shouldChangeCharactersIn range: Range<String.Index>, replacementString string: String) -> Bool
func textFieldShouldClear(_ textField: UITextField) -> Bool
func textFieldShouldReturn(_ textField: UITextField) -> Bool
func textFieldEditingChanged(_ textField: UITextField)
}
open class TextFieldConfiguration: TextInputConfiguration {
/// The auto-capitalization style for the text object. Default is `UITextAutocapitalizationType.sentences`
public var autocapitalizationType: UITextAutocapitalizationType = .sentences
/// The autocorrection style for the text object. Default is `UITextAutocorrectionType.default`
public var autocorrectionType: UITextAutocorrectionType = .default
/// Controls when the standard clear button appears in the text field. Default is `UITextField.ViewMode.never`
public var clearButtonMode: UITextField.ViewMode = .never
/// The custom input view to display when the text field becomes the first responder. Default is nil
public var inputView: UIView? = nil
/// Identifies whether the text object should disable text copying and in some cases hide the text being entered. Default is `false`
public var isSecureTextEntry: Bool = false
/// The appearance style of the keyboard that is associated with the text object. Default is `UIKeyboardAppearance.default`
public var keyboardAppearance: UIKeyboardAppearance = .default
/// The keyboard style associated with the text object. Default is `UIKeyboardType.default`
public var keyboardType: UIKeyboardType = .default
/// The visible title of the Return key. Default is `UIReturnKeyType.default`
public var returnKeyType: UIReturnKeyType = .default
/// The configuration state for smart dashes. Default is `UITextSmartDashesType.default`
public var smartDashesType: UITextSmartDashesType = .default
/// The configuration state for smart quotes. Default is `UITextSmartQuotesType.default`
public var smartQuotesType: UITextSmartQuotesType = .default
/// The configuration state for the smart insertion and deletion of space characters. Default is `UITextSmartInsertDeleteType.default`
public var smartInsertDeleteType: UITextSmartInsertDeleteType = .default
/// The spell-checking style for the text object. Default is `UITextSpellCheckingType.default`
public var spellCheckingType: UITextSpellCheckingType = .default
/// The semantic meaning expected by a text input area. Default is nil
public var textContentType: UITextContentType? = nil
}
Configuration for UITextField
too. But there is UIPickerView
instead keyboard and some basic configurations. Use it both with TextFieldPickerViewDelegate
and TextFieldPickerViewDataSource
public protocol TextFieldPickerViewDataSource: class {
func textField(_ textField: UITextField, numberOfComponentsInPickerView pickerView: UIPickerView) -> Int
func textField(_ textField: UITextField, pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
func textField(_ textField: UITextField, pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> PickerViewTitle?
}
public protocol TextFieldPickerViewDelegate: TextFieldDelegate {
func textField(_ textField: UITextField, pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
func textField(_ textField: UITextField, pickerView: UIPickerView, shouldUpdateTextFromRow row: Int, inComponent component: Int) -> Bool
func textField(_ textField: UITextField, pickerView: UIPickerView, selectedRowInComponent component: Int) -> Int
}
public class TextFieldPickerViewConfiguration: TextFieldConfiguration {
/// Picker view which will use as text field `inputView`
public let pickerView: UIPickerView
/// Methods will call by picker view for needed actions
public unowned let pickerViewDataSource: TextFieldPickerViewDataSource
/// Methods will call by picker view for notify about actions actions
public unowned let pickerViewDelegate: TextFieldPickerViewDelegate
public init(pickerView: UIPickerView = UIPickerView(), dataSource: TextFieldPickerViewDataSource, delegate: TextFieldPickerViewDelegate)
public convenience init(pickerView: UIPickerView = UIPickerView(), controller: TextFieldPickerViewControllerProtocol)
}
Configuration for UITextField
too. But there is UIDatePicker
instead keyboard and some basic configurations. Use it both with TextFieldDatePickerDelegate
public protocol TextFieldDatePickerDelegate: TextFieldDelegate {
func textField(_ textField: UITextField, datePicker: UIDatePicker, didSelectDate date: Date)
func textField(_ textField: UITextField, datePicker: UIDatePicker, shouldUpdateTextFromDate date: Date) -> String?
}
public class TextFieldDatePickerConfiguration: TextFieldConfiguration {
public let datePicker: UIDatePicker
public unowned let datePickerDelegate: TextFieldDatePickerDelegate
public init(datePicker: UIDatePicker, delegate: TextFieldDatePickerDelegate)
public convenience init(mode: UIDatePicker.Mode, date: Date = Date(), minimumDate: Date? = nil, maximumDate: Date? = nil, delegate: TextFieldDatePickerDelegate)
Configuration for UITextView
with keyboard and some basic configurations. Use it both with TextViewDelegate
public protocol TextViewDelegate: class {
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool
func textViewShouldEndEditing(_ textView: UITextView) -> Bool
func textViewDidBeginEditing(_ textView: UITextView)
func textViewDidEndEditing(_ textView: UITextView)
func textView(_ textView: UITextView, shouldChangeTextIn range: Range<String.Index>, replacementText text: String) -> Bool
func textViewDidChange(_ textView: UITextView)
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: Range<String.Index>, interaction: UITextItemInteraction) -> Bool
func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: Range<String.Index>, interaction: UITextItemInteraction) -> Bool
}
open class TextViewConfiguration: TextInputConfiguration {
public var autocapitalizationType: UITextAutocapitalizationType = .sentences
public var autocorrectionType: UITextAutocorrectionType = .default
public var dataDetectorTypes: UIDataDetectorTypes = .all
public var inputView: UIView? = nil
public var isSecureTextEntry: Bool = false
public var isSelectable: Bool = true
public var keyboardAppearance: UIKeyboardAppearance = .default
public var keyboardType: UIKeyboardType = .default
public var returnKeyType: UIReturnKeyType = .default
public var smartDashesType: UITextSmartDashesType = .default
public var smartQuotesType: UITextSmartQuotesType = .default
public var smartInsertDeleteType: UITextSmartInsertDeleteType = .default
public var spellCheckingType: UITextSpellCheckingType = .default
public var textContentType: UITextContentType? = nil
}
Protocol for views that need observe selection state and defines one property isSelected
and one method didSetSelected(_:,:)
. Do not confuse didSetSelected(_:,:)
method with UITableViewCell.setSelected(_:,animated:)
method.
You can implement this protocol that observe selection state change and you can set appearance for your UITableViewCell
or UICollectionViewCell
func didSetSelected(_ selected: Bool, animated: Bool) {
self.titleLabel.textColor = selected ? self.titleLabelSelectedColor : self.titleLabelColor
self.backgroundColor = selected ? self.contentViewSelectedColor : self.contentViewColor
}
Protocol for views that need observe highlight state and defines one property isHighlight
and one method didSetHighlighted(_:,:)
. Do not confuse didSetHighlighted(_:,:)
method with UITableViewCell.setHighlighted(_:,animated:)
method.
You can implement this protocol that observe highlight state change and you can set appearance for your UITableViewCell
or UICollectionViewCell
func didSetHighlighted(_ highlighted: Bool, animated: Bool) {
self.titleLabel.textColor = highlighted ? self.titleLabelHighlightedColor : self.titleLabelColor
self.backgroundColor = highlighted ? self.contentViewHighlightedColor : self.contentViewColor
}
Table view cell should implement Identificable View, one child implementation of Configurable View and optionally Nib Loadable View if cell layouts have Xib
file.
First of all create your UITableViewCell
class and implement IdentificableView
and ModelConfigurableView
protocols.
class TableViewCell: UITableViewCell, IdentificableView, ModelConfigurableView
Than add needed subviews and their layouts. In my example it just titleLabel
private let titleLabel: UILabel = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.addSubview(self.titleLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.titleLabel.frame = self.bounds.inset(by: self.layoutMargins)
}
Finally implement ModelConfigurableView
. Create predefined model for configuration (in my example is struct Model
) with needed primitive properties (in my example is let title: String
) and add required configure(model:)
method where configure all needed subviews by predefined model properties. Caution! Make sure you are using a configure(model: Model)
and configure(_ model: Any)
.
func configure(model: Model) {
self.titleLabel.text = model.title
}
struct Model {
let title: String
}
There is the simplest example when you need to create table view cell with code layouts. For more details see StaticTableViewCell in my project example
First of all create your UITableViewCell
class and implement IdentificableView
, NibLoadableView
and ModelConfigurableView
protocols.
class NibTableViewCell: UITableViewCell, IdentificableView, NibLoadableView, ModelConfigurableView
Than add outlets for subviews and .xib
file for layouts. In my example it titleLabel
and descriptionLabel
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var descriptionLabel: UILabel!
Finally implement ModelConfigurableView
. Create predefined model for configuration (in my example is struct Model
) with needed primitive properties (in my example is let title: String
and let description: String?
) and add required configure(model:)
method where configure all needed subviews by predefined model properties. Caution! Make sure you are using a configure(model: Model)
and configure(_ model: Any)
.
func configure(model: Model) {
self.titleLabel.text = model.title
self.descriptionLabel.text = model.description
self.descriptionLabel.isHidden = model.description == nil
}
struct Model {
let title: String
let description: String?
}
There is the simplest example when you need to create table view cell with xib layouts. For more details see DynamicTitleDescriptionTableViewCell in my project example
Implementation is similar to previous steps but you have to implement TextInputConfigurableView
instead ModelConfigurableView
protocol (e.g we create table view cell with text field)
class TextInputTableViewCell: UITableViewCell, IdentificableView, NibLoadableView, TextInputConfigurableView {
@IBOutlet private weak var textField: UITextField!
}
Next add textInputView
property implementation and return reference to your text input view (e.g. textField
)
var textInputView: UITextField {
return self.textField
}
Finally modify your model implementation and add textInputConfiguration
. It have to one of implementations of TextInputConfiguration
protocol (e.g. TextFieldConfiguration
or TextViewConfiguration
)
struct Model: TextInputConfigurableModel {
...
let textInputConfiguration: TextFieldConfiguration
}
There is the simplest example when you need to create table view cell with text input. For more details see DynamicUserTableViewCell and DynamicStoryTableViewCell in my project example
Collection view cell implementation is exactly the same as table view cell. Just use UICollectionViewCell
instead UITableViewCell