Commit f54f6fa7 authored by 艾娇平's avatar 艾娇平

添加baseList

parent 6c29debf
...@@ -17,4 +17,5 @@ Pod::Spec.new do |s| ...@@ -17,4 +17,5 @@ Pod::Spec.new do |s|
s.dependency 'GMPhobos' s.dependency 'GMPhobos'
s.dependency 'GMHud' s.dependency 'GMHud'
s.dependency 'GMKit' s.dependency 'GMKit'
s.dependency 'GMNetworking'
end end
//
// GMPageProfileModel.h
// GMBase
//
// Created by Mikasa on 2019/3/29.
//
// 初始化一个全局模式页面配置项
typedef NS_ENUM(NSInteger, GMPerPageType) {
GMPerPageTypeStartNum = 0,// 根据当前起始位置进行获取数据
GMPerPageTypePage = 1,// 根据当前页码进行获取数据
GMPerPageTypeOffset = 2 // 根据当前Offset进行获取数据
};// 分页类型
@interface GMPageProfileModel : NSObject
// 页面分页模式配置,默认使用GMPerPageTypeOffset
@property (nonatomic, assign) GMPerPageType perPageType;
// 页面背景颜色配置,默认whiteColor
@property (nonatomic, strong) UIColor *bgPageColor;
+ (instancetype)shareInstance;
@end
//
// GMPageProfileModel.m
// GMBase
//
// Created by Mikasa on 2019/3/29.
//
#import "GMPageProfileModel.h"
@implementation GMPageProfileModel
- (instancetype)init {
if (self = [super init]) {
// 默认使用GMPerPageTypeOffset
self.perPageType = GMPerPageTypeStartNum;
self.bgPageColor = [UIColor whiteColor];
}
return self;
}
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
static id _instance = nil;
dispatch_once(&onceToken, ^{
_instance = [[GMPageProfileModel alloc] init];
});
return _instance;
}
@end
//
// GMService.h
// GMBase
//
// Created by Mikasa on 2019/3/27.
//
#import <GMNetService/WMNetService.h>
@interface GMService : NSObject
/**
GMService 单例
@return shareInstance
*/
- (instancetype)shareInstance;
#pragma mark - Fetch RemoteData
@end
//
// GMService.m
// GMBase
//
// Created by Mikasa on 2019/3/27.
//
#import "GMService.h"
@implementation GMService
- (instancetype)shareInstance {
static dispatch_once_t onceToken;
static id _instance = nil;
dispatch_once(&onceToken, ^{
_instance = [[[self class] alloc] init];
});
return _instance;
}
@end
//
// GMCommonViewController.h
// GMBase
//
// Created by Mikasa on 2019/3/28.
//
#import "GMViewController.h"
#import "GMListViewModel.h"
#import <GMRefresh/GMRefreshFooter.h>
#import <GMRefresh/GMRefreshHeader.h>
@interface GMListViewController : GMViewController<UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource,GMPageListViewProtocol>
/** 快速获取tableView 未添加到当前GMBaseListViewController, 页面根据需要进行Add */
@property (nonatomic, strong) UITableView *tableView;
/** 快速获取collectionView 未添加到当前GMBaseListViewController, 页面根据需要进行Add */
@property (nonatomic, strong) UICollectionView *collectionView;
/** 基本布局样式 */
@property (nonatomic, strong) UICollectionViewLayout *collectionViewLayout;
@end
This diff is collapsed.
//
// GMViewController.h
// GMBase
//
// Created by Mikasa on 2019/3/27.
//
#import <GMKit/GMKit-umbrella.h>
#import "GMViewModel.h"
#import "OCNavigationBar.h"
#import "GMPageViewProtocol.h"
//@import GMHud;
#import <GMHud/GMHud-umbrella.h>
@interface GMViewController : UIViewController<GMPageViewProtocol>
/** 导航 */
@property (nonatomic, strong) OCNavigationBar *navigationBar;
/** 默认值为NO, 表示导航栏自动被WMBaseViewController管理, 永远在所有的view最上方。 */
@property (nonatomic, assign) BOOL controlNavigationByYou;
/** 点击重新加载视图调用方法 */
@property (nonatomic, assign) SEL reloadSelector;
/** 空/异常页面 默认展示空页面*/
@property (nonatomic, strong) GMEmptyView *emptyView;
@property (nonatomic, assign) GMPageType pageType;
/**
@brief 因为controller会有initWithCoder,init,initWithNib三种方式,为了避免子类代码的疏忽导致父类自定义init内容没有覆盖到,所以统一使用initController方法。需要调用super
页面埋点类最好都放在此处设置
*/
- (void)initController __attribute__((objc_requires_super));
/**
展示空/异常页面
@param type 页面类型
*/
- (void)showEmptyView:(GMEmptyViewType)type;
/** 隐藏空页面 */
- (void)hideEmptyView;
/** 点击空页面调用方法(reloadSelector)*/
- (void)emptyViewDidClickReload;
@end
//
// GMViewController.m
// GMBase
//
// Created by Mikasa on 2019/3/27.
//
#import "GMViewController.h"
@interface GMViewController ()<GMEmptyViewDelegate>
@end
@implementation GMViewController
#pragma mark - init
- (instancetype)init {
// 在init方法里调用initWithNibName:bundle,保证了WMBaseViewController里的initWithNibName不会再次被调用,也就是保证了initController方法不会被调用两次
self = [super initWithNibName:nil bundle:nil];
if (self) {
[self initController];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self initController];
}
return self;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
[self initController];
return self;
}
- (instancetype)initWithPageType:(GMPageType)pageType {
if (self = [super init]) {
self.pageType = pageType;
[self initController];
}
return self;
}
- (void)initController {
self.controlNavigationByYou = NO;
self.pageType = GMPageTypeNomal;
[self addPageObserver];
}
- (void)addPageObserver {}
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - View LifeCycle
- (void)viewDidLoad {
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeNone;
self.view.backgroundColor = [GMPageProfileModel shareInstance].bgPageColor;
// 添加子View
[self setupSubView];
}
- (void)setupSubView {}
- (void)layoutSubView {}
- (void)updateLayoutSubView {}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// 保证navigationBar 始终处于最上方位置
if (!self.controlNavigationByYou) {
[self.view bringSubviewToFront:self.navigationBar];
}
}
- (void)didMoveToParentViewController:(UIViewController *)parent {
[super didMoveToParentViewController:parent];
// 作为childController使用,但不是被push到 UINavigationController时,隐藏导航栏
if (parent != nil && ![parent isKindOfClass:[UINavigationController class]]) {
self.navigationBar.hidden = YES;
}
}
#pragma mark - Empty View
- (void)showEmptyView:(GMEmptyViewType)type {
self.emptyView.hidden = NO;
self.emptyView.type = type;
[self.view bringSubviewToFront:self.emptyView];
}
- (void)hideEmptyView {
self.emptyView.hidden = YES;
}
- (void)emptyViewDidClickReload {
[self hideEmptyView];
if (self.reloadSelector && [self respondsToSelector:self.reloadSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:self.reloadSelector];
#pragma clang diagnostic pop
}
}
#pragma mark - OCNavigationBar
- (void)hideLeftButtonForRootController {
if (self.navigationController.viewControllers.count == 1) {
_navigationBar.leftButton.hidden = YES;
}
}
- (void)setTitle:(NSString *)title {
[super setTitle:title];
self.navigationBar.title = title;
}
#pragma mark - OCNavigationBarDelegate
- (void)nearRightButtonClicked:(OCNavigationBarButton *)button {}
- (void)rightButtonClicked:(OCNavigationBarButton *)button {}
- (void)backAction:(OCNavigationBarButton *)button {
if ([self.parentViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigation = (UINavigationController *)self.parentViewController;
NSArray *controllers = navigation.viewControllers;
if (self.presentingViewController && controllers.count == 1) {
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
}else{
[self dismissViewControllerAnimated:YES completion:nil];
}
}
#pragma mark - Private Method
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleDefault;
}
#pragma mark - Lazy Loading
- (OCNavigationBar *)navigationBar {
if (!_navigationBar) {
OCNavigationBar *navigationBar = [OCNavigationBar new];
_navigationBar = navigationBar;
}
if (!_navigationBar.superview) {
[self.view addSubview:_navigationBar];
}
[_navigationBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.right.mas_equalTo(0);
make.height.mas_equalTo(OCNavigationBar.barHeight);
}];
return _navigationBar;
}
- (GMEmptyView *)emptyView {
if (!_emptyView) {
GMEmptyView *emptyView = [GMEmptyView new];
emptyView.hidden = YES;
emptyView.delegate = self;
emptyView.type = GMEmptyViewTypeEmpty;
_emptyView = emptyView;
}
if (!_emptyView.superview) {
[self.view addSubview:_emptyView];
}
CGFloat emptyViewTop = [self.parentViewController isKindOfClass:[UINavigationController class]]?OCNavigationBar.statusBarHeight:0;
[_emptyView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.bottom.mas_equalTo(0);
make.top.mas_equalTo(emptyViewTop);
}];
return _emptyView;
}
@end
//
// GMListViewModel.h
// GMBase
//
// Created by Mikasa on 2019/3/28.
//
#import <GMNetService/WMNetService.h>
#import "GMViewModel.h"
#import <GMNetworking/GMNetworking-Swift.h>
//@import GMNetworking;
@interface GMListViewModel : GMViewModel
/** 是否需要下拉刷新 默认YES*/
@property (nonatomic, assign) BOOL needHeaderRefresh;
/** 是否上拉加载更多 默认YES*/
@property (nonatomic, assign) BOOL needFooterRefresh;
/** 是否需要结束掉上拉加载在没有更多数据的时候 默认YES*/
@property (nonatomic, assign) BOOL needEndRefreshNoMoreData;
/** 是否需要立即加载数据 默认YES*/
@property (nonatomic, assign) BOOL immediateLoad;
/** 分页类型 默认GMPerPageTypeStartNum */
@property (nonatomic, assign) GMPerPageType perPageType;
/** 请求uri */
@property (nonatomic, copy) NSString *uri;
/** 请求httpMethod */
@property (nonatomic, assign) GMHTTPMethod httpMethod;
/** 请求参数 */
@property (nonatomic, strong) NSMutableDictionary *params;
/** @brief 获取http数据分页第一页起始位置,默认为0,下一页为startNum+每页的数据条数(默认为10) */
@property (nonatomic,assign) NSInteger startNum;
/** @brief 获取http数据,每页获取数据(默认为10) */
@property (nonatomic,assign) NSInteger count;
/** @brief 因本地去重复被删掉的数据count */
@property (nonatomic, assign) NSInteger deleteCount;
/** @brief 获取http数据,列表总数量) */
@property (nonatomic, assign) NSInteger totalCount;
/** @brief 获取http数据,当前页码(默认为1)*/
@property (nonatomic, assign) NSInteger page;
/** @brief 获取到的列表数据 */
@property (nonatomic, strong) NSMutableArray *dataArray;
// 清理所有数据
- (void)clearAllData;
- (void)excuteFetchDataSuccessBlock:(HttpSuccessBlock)successBlock
failBlock:(HttpFailedBlock)failBlock;
- (void)handleFooterRereshing;
- (void)handleHeaderRefreshing;
@end
//
// GMListViewModel.m
// GMBase
//
// Created by Mikasa on 2019/3/28.
//
#import "GMListViewModel.h"
//#import <GMNetworking/GMNetworking-umbrella.h>
//@import GMNetService
@implementation GMListViewModel
- (instancetype)init {
if (self = [super init]) {
self.page = 1;
self.count = 10;
self.startNum = 0;
self.deleteCount = 0;
self.totalCount = 0;
self.needEndRefreshNoMoreData = YES;
self.immediateLoad = YES;
self.needFooterRefresh = YES;
self.needHeaderRefresh = YES;
self.httpMethod = GMHTTPMethodGet;
// 默认取配置项,用于全局更改
self.perPageType = [GMPageProfileModel shareInstance].perPageType;
self.dataArray = [NSMutableArray array];
self.params = [NSMutableDictionary dictionary];
self.uri = @"";
}
return self;
}
#pragma mark - buildParams
- (void)buildParams {
[self.params setObject:@(self.count) forKey:@"count"];
if (self.perPageType == GMPerPageTypeStartNum) {
[self.params setObject:@(self.startNum) forKey:@"start_num"];
} else if (self.perPageType == GMPerPageTypePage) {
[self.params setObject:@(self.page) forKey:@"page"];
}
}
#pragma mark - HeaderFooterRereshing
- (void)handleHeaderRefreshing {
self.page = 1;
[self.dataArray removeAllObjects];
[self fetchRemoteData];
}
- (void) handleFooterRereshing{
self.page ++;
self.startNum = self.deleteCount + self.dataArray.count;
[self fetchRemoteData];
}
// 获取远程数据
- (void)fetchRemoteData {}
#pragma mark - Fetch RemoteData
- (void)excuteFetchDataSuccessBlock:(HttpSuccessBlock)successBlock
failBlock:(HttpFailedBlock)failBlock {
[self buildParams];
__weak __typeof(self)weakSelf = self;
[GMNetworking requestOCWithApi:self.uri method:GMHTTPMethodGet parameters:self.params completion:^(GMResponseOC *responseObject) {
if (responseObject.isSuccess) {
if([responseObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *dict = (NSDictionary *)responseObject;
NSInteger code = [[dict objectForKey:@"error"] integerValue];
if (code == APIStatusCodeFailed) {
[weakSelf dealRemoteFailData];
if (failBlock) {
failBlock(responseObject.message);
}
}
} else {
[weakSelf dealRemoteSuccessData:responseObject.data];
if (successBlock) {
successBlock(responseObject.data);
}
}
} else {
[weakSelf dealRemoteFailData];
if (failBlock) {
failBlock(responseObject.message);
}
}
}];
}
// 清理所有数据
- (void)clearAllData {
self.deleteCount = 0;
self.totalCount = 0;
[self.dataArray removeAllObjects];
}
#pragma mark - Fetch RemoteData
- (void)dealRemoteSuccessData:(id)responseObject {}
- (void)dealRemoteFailData {
if (self.page != 1 && self.startNum != 0 ) {
self.page--;
self.startNum = self.startNum - self.dataArray.count;
}
}
@end
//
// GMPageViewProtocol.h
// GMBase
//
// Created by Mikasa on 2019/3/28.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, GMPageType) {
GMPageTypeNomal = 0,// 普通Viewtroller
GMPageTypeTableView = 1,// 拥有一个TableView Viewtroller
GMPageTypeCollectionView = 2 // 拥有一个CollectView Viewtroller
};
@protocol GMPageViewProtocol <NSObject>
/**
初始化获取一个ViewController
@param pageType 三种类型页面
GMPageTypeNomal : 普通Viewtroller
GMPageTypeTableView : 拥有一个TableView Viewtroller
GMPageTypeCollectionView : 拥有一个CollectView Viewtroller
@return ViewController
*/
- (instancetype)initWithPageType:(GMPageType)pageType;
@optional
/**
初始化获取一个ViewController
@param viewModel viewModel
@return ViewController
*/
- (instancetype)initWithViewModel:(GMViewModel *)viewModel;
/**
初始化获取一个ViewController
@param viewModel viewModel
@param pageType 三种类型页面
GMPageTypeNomal : 普通Viewtroller
GMPageTypeTableView : 拥有一个TableView Viewtroller
GMPageTypeCollectionView : 拥有一个CollectView Viewtroller
@return ViewController
*/
- (instancetype)initWithViewModel:(GMViewModel *)viewModel pageType:(GMPageType)pageType;
- (void)addPageObserver;
#pragma mark - Setup SubView
/** 添加子View */
- (void)setupSubView;
/** 布局子View */
- (void)layoutSubView;
/** 更新布局子View */
- (void)updateLayoutSubView;
/** 获取当前页面listView */
- (UIScrollView *)currentSrollView;
@end
@protocol GMPageListViewProtocol <NSObject>
#pragma mark - DataRefresh
/** 下拉刷新 */
- (void)headerRefresh;
/** 上拉加载*/
- (void)footerRefresh;
#pragma mark - Update UI
/** 获取数据后更新UI */
/**
获取数据完成后更新UI
@param success 是否成功获取数据
*/
- (void)updateUIWithSuccess:(BOOL)success;
#pragma mark - DataRefresh
/** 加载远程数据 */
- (void)loadRemoteData;
/** 重新加载数据(清理当前数据+初始化请求) */
- (void)reloadDateRefresh;
@end
//
// GMServiceProtocal.h
// GMBase
//
// Created by Mikasa on 2019/3/28.
//
#import "GMService.h"
//@import GMNetworking;
#import <GMNetworking/GMNetworking-Swift.h>
@protocol GMServiceProtocol <NSObject>
@property (nonatomic, strong) GMService *service;
/**
* @brief 构造Http请求的params的值,如果不构造,则params为nil
*/
- (void)buildParams;
@end
@protocol GMDataDealProtocol <NSObject>
/**
* @brief 处理远程数据成功获取后的处理
*
* @param responseObject 远程获取的数据
*/
- (void)dealRemoteSuccessData:(id)responseObject;
/**
* @brief 处理远程数据失败获取后的处理
*/
- (void)dealRemoteFailData:(NSString *)message;
/**
* @author wangyang, 15-11-25 15:11:53
*
* @brief 解析去重数组,并且添加到 self.dataArray 中
* @param array JSON 中的 Object 数组,也可以是转成 Model 的 array
* @param buildBlock 用这个把 dic 转为 Model 再返回。可以为NULL。为NULL时一般用于 array 已经是转成 Model 的 array
* @since 5.6.0
*/
- (void)deduplicationForArray:(NSArray *)array buildModelBlock:(id (^)(NSDictionary *dic))buildBlock;
/**
* @author wangyang, 16-01-14 16:01:53
*
* @brief 将数组去重,然后返回组织好数据的新model数组
* @param array 待去重的数据
* @param buildBlock 解析器
* @return 使用解析器组织好Model的数据
* @since 5.8.0
*/
- (NSArray *)deduplicationArrayFromArray:(NSArray *)array buildModelBlock:(id (^)(NSDictionary *dic))buildBlock;
@end
//
// GMListViewModel.h
// GMBase
//
// Created by Mikasa on 2019/3/8.
//
#import <GMNetService/WMNetService.h>
#import "GMServiceProtocol.h"
#import "GMPageProfileModel.h"
/**
* @author wangyang, 15-09-26 10:09:06
*
* @brief 通用网络请求的回调
* @param message 服务器返回的 message
* @param success YES 表示请求成功;
* @param data 服务器返回的 json 中的 data 字段
* @since 5.2.0
*/
typedef void (^FinishBlock) (NSString *message, BOOL success, id data);
//@import GMNetworking;
@interface GMViewModel : NSObject<GMServiceProtocol,GMDataDealProtocol>
@property (nonatomic, strong) id<GMServiceProtocol> serviceModel;
//@property (nonatomic, strong) GMPageProfileModel *pageProfile;
/** 单个列表请求方法(仅针对简单列表页面快速进行获取数据) */
//@property (nonatomic, assign) SEL remoteDataSelector;
- (instancetype)initWithServices:(id<GMServiceProtocol>) serviceModel;
@end
//
// GMListViewModel.m
// GMBase
//
// Created by Mikasa on 2019/3/8.
//
#import "GMViewModel.h"
@implementation GMViewModel
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment