FFFramework的实现


前言

最近,结合公司的项目,在前人的基础上整理了一个Framework的一个东西,主要包含了一些常用的category 整理; model 基类的使用,基于MJExtension 实现一个model 基类,模型数据的使用可以继承该基类;网络请求的使用,对于 AFNetworking 的封装,可实现数据请求和网络下载;第三方分享的封装,可以直接使用,分享到QQ,微信, 微博;View的一些使用,1)UITableView和UICollectionView的封装使用,实现UITableView和UICollectionView的上拉刷新和下拉加载(PS:不是三方的刷新和加载)2)自定义的TabBar;UIViewController的使用,实现一个基类的ViewController,实现相关的属性设置,VC的使用继承该基类;还有一些帮助类的使用。FFFramework暂不支持Cocopods。


项目结构介绍


这里写图片描述


具体使用

  • Category

Category里面主要是一些常用分类,比如设备类型,文件管理,日期设置,颜色处理和图片处理等,没什么值得具体说的,具体用的时候直接拿来用就可以了。附张图看一眼吧:


这里写图片描述

  • Models

Model里面会有一个叫做FFBaseModel 的基类,凡是关于模型数据的都可以集成该基类。如图:


这里写图片描述

用法也很简单,是基于MJExtension ,和 MIExtension 的使用是一致的,只不过在外层包装了一下而已。支持字典转模型,字典数组转模型数组, 模型数组转字典数组等。下面是一些常用方法:

@interface FFBaseModel : NSObject
- (NSDictionary *)ff_toKeyValue;
- (void)ff_modelsDidFinishConvertingToKeyValues;
- (void)ff_keyvaluesDidFinishConvertingToModels;

// 属性名替换 
+ (NSDictionary *)ff_replaceKeyFromPropertyName;
+ (NSDictionary *)ff_objectClassInArray;

// 可忽略的属性名
+ (NSArray *)ff_ignoredPropertyNames;

// 字典转模型
+ (instancetype)ff_modelFromKeyValue:(NSDictionary *)keyValue;

+ (NSArray *)ff_keyValuesFromModels:(NSArray *)models;

// 字典数组转模型数组
+ (NSArray *)ff_modelsFromKeyValues:(NSArray *)keyvalues;
+ (NSArray *)ff_allowedCodingPropertyNames;
+ (NSArray *)ff_ignoredCodingPropertyNames;

@end
  • Network

Network里面包含网络数据的请求和上传,以及网络数据下载,基于AFNetworkingAFNetworking 的封装使用,包括 FFBaseRequestFFBaseDownloadRequest , 如下:


这里写图片描述

1) 先看 FFBaseRequest.h 文件

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@class FFBaseRequest;

typedef NS_ENUM(NSUInteger, FFRequestMethod) {
    FFRequestMethodGet,
    FFRequestMethodPost,
    FFRequestMethodPut,
    FFRequestMethodDelete
};

typedef NS_ENUM(NSInteger, FFNetworkReachabilityStatus) {
    FFNetworkReachabilityStatusUnknown          = -1,
    FFNetworkReachabilityStatusNotReachable     = 0,
    FFNetworkReachabilityStatusReachableViaWWAN = 1,
    FFNetworkReachabilityStatusReachableViaWiFi = 2,
};

typedef NS_ENUM(NSUInteger, FFRequestError) {
    FFRequestErrorNetwork = 0
};

static NSString *Key_Model = @"Key_Model";

typedef void(^reqSuccessBlock)(FFBaseRequest *request);
typedef void(^reqCancelBlock)(FFBaseRequest *request);
typedef void(^reqFailureBlock)(FFBaseRequest *request, NSError *error);
typedef void(^reqUploadBlock)(FFBaseRequest *request, NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite);

