做网站开发哪种语言更稳定高效,江苏网站建设哪家专业,个人网站备案填写,学校网站建设与维护https://www.jianshu.com/p/beca3ac24031 实际运用场景#xff1a; 没网时的提示view#xff0c;tableView或collectionView没内容时的展示view#xff0c;以及其它特殊情况时展示的特定view。如#xff1a; 常见的几种情况我的目标#xff1a; 对以上几种情况的展示view做… https://www.jianshu.com/p/beca3ac24031 实际运用场景 没网时的提示viewtableView或collectionView没内容时的展示view以及其它特殊情况时展示的特定view。如 常见的几种情况 我的目标 对以上几种情况的展示view做统一封装将来做新APP时我只需在这个轮子上稍加修改就可实现相应需求。 对自己的要求 代码简洁规范逻辑清晰保证写出的代码将来任何接手的人可以轻松读懂。 对轮子的要求 使用方便易于维护修改高内聚低耦合不要因为这个轮子的加入而影响之前的代码思路 这是一个view可以添加到tableView或collectionView上的view当然也可以添加到其他类型的view上。一般说来在一个项目中从UI的角度来看这样的view有几种但是从结构的角度来看它们又一样比如说正中间一个imageView、imageView下方一个label、label下方一个button。点击这个view或者这个view上的button会执行相应回调方法。先贴出代码稍后细讲 .h文件 #import UIKit/UIKit.h/** 占位图的类型 */
typedef NS_ENUM(NSInteger, CQPlaceholderViewType) { /** 没网 */ CQPlaceholderViewTypeNoNetwork 1, /** 没订单 */ CQPlaceholderViewTypeNoOrder, /** 没商品 */ CQPlaceholderViewTypeNoGoods, /** 美丽的妹纸 */ CQPlaceholderViewTypeBeautifulGirl }; #pragma mark - protocol class CQPlaceholderView; protocol CQPlaceholderViewDelegate NSObject /** 占位图的重新加载按钮点击时回调 */ - (void)placeholderView:(CQPlaceholderView *)placeholderView reloadButtonDidClick:(UIButton *)sender; end #pragma mark - interface interface CQPlaceholderView : UIView /** 占位图类型只读 */ property (nonatomic,assign,readonly) CQPlaceholderViewType type; /** 占位图的代理方只读 */ property (nonatomic,weak,readonly) id CQPlaceholderViewDelegate delegate; /** 构造方法 param frame 占位图的frame param type 占位图的类型 param delegate 占位图的代理方 return 指定frame、类型和代理方的占位图 */ - (instancetype)initWithFrame:(CGRect)frame type:(CQPlaceholderViewType)type delegate:(id)delegate; end .m文件 #import CQPlaceholderView.himplementation CQPlaceholderView #pragma mark - 构造方法 /** 构造方法 param frame 占位图的frame param type 占位图的类型 param delegate 占位图的代理方 return 指定frame、类型和代理方的占位图 */ - (instancetype)initWithFrame:(CGRect)frame type:(CQPlaceholderViewType)type delegate:(id)delegate{ if (self [super initWithFrame:frame]) { // 存值 _type type; _delegate delegate; // UI搭建 [self setUpUI]; } return self; } #pragma mark - UI搭建 /** UI搭建 */ - (void)setUpUI{ self.backgroundColor [UIColor whiteColor]; //------- 图片在正中间 -------// UIImageView *imageView [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width / 2 - 50, self.frame.size.height / 2 - 50, 100, 100)]; [self addSubview:imageView]; //------- 说明label在图片下方 -------// UILabel *descLabel [[UILabel alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(imageView.frame) 10, self.frame.size.width, 20)]; [self addSubview:descLabel]; descLabel.textAlignment NSTextAlignmentCenter; //------- 按钮在说明label下方 -------// UIButton *reloadButton [[UIButton alloc]initWithFrame:CGRectMake(self.frame.size.width / 2 - 60, CGRectGetMaxY(descLabel.frame) 5, 120, 25)]; [self addSubview:reloadButton]; [reloadButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; reloadButton.layer.borderColor [UIColor blackColor].CGColor; reloadButton.layer.borderWidth 1; [reloadButton addTarget:self action:selector(reloadButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; //------- 根据type创建不同样式的UI -------// switch (_type) { case CQPlaceholderViewTypeNoNetwork: // 没网 { imageView.image [UIImage imageNamed:网络异常]; descLabel.text 没网不约; [reloadButton setTitle:点击重试 forState:UIControlStateNormal]; } break; case CQPlaceholderViewTypeNoOrder: // 没订单 { imageView.image [UIImage imageNamed:订单无数据]; descLabel.text 暂无订单; [reloadButton setTitle:没有拉到 forState:UIControlStateNormal]; } break; case CQPlaceholderViewTypeNoGoods: // 没商品 { imageView.image [UIImage imageNamed:没商品]; descLabel.text 红旗连锁你的好邻居; [reloadButton setTitle:buybuybuy forState:UIControlStateNormal]; } break; case CQPlaceholderViewTypeBeautifulGirl: // 妹纸 { imageView.image [UIImage imageNamed:妹纸]; descLabel.text 你会至少在此停留3秒钟; [reloadButton setTitle:不爱妹纸 forState:UIControlStateNormal]; } break; default: break; } } #pragma mark - 重新加载按钮点击 /** 重新加载按钮点击 */ - (void)reloadButtonClicked:(UIButton *)sender{ // 代理方执行方法 if ([_delegate respondsToSelector:selector(placeholderView:reloadButtonDidClick:)]) { [_delegate placeholderView:self reloadButtonDidClick:sender]; } // 从父视图上移除 [self removeFromSuperview]; } end 详细说明 1.关于构造方法的设计 /**构造方法param frame 占位图的frameparam type 占位图的类型param delegate 占位图的代理方 return 指定frame、类型和代理方的占位图 */ - (instancetype)initWithFrame:(CGRect)frame type:(CQPlaceholderViewType)type delegate:(id)delegate; 三个参数说明 frame:决定占位图的大小和位置。之所以需要这个参数是因为这个占位图可能和你的tableView一样大也可能是全屏的。type:占位图的类型。这个参数决定占位图的展示样式。delegate:代理方。处理事件。2.为什么type和delegate要设置为只读 /** 占位图类型只读 */
property (nonatomic,assign,readonly) CQPlaceholderViewType type; /** 占位图的代理方只读 */ property (nonatomic,weak,readonly) id CQPlaceholderViewDelegate delegate; 因为这两个属性需要暴露出去但是我又不希望它们在外部被修改我希望构造方法是决定这个占位图属性的唯一方法。还有就是让在外部能直接修改的越少意外也就越少。 3.为什么我的这代理方法命名如此冗长 /** 占位图的重新加载按钮点击时回调 */
- (void)placeholderView:(CQPlaceholderView *)placeholderViewreloadButtonDidClick:(UIButton *)sender;可能有人会说你这个代理方法不就是想要执行重新加载数据方法嘛直接命名为reloadData不是多好的反正曾经懵懂的我看别人的代码时是这样想当然的认为的直到有一天我看了官方文档以及回想了一下系统给代理方法的命名。 其实代理方法的命名是一个非常讲究的东西我之所以这样命名是完全参照官方文档的命名规范的建议有疑问的瞅两眼delegate 命名。你也可以这样理解代理方法它描述的是某一个事件而不是事件要执行的某个方法。 4.为什么点击按钮后就直接将占位图移除? #pragma mark - 重新加载按钮点击
/** 重新加载按钮点击 */
- (void)reloadButtonClicked:(UIButton *)sender{// 代理方执行方法 if ([_delegate respondsToSelector:selector(placeholderView:reloadButtonDidClick:)]) { [_delegate placeholderView:self reloadButtonDidClick:sender]; } // 从父视图上移除 [self removeFromSuperview]; } 我之前的做法是写一个移除占位图的方法然后将这个方法暴露出去需要移除的时候就调用这个方法。后面想了想这样做完全是自找麻烦我们点击UIAlertView的按钮的时候这个alertView不就自动移除了吗而这个占位图不也可以看做是一个弹窗吗 为何这么6 使用方法 作为标准delegate传值的view使用方法类似于系统的UIAlertView。1. 引入delegate interface ViewController ()CQPlaceholderViewDelegate2. 初始化 CQPlaceholderView *placeholderView [[CQPlaceholderView alloc]initWithFrame:tableView.bounds type:CQPlaceholderViewTypeNoOrder delegate:self];
[tableView addSubview:placeholderView];看到没有我想在哪add就在哪add比那什么只能在tableView或collectionView上展示的强大多了。正是这个frame和完全开放的被add性决定了这个通用占位图的高度灵活性。 推了一下我的300多度近视眼镜 3. 处理回调 #pragma mark - Delegate - 占位图
/** 占位图的重新加载按钮点击时回调 */
- (void)placeholderView:(CQPlaceholderView *)placeholderView reloadButtonDidClick:(UIButton *)sender{switch (placeholderView.type) { case CQPlaceholderViewTypeNoGoods: // 没商品 { [self.view makeToast:买个球啊]; } break; case CQPlaceholderViewTypeNoOrder: // 没有订单 { [self.view makeToast:拉到就拉到]; } break; case CQPlaceholderViewTypeNoNetwork: // 没网 { [self.view makeToast:没网适合打排位]; } break; case CQPlaceholderViewTypeBeautifulGirl: // 妹纸 { [self.view makeToast:哦那你很棒棒哦]; } break; default: break; } } 对比DZNEmptyDataSet DZNEmptyDataSet 这是当前很受欢迎的一个库: A drop-in UITableView/UICollectionView superclass category for showing empty datasets whenever the view has no content to display 它通过一系列代理方法来决定占位图的显示样式及事件回调。平心而论很优秀但是我还是决定用我自己的。我的看法是(Im my opinion) DZNEmptyDataSet很强大它之所以如此强大是为了让大部分人可以直接拿来即可用它的目标是满足大部分开发者的一般常规需求所以它或许适合你但一定不是最适合你最适合你的一定是自己亲手打造的。还有它很强大以至于有些功能你都不需要。 窃以为知道其实现原理然后自己封装真正适合自己当前项目的框架才是王道。 多了些细节 demo 分享的人不少认真总结分享的人不多请不要吝惜你的star。github demo 作者无夜之星辰链接https://www.jianshu.com/p/beca3ac24031來源简书简书著作权归作者所有任何形式的转载都请联系作者获得授权并注明出处。 转载于:https://www.cnblogs.com/sundaysgarden/p/9452914.html