Simple drop-in for using autocomplete component on iOS
MIT License
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!
MJAutoComplete
folder located inside the repo into your project.#import "MJAutoCompleteManager.h"
shouldUpdateText
methods from the protocol.MJAutoCompleteTriggers
with a delimiter and a list of items (for testing).MJAutoCompleteManager
instance.MJAutoCompleteManager
's container
property to that container.-[MJAutoCompleteManager processString:]
!UITableViewCell
subclass.NSDictionary
property, there are two interesting properties:
autoCompleteString
: The string that will be checked against when filtering the listdisplayedString
: The string that the user will see in the default MJAutoCompleteCell
implementation. (e.g.: autoCompleteString = twitter handle, displayedString = Full name).
The top level object that you interact with mainly, is the MJAutoCompleteManager
. The manager retains a TableViewController
and asks you to assign its container
to 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 (trigger.autoCompleteItemList
).
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 NSMutableArray
is 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.
The MJAutoCompleteTC
(where TC stands for TableViewController) simply dequeues a reusable cell and assigns it with the MJAutoCompleteItem
for 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 MJAutoCompleteManagerDelegate
method 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
s!! Use [MJAutoCompleteItem autoCompleteCellModelFromStrings:myObjectArray]
if necessary. This will return an MJAutoCompleteItem
array by passing the -[NSObject description]
message to all the items in the array.
If you would like to use a custom MJAutoCompleteCell
subclass for the component, make sure that:
-[UITableView registerClass:NSClassFromString(...) ...]
.####UNDER CONSTRUCTION
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 UIImageView
categories. 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.