复杂UITableView的相关优化


仅做记录使用,会比较粗糙,不过多探讨!

iOS开发中,UITableView存在于几乎每一个应用中。不是那么复杂的UITableView使用常规写法没有任何问题,但是对于复杂业务一个UITableView中存在几十个不同的UITableViewCell,再使用常规写法简直就是灾难,有些写法性能上并无问题,但是优雅度不够,维护性较差。以下从几点阐述,为了方便,多是图片

UITableVIewCell的创建

  1. 每个cell对应一个viewModel

2.每个section对应一个viewModel

UITableViewCell上的UITextField

  1. 提前创建cell,为当前cell上的textField指定好下一个响应者

2.遍历获取所有可响应键盘的textField

    #import "UIView+NextKeyBoard.h"

@implementation UIView (NextKeyBoard)

/** 获取当前视图所有可以响应键盘的textField或textView */
- (NSArray *)lvdeepResponderViews {
    NSMutableArray<UIView*> *textFields = [[NSMutableArray alloc] init];
    CGFloat height = self.frame.size.height;
    if (height > 1 && self.hidden == NO) {
        for (UIView *textField in self.subviews) {
            if ((textField) && [textField lvcanBecomeFirstResponder] && [textField isUserInteractionEnabled] && ![textField isHidden] && [textField alpha] != 0.0) {
                [textFields addObject:textField];
            }

            if (textField.subviews.count && [textField isUserInteractionEnabled] && ![textField isHidden] && [textField alpha]!= 0.0) {
                [textFields addObjectsFromArray:[textField lvdeepResponderViews]];
            }
        }
    }

    // 按照位置y排序 如果y相等 则按照x的大小排序
    return [textFields sortedArrayUsingComparator:^NSComparisonResult(UIView *view1, UIView *view2) {

        CGRect frame1 = [view1 convertRect:view1.bounds toView:self];
        CGRect frame2 = [view2 convertRect:view2.bounds toView:self];

        CGFloat x1 = CGRectGetMinX(frame1);
        CGFloat y1 = CGRectGetMinY(frame1);
        CGFloat x2 = CGRectGetMinX(frame2);
        CGFloat y2 = CGRectGetMinY(frame2);

        if (y1 < y2) {
            return NSOrderedAscending;
        } else if (y1 > y2) {
            return NSOrderedDescending;
        } else if (x1 < x2) {
            return NSOrderedAscending;
        } else if (x1 > x2) {
            return NSOrderedDescending;
        } else {
            return NSOrderedSame;
        }
    }];
    return textFields;
}

/** 判断当前的输入控件是否可以有输入响应的事件 */
- (BOOL)lvcanBecomeFirstResponder {
    BOOL canBecomeFirstResponder = NO;
    if ([self isKindOfClass:[UITextField class]]) {
        canBecomeFirstResponder = [(UITextField*)self isEnabled];
    } else if ([self isKindOfClass:[UITextView class]]) {
        canBecomeFirstResponder = [(UITextView*)self isEditable];
    }

    if (canBecomeFirstResponder) {
        canBecomeFirstResponder = ([self isUserInteractionEnabled] && ![self isHidden] && [self alpha] != 0.0 && ![self isAlertViewTextField]  && ![self isSearchBarTextField]);
    }

    return canBecomeFirstResponder;
}

- (BOOL)isAlertViewTextField {
    UIResponder *alertViewController = [self lvviewController];
    BOOL isAlertViewTextField = NO;
    while (alertViewController && isAlertViewTextField == NO) {
        if ([alertViewController isKindOfClass:[UIAlertController class]]) {
            isAlertViewTextField = YES;
            break;
        }

        alertViewController = [alertViewController nextResponder];
    }
    return isAlertViewTextField;
}

- (BOOL)isSearchBarTextField {
    UIResponder *searchBar = [self nextResponder];
    BOOL isSearchBarTextField = NO;
    while (searchBar && isSearchBarTextField == NO) {
        if ([searchBar isKindOfClass:[UISearchBar class]]) {
            isSearchBarTextField = YES;
            break;
        } else if ([searchBar isKindOfClass:[UIViewController class]]) {
            break;
        }

        searchBar = [searchBar nextResponder];
    }
    return isSearchBarTextField;
}

- (UIViewController *)lvviewController {
    UIResponder *nextResponder =  self;
    do {
        nextResponder = [nextResponder nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            return (UIViewController*)nextResponder;
        }
    } while (nextResponder != nil);
    return nil;
}

@end

UITableviewCell高度计算

  1. 提前创建好的cell直接获取cell的高度 (适用于相同样式cell数量相对较少的情况,对应上面的每个section对应一个viewModel情况)

  2. 通过协议或者上图展示的viewModel,提前计算好cell的高度并缓存

UITableviewCell布局

  1. 每个section对应一个viewModel情况

2.每个cell对应一个model对象

UITableviewCell上事件响应

1.delegate,block,RacSubject

2.使用响应者链ResponderChain

内存问题

以上


如有任何疑问或问题请联系我:fishnewsdream@gmail.com,欢迎交流,共同提高!

Objective-C/Swift技术开发交流群201556264,讨论何种技术并不受限,欢迎各位大牛百家争鸣!

微信公众号OldDriverWeekly,欢迎关注并提出宝贵意见

老司机iOS周报,欢迎关注或订阅

刚刚在线工作室,欢迎关注或提出建设性意见!

刚刚在线论坛, 欢迎踊跃提问或解答!

如有转载,请注明出处,谢谢!

本站总访问量 本文总阅读量