@interface FFBaseRequest : NSObject
/**请求路径*/
@property (nonatomic, copy,   readonly) NSString *requestUrl;
/**请求参数*/
@property (nonatomic, strong, readonly) NSDictionary *requestParameters;
/**上传二进制数据数组*/
@property (nonatomic, strong, readonly) NSMutableArray *binaryParameterArray;
/**返回字典数据*/
@property (nonatomic, strong, readonly) NSMutableDictionary *resultDict;
/**结果数组*/
@property (nonatomic, strong, readonly) NSMutableArray *resultArray;
/**结果字符串*/
@property (nonatomic, copy)             NSString *resultString;
@property (nonatomic, strong, readonly) UIImage *responseImage;
/**是否请求成功*/
@property (nonatomic, assign, readonly) BOOL isSuccess;

/**
 *  网络数据请求
 *
 *  @param parameters 上传参数
 *  @param successBlock 成功回调
 *  @param cancelBlock 取消回调
 *  @param failureBlock 失败回调
 */
+ (void)requestParameters:(NSDictionary *)parameters
             successBlock:(reqSuccessBlock)successBlock
              cancelBlock:(reqCancelBlock)cancelBlock
             failureBlock:(reqFailureBlock)failureBlock;
/**
 *  执行请求
 *
 *  @param parameters   请求参数(非二进制文件)
 *  @param binaryArray  上传的二进制文件(ZZBinaryData对象)
 *  @param successBlock 成功回调
 *  @param cancelBlock  取消回调
 *  @param failureBlock 失败回调
 *  @param uploadProcessBlock 上传进度回调
 */
+ (void)requestParameters:(NSDictionary *)parameters
              binaryArray:(NSMutableArray *)binaryArray
             successBlock:(reqSuccessBlock)successBlock
              cancelBlock:(reqCancelBlock)cancelBlock
             failureBlock:(reqFailureBlock)failureBlock
        uplodProcessBlock:(reqUploadBlock)uploadProcessBlock;

/**获取请求地址*/
- (NSString *)getRequestUrl;

/// 是否正在请求数据
+ (BOOL)isRequesting;

/**获取当前网络类型*/
+ (FFNetworkReachabilityStatus)fetchReachabilityStatus;

/**启动网络监听*/
+ (void)starNetWorkReachability;

#pragma mark - Children Class
- (NSString *)getRequestHost;
- (NSString *)getRequestQuery;
- (NSString *)getUserAgent;
/**请求头设置*/
- (NSDictionary<NSString *, NSString *> *)getCustomHeaders;
/**请求方式(默认GET)*/
- (FFRequestMethod)getRequestMethod;
/**请求参数*/
- (NSDictionary *)getDefaultParameters;
/**数据解析*/
- (void)processResult;
/**取消请求*/
+ (void)cancelTheRequest;

#pragma mark- 以下可根据服务器返回自行设置
/**是否成功*/
- (BOOL)success;
/**请求失败错误信息*/
- (NSString *)errorMsg;
/**数据总数*/
- (NSInteger)totalCount;
/**是否有数据(通常是分页请求数据)*/
- (BOOL)hasMoreData;
@end

已有相关的注释,具体查看可以看源项目, 我会在最后把地址贴一下,现在结合一个接口, 看一下具体使用,一般数据请求和UITableView连用,我一起贴出来了:

首先,继承FFBaseRequest 创建一个通用请求类 TestRequest

#import "FFBaseRequest.h"

extern NSString * const FORMAL_SERVER_URL;
extern NSString * const TEST_SERVER_URL;

@interface TestRequest : FFBaseRequest

@end

/*******************************************/

#import "TestRequest.h"

// 以豆瓣的接口为例
NSString * const FORMAL_SERVER_URL = @"https://api.douban.com/v2/";    // 正式服务器
NSString * const TEST_SERVER_URL = @"https://api.douban.com/v2/";   // 测试服务器

@implementation TestRequest

#pragma mark - Methods
// 设置getRequestHost的目的是为了方便,如:https://api.douban.com/v2/book/search?q=“美女”&start = 0&count = 20 这个地址,https://api.douban.com/v2/ 这是通用的,可单独提取出来,如针对图书相关的接口,将book/search?q=“美女”&start = 0&count = 20拼起来即可。
- (NSString *)getRequestHost {  
    return FORMAL_SERVER_URL;
    //    return TEST_SERVER_URL;
}

