關于runtime的介紹這里就不做記錄了,簡書內搜索 “runtime”一大堆。曽看到過一篇介紹runtime的文章,末尾寫了一句話:用runtime如果不是為了裝X,那將毫無意義。那么今天,我就裝一回,用一個實際的需求(每個項目都能用到哦)來驗證runtime的作用之一 ,給分類動態添加屬性。
需求:當網絡連接錯誤或者接口返回 code= 0 的時候,頁面如下:
網絡請求失敗.png
有人說了,嗨,就這個需求......的確,就這個需求,但今天是通過runtime來實現。
1.準備工作:準備一個xib視圖
NoNetWorkView.xib.png
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];
}
通過以上介紹,是不是可以舉一反三呢?當沒收藏列表中沒收藏,地址列表中沒地址,訂單列表中沒訂單等等等等,趕緊用起來吧。
以上。