Project address: ChainDroplist

Recently, the project often meets the needs of drop/droplist (droplist), which has more commonalities, but will have slight differences. The first choice is of course to use a UITableView, but creating a datasource delegate for every Droplist would be too much trouble; Take some time to package a simple chained Droplist that meets the following needs:

  • Use chain-style program (Assemble, display, and select Droplist cells in one method)
  • Provide optional Droplist HostView (Not all dropilst is simply loaded onto KeyWindow)
  • Provides an optional tap rotation icon (Clicking and showing droplist should be accompanied by icon rotation, right?)
  • Provides optional Droplist baseView (Droplist should be stretched at the bottom or top of the click view)
  • When the upper/lower display space is insufficient, the development direction will be adjusted (Trust me, users don’t care, but I will always mention this bug in my tests)
  • The default display5If the display space is insufficient, automatically **-1** until the display conditions can be met (The experience of small screen users should be considered)
  • Cell supports maximum scaling and inheritance is currently recommended (You never know what the next designer is going to come up with)

Let’s start with a simple Sample:

Look at the use method again, there is an intuitive impression:


- (void)showDroplist:(UIView *)baseView icon:(UIView *)icon hostView:(UIView *)hostView
{
    [[[[[ChainedDroplistView alloc] initWithConfig:^(ChainedDroplistView *droplist) {
        droplist.hostView = self.view; /* Displays the droplist parent view, which defaults to Window */
        droplist.baseView = baseView; /* Used to determine the droplist top/bottom */
        droplist.rotationView = icon; /* Show droplist while doing rotation view */
        droplist.cellHeight = 60; /* Default Cell height */
        droplist.datas = [self createTestDatas]; /* Create cell datas */
    }] registCustomerCellsWithConfig:^(UITableView *tableView) {
        /* Bind Cell Identifier */ 
        [tableView registerClass:ChainedDroplistBaseCell.class forCellReuseIdentifier:kChainedDroplistBaseCellIdentifier];
    }] show] /* The show animation is performed after the call to show
        processAfterSelected:^(NSInteger index) {
        /* This block is executed when the user selects a Cell
        NSLog(@"U have selected index -> [%@]", @(index));
    }];
    
}

Copy the code

The code structure

Based on the UITableView encapsulation, through ChainedDroplistModelProtocol and ChainedDroplistCellProtocol cohesion Cell and the Model

ChainedDroplistModelProtocol
  • provideregisterClass:forCellReuseIdentifier:The identifier of
  • You can inherit directlyChainedDroplistBaseModel, the rewrite- (NSString *)strCellIdentifierMethod provides custom identifiers
Cell
  • configCellWithModel:At the end of eachtableView: cellForRowAtIndexPath:Method, which updates the Cell based on the Model

Key code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    NSInteger index = indexPath.row;
    NSAssert(index < self.cellDatas.count, @"index[%@] beyonds the max count[%@] of datas", @(index), @(self.cellDatas.count));

    / / according to ChainedDroplistModelProtocol strCellIdentifier for specified Cell
    id<ChainedDroplistModelProtocol> model = self.cellDatas[index];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:model.strCellIdentifier];
    NSAssert([cell conformsToProtocol:@protocol(ChainedDroplistCellProtocol)].
             @"cell[%@] from identifier[%@] must conforms protocol [%@]",
             cell, model.strCellIdentifier, NSStringFromProtocol(@protocol(ChainedDroplistCellProtocol)));
    UITableViewCell <ChainedDroplistCellProtocol> * droplistCell = (UITableViewCell <ChainedDroplistCellProtocol> *)cell;
    
    if ([droplistCell respondsToSelector:@selector(configCellWithModel:)]) {
        / / refresh the Cell
        [droplistCell configCellWithModel:model];
    }
    
    return droplistCell;
}
Copy the code
  • ChainedDroplistBaseCellIn theinitWithStyle: reuseIdentifier:Call thesetupUI,setupConstraintsUsed to set UI and constraints that can be inherited directlyChainedDroplistBaseCell, the rewritesetupUI setupConstraintsThe Customer cell definition is complete
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        [self setupUI];
        [self setupConstraints];
    }
    
    return self;
}
Copy the code

Declaration and definition of identifier

  • Leverage in ModelFOUNDATION_EXPORT NSString *const identifierThe statementidentifier
  • Define correlations in the Cellidentifier: NSString *const identifier=@"identifier"

This is done just to find the cell and the corresponding model through a simple identifier search

Sample

Students who want to know can refer to the use of the example

  1. cd Example/
  2. run pod install
  3. open ChainedDroplist.xcworkspace/

To best illustrate ChainDroplist’s design, examples include detailed usage scenarios, including:

  1. Default scenario: Expand down. By default, 5 lines are visible
  2. Insufficient downward display space: according tohostView,baseView,cellHeghtTo calculate the viewable space, or if there’s not enough space underneathupwardshow
  3. rotationViewUsed when expanding DroplistSynchronous rotation
  4. If the space above and below is insufficient to display 5 rows, calculate the minimum number of rows that can be displayed and display
  5. Through inheritanceChainedDroplistBaseCell,ChainedDroplistBaseModelTo implement custom styles (I don’t like using inheritance, but it works best for lightweight extension scenarios)