- (BOOL)isSuccess {
    return [self success];
}

- (BOOL)success {
    if ([self.resultDict.allKeys containsObject:@"status"]) {
        NSDictionary *dict = self.resultDict[@"status"];
        NSInteger code = [[NSString stringWithFormat:@"%@", dict[@"code"]] integerValue];
        return code == 1;
    }
    return false;
}

- (NSString *)errorMsg {
    if ([self.resultDict.allKeys containsObject:@"status"]) {
        NSDictionary *dict = self.resultDict[@"status"];
        return dict[@"msg"];
    }
    return @"";
}


#pragma mark - 可根据具体返回数据设置相关属性
- (NSInteger)totalCount {
    return [self.resultDict[@"total"] integerValue];
}

@end

接着,以豆瓣的图书搜索为例,继承 TestRequest 创建一个图书搜索请求 TestARequest

/**
 获取书籍信息的接口
 */

/**
GET  https://api.douban.com/v2/book/search
参数       意义         备注
q       查询关键字     q和tag必传其一
tag     查询的tag        q和tag必传其一
start   取结果的offset  默认为0
count   取结果的条数    默认为20,最大为100
返回:返回status=200,
{
    "start": 0,
    "count": 10,
    "total": 30,
    "books" : [Book, ]
}
*/


#import "TestRequest.h"

@interface TestARequest : TestRequest

@end

/*******************************************/

#import "TestARequest.h"
#import "TestModel.h" // 图书模型
@implementation TestARequest
// https://api.douban.com/v2/book/search?q=“美女”&start = 0&count = 20, https://api.douban.com/v2/ 已提取出来, 由于q=“美女”&start = 0&count = 20中 q ,start, count 可能会有改变,故不能写死, 在 getRequestQuery方法中拼接book/search? 即可。  
- (NSString *)getRequestQuery {
    return @"book/search?";
}

// 进行数据解析,字典数组转模型
- (void)processResult {
    NSArray *results = self.resultDict[@"books"];
    NSArray *books = [TestModel ff_modelsFromKeyValues:results];
    if (books != nil) {
        [self.resultDict setObject:books forKey:Key_Model];
    }
}

准备工作已完成,下面就在ViewController里面请求数据:

// 下拉刷新和上拉加载可先忽略
- (void)getNetData:(BOOL)isRefresh {
    if ([TestARequest isRequesting]) {
        return;
    }
    __weak typeof(self) WS = self;

    NSInteger page = isRefresh ? 1 : _page + 1;
    NSDictionary *parameter = @{@"q": @"美女",
                                @"start": @(page),
                                @"count": @20};

    // 1.设置下拉刷新 (不需要的话可去掉)
    id refreshBlock = ^{
        [WS getNetData:YES];
    };
    [self.tableView setRefreshBlock:refreshBlock];

    // 回调成功Block
    id successBlock = ^(FFBaseRequest *request){

        NSLog(@"请求路径-->> %@",request.requestUrl); // 这时请求路径就是一个完成的地址了。 
        NSLog(@"请求参数-->> %@",request.requestParameters);
        NSLog(@"请求结果-->> %@",request.resultDict);

        // 2.设置分页数
        _page = page;

        // 3.获取数据
        NSArray *arrResult = request.resultDict[Key_Model];
        if (isRefresh) {
            WS.books = arrResult;
        } else {
            NSMutableArray *arrTemp = [NSMutableArray arrayWithArray:WS.books];
            [arrTemp addObjectsFromArray:WS.books];
            WS.books = arrTemp;
        }

        // 4.设置上拉加载(不需要可去掉)
        id moreBlock = ^ {
            [WS getNetData:NO];
        };
        [WS.tableView setMoreBlock:request.totalCount > WS.books.count ? moreBlock : nil];

        // 5.完成加载
        [WS.tableView didFinishedLoading];

        // 6.数据刷新
        [WS.tableView reloadData];
    };

    // 回调取消Block
    id cancleBlock = ^(FFBaseRequest *request) {
        [WS.tableView didFinishedLoading];
    };

    // 回调失败Block
    id failureBlock = ^(FFBaseRequest *request, NSError *error){
        [WS.tableView didFinishedLoading];
        NSLog(@"---> %@",error.localizedDescription);
    };
    [TestARequest requestParameters:parameter successBlock:successBlock cancelBlock:cancleBlock failureBlock:failureBlock];
}

