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



2.每个section对应一个viewModel






UITableViewCell上的UITextField
- 提前创建
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高度计算
提前创建好的
cell直接获取cell的高度 (适用于相同样式cell数量相对较少的情况,对应上面的每个section对应一个viewModel情况)通过协议或者上图展示的viewModel,提前计算好
cell的高度并缓存
UITableviewCell布局
- 每个
section对应一个viewModel情况


2.每个cell对应一个model对象
UITableviewCell上事件响应
1.delegate,block,RacSubject
2.使用响应者链ResponderChain





内存问题




以上
如有任何疑问或问题请联系我:fishnewsdream@gmail.com,欢迎交流,共同提高!
Objective-C/Swift技术开发交流群201556264,讨论何种技术并不受限,欢迎各位大牛百家争鸣!
微信公众号OldDriverWeekly,欢迎关注并提出宝贵意见
老司机iOS周报,欢迎关注或订阅
刚刚在线工作室,欢迎关注或提出建设性意见!
刚刚在线论坛, 欢迎踊跃提问或解答!
如有转载,请注明出处,谢谢!