A common list page needs a mask view when there is no data. Take a chestnut, as shown below:

Screenshot 10.24.21.png on September 17, 2018
The methods in the runtime function library used here are:
objc_setAssociatedObject(<#id _Nonnull object#>, <#const void * _Nonnull key#>, <#id _Nullable value#>, <#objc_AssociationPolicy policy#>)
id object: refers to the associated person. It is an object. The variable name is also an object
const void *key: get the index key of the associated person
id value: associated person, here is a block
Objc ﹣ associationpolicy policy: the protocol used in association, including assign ment, retain, copy and other protocols. Objc ﹣ Association ﹣ retain ﹣ nonatomic is generally used
Upper code
Create a new class to inherit ViewController (I will not show the UI built by Xib file here)
.h file
#import <UIKit/UIKit.h> @class DXMaskViewController; @interface UIViewController (DXMaskView) @property (nonatomic,strong) DXMaskViewController* dxHudViewController; @property (nonatomic,strong) DXMaskViewController* dxNoDataViewController; // Loading - (DXMaskViewController *)dxShowHUDIndeterminate; - (DXMaskViewController *)dxShowHUDIndeterminateWithOffset:(float)offset; - (void)dxHideHUDIndeterminate; - (void)dxHideNoDataView; //Newly added - (DXMaskViewController *)dxShowNoDataViewOfTitle:(NSString *)title Detail:(NSString *)detail WithOffset:(float)offset; @end @interface DXMaskViewController : UIViewController @property (weak, nonatomic) IBOutlet UIImageView *maskImageView; @property (weak, nonatomic) IBOutlet UILabel *maskTitleLabel; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *maskIndicatorView; @property (weak, nonatomic) IBOutlet UILabel *maskDetailTitleLabel; @property (weak, nonatomic) IBOutlet UIButton *maskOnTapView; @property (nonatomic,copy) void(^onClick)(void); @end
.m file
#import "DXMaskViewController.h" #import <objc/runtime.h> #import <Masonry/Masonry.h> @interface DXMaskViewController () @end @implementation DXMaskViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (IBAction)onTapMask:(id)sender { if (self.onClick) { self.onClick(); } } @end @implementation UIViewController (DXMaskView) -(void)setDxHudViewController:(DXMaskViewController *)dxHudViewController { objc_setAssociatedObject(self, @selector(dxHudViewController), dxHudViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (DXMaskViewController *)dxHudViewController { return objc_getAssociatedObject(self, @selector(dxHudViewController)); } -(void)setDxNoDataViewController:(DXMaskViewController *)dxNoDataViewController { objc_setAssociatedObject(self, @selector(dxNoDataViewController), dxNoDataViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(DXMaskViewController *)dxNoDataViewController { return objc_getAssociatedObject(self, @selector(dxNoDataViewController)); } // Loading - (DXMaskViewController*)dxShowHUDIndeterminate { return [self dxShowHUDIndeterminateWithOffset:0]; } - (DXMaskViewController*)dxShowHUDIndeterminateWithOffset:(float)offset { DXMaskViewController *maskVc = self.dxHudViewController; if (!maskVc) { maskVc = [[DXMaskViewController alloc] initWithNibName:@"DXMaskViewController" bundle:nil]; self.dxHudViewController = maskVc; } if ([self isKindOfClass:[UICollectionViewController class]] ) { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } maskVc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); }else if ([self isKindOfClass:[UITableViewController class]]) { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } maskVc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); }else { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } [maskVc.view mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.mas_topLayoutGuide).offset(offset); make.left.right.bottom.equalTo(self.view); }]; } maskVc.maskImageView.image = [UIImage imageNamed:@""]; maskVc.maskTitleLabel.text = @"Loading! Please wait a moment";//Loading! Please wait a moment maskVc.maskDetailTitleLabel.text = @"";//Maybe it's a surprise maskVc.maskIndicatorView.hidden = false; [maskVc.maskIndicatorView startAnimating]; maskVc.maskOnTapView.hidden = true; maskVc.view.alpha = 1; return maskVc; } - (void)dxHideHUDIndeterminate { DXMaskViewController *maskVc = self.dxHudViewController; self.dxHudViewController = nil; if(maskVc) { [UIView animateWithDuration:0.2 animations:^{ maskVc.view.alpha = 0; } completion:^(BOOL finished) { [maskVc.view removeFromSuperview]; [maskVc removeFromParentViewController]; }]; } } - (DXMaskViewController*)dxShowNoDataViewOfTitle:(NSString *)title Detail:(NSString *)detail WithOffset:(float)offset { return [self dxShowNoDataViewWithTitle:title detail:detail image:[UIImage imageNamed:@"Empty page"] animating:false offset:offset]; } - (DXMaskViewController*)dxShowNoDataViewWithTitle:(NSString*)title detail:(NSString*)detail image:(UIImage*)image animating:(BOOL)animating { return [self dxShowNoDataViewWithTitle:@"" detail:@"" image:[UIImage imageNamed:@"Empty page"] animating:false offset:0]; } - (DXMaskViewController*)dxShowNoDataViewWithTitle:(NSString*)title detail:(NSString*)detail image:(UIImage*)image animating:(BOOL)animating offset:(float)offset { DXMaskViewController *maskVc = self.dxNoDataViewController; if (!maskVc) { maskVc = [[DXMaskViewController alloc] initWithNibName:@"DXMaskViewController" bundle:nil]; self.dxNoDataViewController = maskVc; } if ([self isKindOfClass:[UICollectionViewController class]] ) { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } maskVc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); }else if ([self isKindOfClass:[UITableViewController class]]) { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } maskVc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); }else { if (!maskVc.view.superview) { [self addChildViewController:maskVc]; [self.view addSubview:maskVc.view]; } [maskVc.view mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.mas_topLayoutGuide).offset(offset); make.left.right.bottom.equalTo(self.view); }]; } maskVc.maskImageView.image = image; maskVc.maskTitleLabel.text = title; maskVc.maskDetailTitleLabel.text = detail; if (animating) { maskVc.maskIndicatorView.hidden = false; [maskVc.maskIndicatorView startAnimating]; }else{ maskVc.maskIndicatorView.hidden = true; [maskVc.maskIndicatorView stopAnimating]; } maskVc.view.alpha = 1; maskVc.maskOnTapView.hidden = false; return maskVc; } - (void)dxHideNoDataView { DXMaskViewController *maskVc = self.dxNoDataViewController; self.dxNoDataViewController = nil; if (maskVc) { [UIView animateWithDuration:0.2 animations:^{ maskVc.view.alpha = 0; } completion:^(BOOL finished) { [maskVc.view removeFromSuperview]; [maskVc removeFromParentViewController]; }]; } } @end
When the list page requests data, use the following
Note: offset can set the view offset
//Default mask if (self.dataArray.count) { [self dxHideNoDataView]; }else { DXMaskViewController *maskView = [self dxShowNoDataViewOfTitle:@"No listings found" Detail:@"" WithOffset:60]; [maskView setOnClick:^{ //The callback here can be re requested }]; }