到此,一个数据请求就算完成了,这样更加模块化,更加好维护。。。。

2) 接着看FFBaseDownloadRequest.h

#import <Foundation/Foundation.h>

@class FFBaseDownloadRequest;

extern NSString * const FFDownloadErrorReasonKey;
extern NSString * const FFDownloadDoDownloadBlockKey;
extern NSString * const FFDownloadAllowUseMobileNetworkKey;
extern NSString * const FFDownloadAllowUseMobileNetworkNotification;


typedef void(^ProgressBlock)(float progress, NSUInteger bytesRead, unsigned long long totalRead, unsigned long long totalExpectedToRead);
typedef void(^SuccessBlock)(FFBaseDownloadRequest *request, id responseObject);
typedef void(^CancelBlock)(FFBaseDownloadRequest *request);
typedef void(^FailureBlock)(FFBaseDownloadRequest *request, NSError *error);

@interface FFBaseDownloadRequest : NSObject
/**
 * 下载路径(文件夹)
 */
@property (nonatomic, strong, readonly) NSString *downloadPath;
@property (nonatomic, strong, readonly) NSString *fileName;
/**
 * 下载文件绝对路径
 */
@property (nonatomic, strong, readonly) NSString *filePath;

/**
 *  下载文件
 *
 *  @param URLStirng     文件链接
 *  @param fileName      文件名
 *  @param progressBlock 下载进度回调
 *  @param successBlock  下载成功回调
 *  @param failureBlock  下载失败回调
 *
 *  @return 下载任务
 */
+ (FFBaseDownloadRequest *)downloadFileWithURLString:(NSString *)URLStirng
                                        fileName:(NSString *)fileName
                                   progressBlock:(ProgressBlock)progressBlock
                                    successBlock:(SuccessBlock)successBlock
                                     cancelBlock:(CancelBlock)cancelBlock
                                    failureBlock:(FailureBlock)failureBlock;
/**
 *  下载文件
 *
 *  @param URLStirng     文件链接
 *  @param fileName      文件名
 *  @param downloadPath  下载位置
 *  @param progressBlock 下载进度回调
 *  @param successBlock  下载成功回调
 *  @param failureBlock  下载失败回调
 *
 *  @return 下载任务
 */
+ (FFBaseDownloadRequest *)downloadFileWithURLString:(NSString *)URLStirng
                                    downloadPath:(NSString *)downloadPath
                                        fileName:(NSString *)fileName
                                   progressBlock:(ProgressBlock)progressBlock
                                    successBlock:(SuccessBlock)successBlock
                                     cancelBlock:(CancelBlock)cancelBlock
                                    failureBlock:(FailureBlock)failureBlock;

/**
 *  暂停下载文件
 *
 *  @param downloadRequest 下载任务
 */
+ (void)pauseWithDownloadRequest:(FFBaseDownloadRequest *)downloadRequest;

/**
 *  恢复下载文件
 *
 *  @param downloadRequest 下载请求
 */
+ (void)resumeWithDownloadRequest:(FFBaseDownloadRequest *)downloadRequest;

/**
 *  获取文件大小
 *
 *  @param path 本地路径
 *
 *  @return 文件大小
 */
- (unsigned long long)fileSizeForPath:(NSString *)path;
/**
 * 暂停下载
 */
- (void)pauseDownload;
/**
 * 恢复下载
 */
- (void)resumeDownload;
/**
 * 取消下载
 */
