|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
其实net网页编程之所以在曾经独步天下,就是因为他的跨平台、安全性,这两方面,效率可不是net网页编程的强项,反而是他最短的一块挡板,虽然net总是用理论证明比.NET快。在开辟iOSApp时常常会碰到跟后端RESTAPI通讯的情形。这就触及到毛病处置,NSDictionary与Model的映照,用户登录与登出,权限考证,Archive/UnArchive,Copy,AccessToken过时处置等等,假如没有很好地处置这些点,就简单呈现代码庞大度增年夜,布局狼藉,不便利前期保护的征象。
恰好比来在看AFNetworking2.0和ReactiveCocoa2.1,参考了github的octokit,重写了花瓣的iOSRESTAPI,分享些心得。
基础布局
- |-HBPAPI.h|-Classes|-HBPAPIManager.h|-HBPAPIManager.m|-Models|-HBPObject.h|-HBPObject.m|-HBPUser.h|-HBPUser.m...
复制代码 利用时,间接援用HBPAPI.h便可,内里包括了一切的Class。由于利用了AFNetworking2.0,以是不再是HBPClient,而是HBPManager。HBPAPIManager包括了一切的跟服务端通讯的办法,经由过程Category来辨别。- #pragmamark-HBPAPIManager(Private)@interfaceHBPAPIManager(Private)//外部一致利用这个办法来向服务端发送哀求////resultClass-从服务端猎取到JSON数据后,利用哪一个Class来将JSON转换为OC的Model//listKey-假如不指定,暗示前往的是一个object,如user,假如指定暗示前往的是一个数组,listKey就暗示这个列表的keyname,如{users:[]},那末listName就为user-(RACSignal*)requestWithMethod:(NSString*)methodrelativePath:(NSString*)relativePathparameters:(NSDictionary*)parametersresultClass:(Class)resultClasslistKey:(NSString*)listKey;@end#pragmamark-HBPAPIManager(User)@interfaceHBPAPIManager(User)//signal会senduser,假如没有user,就会sendError//必需以后用户已登录的情形下挪用-(RACSignal*)fetchUserInfo;//...@end#pragmamark-HBPAPIManager(Friendship)//...
复制代码 ModelsGroup包括了一切跟服务端API对应的Model,好比HBPComment
HBPComment.h- #import"HBPObject.h"@classHBPUser;@interfaceHBPComment:HBPObject@property(nonatomic,assign)NSIntegercommentID;@property(nonatomic,copy)NSString*createdAt;@property(nonatomic,strong)HBPUser*user;//...@end
复制代码 HBPComment.m- #import"HBPComment.h"@implementationHBPComment-(NSDictionary*)JSONKeysToPropertyKeys{return@{@"comment_id":@"commentID",@"user_id":@"userID",@"created_at":@"createdAt",//...};}@end
复制代码 Archive/UnArchive/Copy
每个Object都要撑持Archive/UnArchive/Copy,也就是要完成<NSCoding>和<NSCopying>协定,这两个协定的内容实在就是对Object的Property做些处置,以是假如能够在基类里把这些事都一致处置,就会便利很多。octokit利用Mantle来做这些事变,不外我以为Mantle仍是有些贫苦,因而写了个经由过程运转时来猎取property,并完成<NSCoding>和<NSCopying>的基类,只要两个大众办法:- #import<Foundation/Foundation.h>@interfaceHBPObject:NSObject<NSCopying,NSCoding>//剖析API前往的JSON,前往对应的Model-(id)initWithDictionary:(NSDictionary*)JSON;//JSONkey到property的映照干系-(NSDictionary*)JSONKeysToPropertyKeys;@end
复制代码 个中-(id)initWithDictionary:(NSDictionary*)JSON的感化是遍历Object的Property,假如Property的Class是HBPObject,那末就挪用-(id)initWithDictionary:(NSDictionary*)JSO,否则就经由过程KVC的setValue:forKey:来设定值。
-(NSDictionary*)JSONKeysToPropertyKeys的内容也许是如许:- -(NSDictionary*)JSONKeysToPropertyKeys{return@{@"id":@"ID",@"nav_link":@"navLink",};}
复制代码 如许经由过程一个HBPObject基类就完成了Archive/UnArchive/Copy。
用户的登录与登出
先来讲说登录,因为利用RAC,在机关API时,就不必要传进Block了,随之而来的一个成绩就是必要在正文中申明sendNext时会发送甚么内容。- +(RACSignal*)signInUsingUsername:(NSString*)usernamepassowrd:(NSString*)password{NSAssert(API_CLIENT_ID&&API_CLIENT_SECRET,@"API_CLIENT_IDandAPI_CLIENT_SECRETmustbesetted");NSDictionary*parameters=@{@"grant_type":@"password",@"username":username,@"password":password,};HBPAPIManager*manager=[selfcreateManager];return[[managerfetchTokenWithParameters:parameters]setNameWithFormat:@"+signInUsingUsername:%@password:%@",username,password];}
复制代码 看着还挺复杂的吧,由于次要事情都是+fetchMoreData:parameters在做,看看它的完成- -(RACSignal*)fetchTokenWithParameters:(NSDictionary*)parameters{return[[[[[[[selfrac_POST:@"oauth/access_token"parameters:parameters]//reduceEach的感化是传进多个参数,前往单个参数,是基于`map`的一种完成reduceEach:^id(AFHTTPRequestOperation*operation,NSDictionary*response){//拿到token后,就设置tokenproperty//setToken:办法会被触发,在那边会设置哀求的头信息,如Authorization。HBPAccessToken*token=[[HBPAccessTokenalloc]initWithDictionary:response];self.token=token;returnself;}]catch:^RACSignal*(NSError*error){//对Error举行处置,便利内部辨认NSIntegercode=error.code==-1001?HBPAPIManagerErrorConnectionFailed:HBPAPIManagerErrorAuthenticatedFailed;NSError*apiError=[[NSErroralloc]initWithDomain:HBPAPIManagerErrorDomaincode:codeuserInfo:nil];return[RACSignalerror:apiError];}]then:^RACSignal*{//统统一般的话,特地猎取用户信息return[selffetchUserInfo];}]doNext:^(HBPUser*user){//doNext相称于一个钩子,是在sendNext时会被实行的一段代码self.user=user;}]//把发送内容换成selfmapReplace:self]//制止sideeffectreplayLazily];}
复制代码 这里对signal举行了chain/modify/hook等操纵,次要感化是猎取accesstoken和用户信息。
用户的登出就复杂了,间接设置user和token为nil就好了。
设置超不时间弛缓存战略
由于AF2.0利用了新的架构,招致要设置Request的超时弛缓存略微有些贫苦,必要新建一个承继自AFHTTPRequestSerializer的Class- @interfaceHBPAPIRequestSerializer:AFHTTPRequestSerializer@end@implementationHBPAPIRequestSerializer-(NSMutableURLRequest*)requestWithMethod:(NSString*)methodURLString:(NSString*)URLStringparameters:(NSDictionary*)parameters{NSMutableURLRequest*request=[superrequestWithMethod:methodURLString:URLStringparameters:parameters];request.timeoutInterval=10;request.cachePolicy=NSURLRequestReloadIgnoringLocalCacheData;returnrequest;}@end
复制代码 然后将这个class设置为manager.requestSerializer- HBPAPIManager*manager=[[HBPAPIManageralloc]initWithBaseURL:[NSURLURLWithString:API_SERVER]];manager.requestSerializer=[HBPAPIRequestSerializerserializer];
复制代码 如许就好了
权限考证
这个对照复杂些,间接在办法内里加上判别- #pragmamark-HBPAPIManager(Private)@interfaceHBPAPIManager(Private)//外部一致利用这个办法来向服务端发送哀求////resultClass-从服务端猎取到JSON数据后,利用哪一个Class来将JSON转换为OC的Model//listKey-假如不指定,暗示前往的是一个object,如user,假如指定暗示前往的是一个数组,listKey就暗示这个列表的keyname,如{users:[]},那末listName就为user-(RACSignal*)requestWithMethod:(NSString*)methodrelativePath:(NSString*)relativePathparameters:(NSDictionary*)parametersresultClass:(Class)resultClasslistKey:(NSString*)listKey;@end#pragmamark-HBPAPIManager(User)@interfaceHBPAPIManager(User)//signal会senduser,假如没有user,就会sendError//必需以后用户已登录的情形下挪用-(RACSignal*)fetchUserInfo;//...@end#pragmamark-HBPAPIManager(Friendship)//...0
复制代码 AccessToken过时的处置
AccessToken过时和猎取新的AccessToken能够交给利用者来做,可是会对照贫苦,最好的办法是过时后主动往猎取新的AccessToken,拿到Token后主动往实行之前失利的哀求,这块我是这么处置的- #pragmamark-HBPAPIManager(Private)@interfaceHBPAPIManager(Private)//外部一致利用这个办法来向服务端发送哀求////resultClass-从服务端猎取到JSON数据后,利用哪一个Class来将JSON转换为OC的Model//listKey-假如不指定,暗示前往的是一个object,如user,假如指定暗示前往的是一个数组,listKey就暗示这个列表的keyname,如{users:[]},那末listName就为user-(RACSignal*)requestWithMethod:(NSString*)methodrelativePath:(NSString*)relativePathparameters:(NSDictionary*)parametersresultClass:(Class)resultClasslistKey:(NSString*)listKey;@end#pragmamark-HBPAPIManager(User)@interfaceHBPAPIManager(User)//signal会senduser,假如没有user,就会sendError//必需以后用户已登录的情形下挪用-(RACSignal*)fetchUserInfo;//...@end#pragmamark-HBPAPIManager(Friendship)//...1
复制代码 HBPObjectSubClass
那些承继自HBPObject的子类,有些事变是HBPObject没法处置的,好比NSArray的Property,由于Objective-C不撑持generic,以是没法晓得这个数组包括的事实是如何的Class,这时候就必要在子类对这些property做处置。
兄弟们,想来你们都看过了昨天的比赛了。我现在的痛苦状跟当时应该差不多。希望本版.net老师不吝赐教,为小弟这一批迷途的羊羔指一条阳光之道!您也知道:学习技术如果只有一个人摸索,那是一件多么痛苦的事情!还有,如果万辛能得名师或长者指点,那又是多么一件幸福和快乐的事情! |
|