Simple drop-in for using autocomplete component on iOS
A simple drop-in for using an autocomplete component on iOS. It comes with a simple demo app that should help you get started in a jiffy!
MJAutoCompletefolder located inside the repo into your project.
shouldUpdateTextmethods from the protocol.
MJAutoCompleteTriggerswith a delimiter and a list of items (for testing).
containerproperty to that container.
NSDictionaryproperty, there are two interesting properties:
autoCompleteString: The string that will be checked against when filtering the list
displayedString: The string that the user will see in the default
MJAutoCompleteCellimplementation. (e.g.: autoCompleteString = twitter handle, displayedString = Full name).
The top level object that you interact with mainly, is the
MJAutoCompleteManager. The manager retains a
TableViewControllerand asks you to assign its
containerto a UIView that will host the AutoComplete table view. The manager also provides a delegate & dataSource interface to interact with the component.
After initialization, you would send the whole string the user is typing to the AutoComplete manager through
processString:. The manager will iterate over the triggers and check whether the input fires any of them.
If the input fires a trigger, the manager will check if the dataSource implements the
itemList:selector. This method is meant for developers who plan to fetch the list asynchronously. This selector is called with a callback that must be called once the list is ready. If the method is not implemented, then the developer must set the item list on the trigger (
Immidiatly afte the manager gets the result of the trigger, it sends another optional message to the dataSource to filter the list in-place. (i.e. an
NSMutableArrayis passed to the dataSource, and that same object is expected to contain the filtered list on return). If this method is not implemented by the dataSource, the manager will apply a default filter to the list (e.g.
autoCompleteString beginswith[cd] %@).
Finally, an optional message is sent to the delegate that the AutoComplete table view will appear.
This process actually takes place every time the user types more stuff, even if the AutoComplete table is already displayed. This allows the developer to implement heuristics, such as autoCorrection or something.
MJAutoCompleteTC(where TC stands for TableViewController) simply dequeues a reusable cell and assigns it with the
MJAutoCompleteItemfor that row to the cell. before returning the cell to the table view, the controller sends a message to the manager, which in turn calls the optional selector on the delegate
autoCompleteManager:willPresentCell:forTrigger:. This is intended for developers who would like to load data just when the cell is presented (i.e. avatars).
At this point, the user either enters a character that hides the autoComplete table, such as a whitespace, or they select an AutoComplete option (or they exit the app, or the app crashes, or...). If they select an option, the only required
MJAutoCompleteManagerDelegatemethod is called, which is
-[autoCompleteManager:shouldUpdateToText:]. The implementation of this method is typically to set the string passed by the manager as the new string of the component the user was typing in.
When sending the list of autoComplete items to the component, make sure it's an array of
[MJAutoCompleteItem autoCompleteCellModelFromStrings:myObjectArray]if necessary. This will return an
MJAutoCompleteItemarray by passing the
-[NSObject description]message to all the items in the array.
If you would like to use a custom
MJAutoCompleteCellsubclass for the component, make sure that:
-[UITableView registerClass:NSClassFromString(...) ...].
After a default very simple implementation that allowed the developer to lazily load the thumbnails and cache them on their side, I realized that most of the async image loading components for iOS out there are
UIImageViewcategories. This meant that providing the developer with a model object that has an image property will not be compatible with these components. I thought about embedding a component within the project, like the notorious SDWebImage, but that meant that there will be a different internal cache for the component that I must either expose to the developer, or somehow allow the developer to manage/disable.
The final adapted solution was to remove the thumbnail support completely. Instead, a feature was implemented that allowed the developer to subclass the
MJAutoCompleteCell, hence customize the cell to their heart's content. The reason behind this approach is because I am from a school of thought that supports fine-grain maintainable/replaceable components rather than a huge monolithic component that just tries to do everything.