- (void)cancelDownload;
/**
 * 是否正在下载
 */
- (BOOL)isDownloading;
/**
 * 是否完成
 */
- (BOOL)finished;
/**
 * 移除Cache
 */
+ (void)removeAllCache;

网络数据下载,简单使用 :

- (void)downloadData {
    // http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.5.1.dmg
    NSString *path = [kCachePath stringByAppendingPathComponent:@"QQ"];

    if (![NSFileManager isDirectoryExist:path]) {
        [NSFileManager createDirectorysAtPath:path];
    }

    [FFBaseDownloadRequest downloadFileWithURLString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.5.1.dmg" downloadPath:path fileName:[NSString stringWithFormat:@"%@", @"1.zip"] progressBlock:^(float progress, NSUInteger bytesRead, unsigned long long totalRead, unsigned long long totalExpectedToRead) {

        NSLog(@"---------->> %f", progress);

    } successBlock:^(FFBaseDownloadRequest *request, id responseObject) {

        NSLog(@">> %@",request.filePath);
    } cancelBlock:^(FFBaseDownloadRequest *request) {

    } failureBlock:^(FFBaseDownloadRequest *request, NSError *error) {
        NSLog(@" ---->> %@",error.localizedDescription);
    }];
}
  • ShareKit

ShareKit里面包含分享都QQ,微信,微博 第三方平台,傻瓜式分享,只需要申请相对应的AppKey 和 AppSecretKey,设置好相关的白名单,就能实现分享啦~~。


这里写图片描述

下面我们来看看简单使用:
ShareContentInfo 类设置分享信息,包含分享的类型(文字,链接等)

#import "FFBaseModel.h"
#import "FFAuthInfo.h"

typedef NS_ENUM(NSUInteger, ShareContentType) {
    ShareContentType_None,
    ShareContentType_Text,
    ShareContentType_Link,
    ShareContentType_Image
};

@interface ShareContentInfo : FFBaseModel
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, strong) NSString *urlStr;
@property (nonatomic, strong) NSString *imgPath;
@property (nonatomic, strong) NSData   *objData;
@property (nonatomic, assign) ShareContentType contentType;
@property (nonatomic, assign) ShareType shareType;


/**
 *  获取分享信息
 *
 *  @param title 标题
 *  @param content 内容
 *  @param contentType 分享的类型
 *  @return ShareContentInfo
 */
+ (instancetype)shareTitle:(NSString *)title content:(NSString *)content contentType:(ShareContentType)contentType;

/**
 *  获取分享信息
 *
 *  @param title 标题
 *  @param content 内容
 *  @param url 链接
 *  @param imgPath 图片地址
 *  @param contentType 分享的类型
 *  @return ShareContentInfo
 */
+ (instancetype)shareTitle:(NSString *)title content:(NSString *)content url:(NSString *)url imagePath:(NSString *)imgPath contentType:(ShareContentType)contentType;

/**
 *  获取分享信息
 *
 *  @param title 标题
 *  @param content 内容
 *  @param url 链接
 *  @param imgPath 图片地址
 *  @param objData 图片二进制文件
 *  @param contentType 分享的类型
 *  @return ShareContentInfo
 */
+ (instancetype)shareTitle:(NSString *)title content:(NSString *)content url:(NSString *)url imagePath:(NSString *)imgPath objData:(NSData *)objData contentType:(ShareContentType)contentType;

FFBaseShareCenter 类设置分享:

typedef void(^ShareSuccessBlock)();
typedef void(^ShareCancelBlock)(BOOL cancelled);
typedef void(^ShareFailureBlock)(NSError *error);

typedef NS_ENUM(NSUInteger, InstallClientType) {
    InstallClientType_None,
    InstallClientType_QQ,
    InstallClientType_QZone,
    InstallClientType_Both_QQ_QZone,
    InstallClientType_Weibo,
    InstallClientType_WeChat
};

typedef enum : NSUInteger {
    SourceAppTypeUnknow,
    SourceAppTypeQQ,
    SourceAppTypeWX,
    SourceAppTypeWB,
} SourceAppType;

