关于runtime的介绍这里就不做记录了,简书内搜索 “runtime”一大堆。曽看到过一篇介绍runtime的文章,末尾写了一句话:用runtime如果不是为了装X,那将毫无意义。那么今天,我就装一回,用一个实际的需求(每个项目都能用到哦)来验证runtime的作用之一 ,给分类动态添加属性。
需求:当网络连接错误或者接口返回 code= 0 的时候,页面如下:
有人说了,嗨,就这个需求......的确,就这个需求,但今天是通过runtime来实现。
1.准备工作:准备一个xib视图
2 新建一个UIView的分类 UIView+State
UIView+State.h 文件代码如下
#import <UIKit/UIKit.h>
@protocol UIViewStateDelegate <NSObject>
@optional
- (void)xs_noNetWorkViewStateShouldChnaged; //点击刷新页面代理
@end
@interface UIView (State)
@property (weak, nonatomic) id<UIViewStateDelegate> stateDelegate;
- (void)xs_switchToNoNetWorkState;//当网络连接错误时加载NoNetworkView
- (void)xs_switchToContentState;//当网络连接正常时移除NoNetworkView
@end
UIView+State.m文件代码如下
#import "UIView+State.h"
#import <objc/runtime.h>//必须导入
@interface UIView ()
@property (strong, nonatomic) UIView *noNetworkView;//添加属性
@end
@implementation UIView (State)
- (void)xs_switchToNoNetWorkState {
if (self.noNetworkView == nil) {
self.noNetworkView = [[[NSBundle mainBundle] loadNibNamed:@"NoNetWorkView" owner:nil options:nil] objectAtIndex:0];
}
[self addSubview:self.noNetworkView];
[self bringSubviewToFront:self.noNetworkView];
self.noNetworkView.frame = self.bounds;
if (self.stateDelegate && [self.stateDelegate respondsToSelector:@selector(xs_noNetWorkViewStateShouldChnaged)]) {
self.noNetworkView.userInteractionEnabled = YES;
[self.noNetworkView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.stateDelegate action:@selector(xs_noNetWorkViewStateShouldChnaged)]];//添加点击手势
}
}
- (void)xs_switchToContentState {
[self.noNetworkView removeFromSuperview];
}
#pragma mark - getters and setters
//关联
//objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略
static char stateDelegateKey;
- (id<UIViewStateDelegate>)stateDelegate {
return objc_getAssociatedObject(self, &stateDelegateKey);
}
- (void)setStateDelegate:(id<UIViewStateDelegate>)stateDelegate {
objc_setAssociatedObject(self, &stateDelegateKey, stateDelegate, OBJC_ASSOCIATION_ASSIGN);
}
static char noNetWorkViewKey;
- (UIView *)noNetworkView {
return objc_getAssociatedObject(self, &noNetWorkViewKey);
}
- (void)setNoNetworkView:(UIView *)noNetworkView {
objc_setAssociatedObject(self, &noNetWorkViewKey, noNetworkView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
3.UIView+State 分类的使用
3.1在controller.m中 先导入文件
#import "UIView+State.h"
3.2 遵循代理
@interface ZLMComplainListViewController ()<UIViewStateDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
self.view.stateDelegate = self;
}
3.3 在适当条件下调分类方法
-(void)loadData:(NSInteger )page{
NSString *urlStr = [NSString stringWithFormat:@"%@/complaint/list", host];
NSDictionary *param = @{
@"page":@(page)
};
if (page == 1) {
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
}
XSAPIManager *manager = [XSAPIManager manager];
[manager GET:urlStr parameters:param success:^(id responseObject) {
self.complainListBridge = [ComplainList mj_objectWithKeyValues:responseObject];//将json数据映射到model中
if (self.complainListBridge.code == 1) {
[self.view xs_switchToContentState];//如果网络请求成功并返回code=1,移除网络连接错误的视图
} else {
[self.view xs_switchToNoNetWorkState];//返回code= 0 ,加载网络连接的视图
}
[self.tableview reloadData];
[MBProgressHUD hideAllHUDsForView:weakSelf.view animated:YES];
} failure:^(NSError *error) {
[MBProgressHUD hideAllHUDsForView:weakSelf.view animated:YES];
[self.view xs_switchToNoNetWorkState];//网络连接错误 ,加载网络连接的视图
}];
}
3.4 实现代理方法 点击刷新
#pragma mark - UIViewStateDelegate
- (void)xs_noNetWorkViewStateShouldChnaged {
[self loadData:1];
}
通过以上介绍,是不是可以举一反三呢?当没收藏列表中没收藏,地址列表中没地址,订单列表中没订单等等等等,赶紧用起来吧。
以上。