UItableViewはデータなしのビット画像を実現

2804 ワード

国際慣例、効果図
1.gif
この効果の実装は主にruntimeのクロスメソッドを用いて実現され,tableViewのreloadDataとカスタムkk_reloadData交換.新しいtableViewのCategory.交換メソッドプライマリコード
+ (void)swizzleInstanceSelector:(SEL)originalSel
           WithSwizzledSelector:(SEL)swizzledSel {
    
    Method originMethod = class_getInstanceMethod(self, originalSel);
    Method swizzedMehtod = class_getInstanceMethod(self, swizzledSel);
    BOOL methodAdded = class_addMethod(self, originalSel, method_getImplementation(swizzedMehtod), method_getTypeEncoding(swizzedMehtod));
    
    if (methodAdded) {
        class_replaceMethod(self, swizzledSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
    }else{
        method_exchangeImplementations(originMethod, swizzedMehtod);
    }
}

reloadDataの交換
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleInstanceSelector:@selector(reloadData) WithSwizzledSelector:@selector(kk_reloadData)];
    });
}

kk_reloadDataメソッドは、まずデータがあるかどうかをチェックし、再度kk_reloadDataメソッドがruntimeの交換メソッドを使用している場合、実際にはシステムのreloadDataメソッドが呼び出されます.
- (void)kk_reloadData {
    [self kk_checkEmpty];
    [self kk_reloadData];
}

kk_checkEmptyメソッド
- (void)kk_checkEmpty {
   BOOL isEmpty = YES;
   id src = self.dataSource;
   NSInteger sections = 1;
   if ([src respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
       sections = [src numberOfSectionsInTableView:self];
   }
   for (int i = 0; i < sections; i++) {
       NSInteger rows = [src tableView:self numberOfRowsInSection:i];
       if (rows) {
           isEmpty = NO;
       }
   }
   if (isEmpty) {//    ,       
   }else{//     ,       
   }
}

コードの侵入を低減するために、tableViewにViewプロパティ、すなわちビットマップビューを動的に追加できます.
@property (nonatomic, strong) UIView *placeHolderView;
- (void)setPlaceHolderView:(UIView *)placeHolderView {
    objc_setAssociatedObject(self, @selector(placeHolderView), placeHolderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIView *)placeHolderView {
    return objc_getAssociatedObject(self, @selector(placeHolderView));
}

kk_checkEmptyの
if (isEmpty) {//    ,       
}else{//     ,       
}

次のように変更
    if (isEmpty) {
        [self.placeHolderView removeFromSuperview];
        [self addSubview:self.placeHolderView];
    }else{
        [self.placeHolderView removeFromSuperview];
    }

以降はtableViewのplaceHolderViewプロパティを設定するだけで済みます
 _tableView.placeHolderView = [[UIView alloc] init];

終了githubアドレス:https://github.com/wuzaozhou/UITableView-placeholder