extern NSString * const ErrorDescKey;

extern NSString * const QQAppIdKey;
extern NSString * const SinaAppIdKey;
extern NSString * const SinaRedirectURIKey;
extern NSString * const WeChatAppIdKey;
extern NSString * const WeChatAppSecretKey;

@interface FFBaseShareCenter : NSObject
@property (nonatomic, strong) FFUser *user;
@property (nonatomic, strong) FFAuthInfo *authInfo;
@property (nonatomic, strong, readonly) NSDictionary *AppIdDict;
@property (nonatomic, assign, readonly, getter=isInstalledClient) InstallClientType installedClient;

- (void)openClientAuthWithShareType:(ShareType)shareType successBlock:(ShareSuccessBlock)shareSuccessBlock cancelBlock:(ShareCancelBlock)shareCancelBlock failureBlock:(ShareFailureBlock)shareFailureBlock;
+ (SourceAppType)sourceAppTypeWithSourceAppString:(NSString *)sourceApplication;

/**
   在appDelegate,- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 里面实现该方法
 */
+ (BOOL)handlerOpenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication;
/**
 *  设置各平台的AppId、AppSecret、RedirectURI
 *
 *  @param appIdDict       key 为QQAppIdKey,SinaAppIdKey,WeChatAppIdKey value 为各平台AppId
 *  @param appSecretDict   key 为WeChatAppSecretKey,... value为各平台的Secret
 *  @param redirectURIDict key 为SinaRedirectURIKey,... value为各平台的RedirectURI
 */
+ (void)setAppId:(NSDictionary *)appIdDict appSecret:(NSDictionary *)appSecretDict redirectURI:(NSDictionary *)redirectURIDict;

/**
 *  获取分享平台
 *
 *  @param shareType 分享类型
 *  @return 分享平台
 */
+ (FFBaseShareCenter *)getShareCenterWithShareType:(ShareType)shareType;

/**
 *  分享
 *
 *  @param contentInfo  分享信息
 *  @param successBlock 成功回调
 *  @param cancelBlock  取消回调
 *  @param failureBlock 失败回调
 */
- (void)shareContentInfo:(ShareContentInfo *)contentInfo successBlock:(ShareSuccessBlock)successBlock cancelBlock:(ShareCancelBlock)cancelBlock failureBlock:(ShareFailureBlock)failureBlock;
- (void)executeFailureBlock:(ShareFailureBlock)failureBlock errorDomain:(NSString *)ErrorDomain errorMsg:(NSString *)errorMsg errorCode:(NSInteger)errorCode;

简单使用,如下:

 - (IBAction)onShareBtnTap:(UIButton *)sender {
    UIImage *image = [UIImage imageNamed:@"benz.png"];
    NSData *imgData = UIImagePNGRepresentation(image);
    ShareContentInfo *shareInfo = [ShareContentInfo shareTitle:@"哈哈哈" content:@"你在干什么,什么都不说" url:@"https:www.baidu.com" imagePath:nil objData:imgData contentType:ShareContentType_Link];
    ShareType shareType = ShareType_None;
    if (sender.tag == 1) {
        shareType = ShareType_WeChat;
    } else if (sender.tag == 2) {
        shareType = ShareType_QQ;
    } else if (sender.tag == 3) {
        shareType = ShareType_WeChatTimeline;
    } else if (sender.tag == 4) {
        shareType = ShareType_Sina;
    }
    shareInfo.shareType = shareType;

    FFBaseShareCenter *shareCenter = [FFBaseShareCenter getShareCenterWithShareType:shareType];
    [shareCenter shareContentInfo:shareInfo successBlock:^{
        NSLog(@"分享成功");
    } cancelBlock:^(BOOL cancelled) {
        NSLog(@"取消分享");
    } failureBlock:^(NSError *error) {
        NSLog(@"分享失败 --->%@",error.localizedDescription);
    }];
}
  • ViewController

