Contents
- Contents
- Introduction
- Installation
- Usage
- Running the examples
- Customization
- Dependencies
- Requirements
- Getting involved
Introduction
SuggestionRow
is a row extension for the Eureka iOS form builder that provides completion suggestions as the user is typing. There are two rows that can be instantiated:
SuggestionAccessoryRow<T>
- provides completion suggestions as tags in a horizontalcollectionView
displayed as theinputAccessoryView
above the keyboard.SuggestionTableRow<T>
- provides completion suggestions in a table below the cell.
Both classes are generic and can be used to provide completion suggestions for any type that conforms to the SuggestionValue
protocol:
public protocol SuggestionValue: Equatable, InputTypeInitiable {
var suggestionString: String { get }
}
SuggestionRow
is based off of GooglePlacesRow
Installation
CocoaPods
CocoaPods is a dependency manager for Cocoa projects.
Add SuggestionRow
to your project's Podfile
:
pod 'SuggestionRow'
Then run pod install
.
Swift Package Manager
Swift Package Manager is a tool for managing the distribution of Swift code.
After you set up your Package.swift
manifest file, you can add SuggestionRow as a dependency by adding it to the dependencies value of your Package.swift
.
dependencies: [ .package(url: "https://github.com/EurekaCommunity/SuggestionRow.git", from: "3.3.0") ]
Usage
SuggestionValue
protocol
Conform to First, the type that you want to provide completion suggestions for must conform to the SuggestionValue
protocol. For example, consider the following Scientist struct
:
struct Scientist {
var id: Int
var firstName: String
var lastName: String
init(id: Int, firstName: String, lastName: String) {
self.id = id
self.firstName = firstName
self.lastName = lastName
}
}
To conform to the SuggestionValue
protocol, add a suggestionString
method that specifies how Scientist
s should be displayed as suggestions. This is the text that will either go in a tag in the inputAccessoryView
or in a row in the suggestions UITableView
. For Scientist
s, displaying the full name is a good option, as shown below. Scientist
must also conform to Equatable
and InputTypeInitiable
as required by SuggestionValue
. InputTypeInitiable
is a protocol defined by Eureka
which requires an optional initializer that takes in a String
. It's used to determine how to instatiate a value from the contents of a UITextField
. In this case, the text that the user types in is used to filter existing values but not create new ones so the initializer can return nil.
extension Scientist: SuggestionValue {
// Required by `InputTypeInitiable`, can always return nil in the SuggestionValue context.
init?(string stringValue: String) {
return nil
}
// Text that is displayed as a completion suggestion.
var suggestionString: String {
return "\(firstName) \(lastName)"
}
}
To conform to the Equatable
protocol, implement the ==
operator at a global scope:
func == (lhs: Scientist, rhs: Scientist) -> Bool {
return lhs.id == rhs.id
}
Instantiate the row
In your form, add a row of type SuggestionAccessoryRow<Scientist>
or SuggestionTableRow<Scientist>
. You must define the row's filterFunction
to determine where completion suggestions come from and how they are selected based on the user's input. The function you set as filterFunction
must take in a String
parameter (what the user has typed in) and return an array of Scientist
(the valid suggestions). This function is called each time the user input field changes. The following example is also in SuggestionExampleViewController
:
let users: [Scientist] = [Scientist(id: 1, firstName: "Albert", lastName: "Einstein"),
Scientist(id: 2, firstName: "Isaac", lastName: "Newton")]
...
form +++ Section("Table suggestions")
<<< SuggestionTableRow<Scientist>() {
$0.filterFunction = { [unowned self] text in
self.users.filter({ $0.firstName.lowercased().contains(text.lowercased()) })
}
$0.placeholder = "Search for a famous scientist"
}
Running the examples
To run the examples follow these steps:
- Clone or download this repo
- Run
carthage update
in the root folder - Run the project
Customization
SuggestionTableRow
SuggestionTableRow
uses a generic SuggestionTableCell
cell whose generic parameter is the UITableViewCell
class used to create the cells displayed in a UITableView
with the suggested options.
-
If you want to make minor visual changes to the suggestion table row cells, use the
customizeTableViewCell
callback. -
You can customize attributes of the
tableView
that displays the options. You should do this incellSetup
and keep in mind that the frame of the tableView is reset each time the tableView is displayed. -
If you want to change these cells drastically, create your own row with your own cell class which conforms to
EurekaSuggestionTableViewCell
. For example like this:
final class MySuggestionTableRow<T: SuggestionValue>: _SuggestionRow<MySuggestionTableCell<T, SuggestionTableViewCell<T>>>, RowType {
required public init(tag: String?) {
super.init(tag: tag)
}
}
class MySuggestionTableCell<T, TableViewCell: UITableViewCell>: SuggestionTableCell<T, TableViewCell> where TableViewCell: EurekaSuggestionTableViewCell, TableViewCell.S == T {
// ...
}
open class MySuggestionTableViewCell<T: SuggestionValue>: SuggestionTableViewCell<T> {
// ...
}
Here MySuggestionTableCell
is the cell of the row itself and MySuggestionTableViewCell
is the cell that is used to display the suggestions.
Look at the source code of the default cells for inspiration.
SuggestionAccessoryRow
SuggestionAccessoryRow
uses a generic SuggestionCollectionCell
cell whose generic parameter is the UICollectionViewCell
class used in the inputAccessoryView
.
-
If you want to make minor visual changes to the suggestion cells, use the
customizeCollectionViewCell
callback. -
If you want to change the layout of the collectionView then you can use/modify/override the
collectionViewLayout
attribute in thecellSetup
method when declaring the row. -
If you want to change something about the collectionView (e.g. its height, backgroundColor) then you can also do that in the
cellSetup
method. -
If you want to change the collection view cell of the inputAccessoryView drastically, create your own row (
MySuggestionAccessoryRow
) with your own cell class which conforms toEurekaSuggestionCollectionViewCell
. This is very similar to the example mentioned above forSuggestionTableRow
.
Dependencies
- Eureka
Requirements
- iOS 9.3+
- Xcode 11+
- Swift 5.0
Getting involved
- If you want to contribute please feel free to submit pull requests.
- If you have a feature request please open an issue.
- If you found a bug or need help please check older issues before submitting an issue..