ViewController创建了一个基类,使用VC的时候都可以继承该基类,可设置标题,NavigationBar的设置, 如下:


这里写图片描述

@interface FFBaseViewController : UIViewController
/**设置标题*/
@property (nonatomic, copy) NSString *navigationTitle;
/**设置标题颜色*/
@property (nonatomic, strong) UIColor *navigationTitleColor;
/**设置NavigationBar颜色*/
@property (nonatomic, strong) UIColor *navigationBarColor;
/**隐藏NavigationBar*/
@property (nonatomic, assign, getter=isHideNavigationBar) BOOL hideNavigationBar;
/**隐藏状态栏*/
@property (nonatomic, assign, getter=isHideStatusBar) BOOL hideStatusBar;
/**设置状态栏样式*/
@property (nonatomic, assign, getter=isStatusBarStyleDefault) BOOL statusBarStyleDefault;

@property (nonatomic, assign, getter=isNavBarColorChange) BOOL navBarColorChange;
/**左按钮*/
@property (nonatomic, strong) UIButton *leftBtn;
/**右按钮*/
@property (nonatomic, strong) UIButton *rightBtn;
/**右边多个按钮数组*/
@property (nonatomic, strong) NSArray *rightBtns;
/***/
@property (nonatomic, copy) DismissBlock dismissBlock;

/**显示返回按钮(默认返回按钮)*/
- (void)showBackBtn;

/**返回按钮点击*/
- (void)onBackBtnTap:(UIButton *)sender;

/**取消请求*/
- (void)cancelAllRequest;
+ (NSString *)classStr;
  • View

View里面包含自定义 UITableViewUICollectionView 的使用,内封装下拉刷新和上拉加载的使用。


这里写图片描述

上面介绍了UITableView的使用,包括下拉刷新和上拉加载,这里介绍一下UICollectionView的使用。


- (void)getRequest:(BOOL) isRefresh {
    if ([TestARequest isRequesting]) {
        return;
    }
    __weak typeof(self) WS = self;

    NSInteger page = isRefresh ? 1 : _page + 1;
    NSDictionary *parameter = @{@"q": @"美女",
                                @"start": @(page),
                                @"count": @10};
    // 回调成功Block
    id successBlock = ^(FFBaseRequest *request){
        // 设置分页数
        _page = page;

        // 获取数据
        NSArray *arrResult = request.resultDict[Key_Model];
        if (isRefresh) {
            WS.books = arrResult;
        } else {
            NSMutableArray *arrTemp = [NSMutableArray arrayWithArray:WS.books];
            [arrTemp addObjectsFromArray:WS.books];
            WS.books = arrTemp;
        }

        // 设置上拉加载
        [WS.collectionView isDisplayMoreView:WS.books.count < request.totalCount];

        // 完成加载
        [WS.collectionView didFinishedLoading];

        // 刷新数据
        [WS.collectionView reloadData];
    };

    // 回调取消Block
    id cancleBlock = ^(FFBaseRequest *request) {
        [WS.collectionView didFinishedLoading];
    };

    // 回调失败Block
    id failureBlock = ^(FFBaseRequest *request, NSError *error){
        [WS.collectionView didFinishedLoading];
    };
    [TestARequest requestParameters:parameter successBlock:successBlock cancelBlock:cancleBlock failureBlock:failureBlock];
}


// 需要实现的两个协议方法
#pragma mark - FFCollectionViewDelegate
- (void)collectionViewLoadMore:(FFCollectionView *)collectionView {
    [self getRequest:NO];
}

- (void)collectionViewRefresh:(FFCollectionView *)collectionView {
    [self getRequest:YES];
}

结语

到这里,基本上FFFramework的基本使用算是差不多了,具体的详细使用可以把源项目下载下来具体的试验一下。洋洋洒洒的写了这一些,算是一种总结归纳吧。。。 希望在总结的同时对别人也能有帮助。 另外, 附上源项目的地址: https://github.com/ismilesky/FFDemo.git

未完待续, 会持续补充。。。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值