iOS – API对象和控制器之间的通信

我很好奇两件事:

1有哪些高效且易于扩展的方法来设计与API通信的对象与视图控制器之间的通信

2如何设计通信对象本身(如何设计可扩展的方法,…)

(我知道,下面提到的方法很混乱,但最后期限很疯狂,直到现在我还没有时间考虑它。)

让我介绍一下我正在处理的任务:

我必须根据与API的通信编写2-3个应用程序。 API响应了大约10-15种不同的方法(通过http POST发送,产生JSON)。 当然,沟通必须是异步的。

我的方法:

因此,与API(简称apiComm )的对象通信由所有UIViewControllers共享。 apiComm有10-15个方法,每个方法用于API能够处理的方法; 个别请求内容之间存在很大差异.. => 问题2

apiComm从API收到数据时,它在[NSNotificationCenter defaultCenter]上发布了通知。 这意味着,每个想要使用apiComm的 UIViewController必须为通知注册self并实现处理传入通知的方法。 这种方法变得讨厌,因为一些UIViewController必须处理更多的API请求,… => 问题1

我想知道在设计这些问题时是否有一种通用的模式。我会很高兴任何关于这个问题的任何部分的评论。

对我来说,我能给这个棘手问题的唯一真正答案或方向是:

  • 用@liamnichols指出,无论如何都要使用某种类似抽象类的模式

  • 如果您正在阅读iOS新版本,那么使用“after …”块模式绝对必要(下面的代码示例)

  • 在这一点上,这是iOS / objective中的绝对关键点 – C https://stackoverflow.com/a/20760583/294884 ..如何使块成为属性

  • 纯粹的IMO,我从来没有找到一个大项目,其中“15项”实际上可以真正合理化。 它还没有发生。 所以对我们来说最好小心 – 至少 – 包装它以便(以这种或那种方式)你称之为“15项”这样的东西.. CLOUD.NOTES .. CLOUD.PROFILE .. CLOUD.SCORES ..和等等你的代码。

  • 当然,对网络系统使用单例

  • 对于网络系统而言,获得KVO和NSNotifications至关重要

  • 非常重要的是要注意在iOS世界中处理JSON是如此荒谬,现在,(幸运的是)“只有15个单独的文件”{这样或那样}真的不是坏事而且很容易把它看作真的,你可以做出的最明确的合理化。

所以,只是一些混合的想法。 最后一点 – 一切都只是转移到parse.com所以这一切都变得毫无意义,幸运的是:)

这几乎就是“我正在与尚未转向bAAs的客户合作(’不,真的!’),所以我如何保持网络代码整洁……!” 嘿。


不可能更容易,只写一个漂亮的单身人士

将其放入任何需要它的应用程序中。

如今在iOS中处理JSON简直令人难以置信。 所以,我所描述的往往是微不足道的……只有几十行代码。

你的“云”文件将包含这个简单的例程…这个单例将被称为“BLANKS”或类似…它从服务器获取一些“空白”用户文件类型,比方说。

-(void)loadIfNeededThen:(void(^)(void))after { if ( self.rawStubsFromCloud != nil ) { NSLog(@"good new, blanks are already loaded!!"); after(); return; } [APP huddie]; // (use MBProgressHUD for all spinners) APP.hud.labelText = @"Loading file blanks from cloud..."; dispatch_after_secs_on_main(0.1 , ^{ [self _refreshThen: ^{ [APP.hud hide:YES]; NSLog(@"loaded the blanks fine:\n%@\n", [self supplyDisplayStyleString] ); after(); }]; } ); } -(void)_refresh { [self _refreshThen:nil]; } #define uBlanks [NSURL URLWithString:@"http://blah.com/json/blanks"] -(void)_refreshThen:(void(^)(void))after { dispatch_async(dispatch_get_main_queue(), ^{ self.rawBlanksFromCloud = [NSData dataWithContentsOfURL:uBlanks]; [self _doShowAllOnLog]; after(); }); } 

值得注意的是,一切都在转向Parse.com和其他bAAs 。 没有其他现实的未来,今年年底之后不会有太多的“服务器端”。

所以在实践中,这些简单的单例变得更加简单 – 它们只是连接到Parse的几行代码。 请享用!

所以TBC上面的代码示例来自“ye olde web server”情况。

这是一个获取“用户文件”的例子..(注意用于组装该死的url调用的方便的例程postStringUser ..我从来没有找到一个非常简洁的方法来做到这一点!)…

 -(NSString *)postStringUser:(NSString *)user pass:(NSString *)pass { NSString *username = user; NSString *password = pass; NSMutableString *r = [NSMutableString stringWithString:@""]; [r appendString:@"command=commandExampleGetFile"]; [r appendString:@"&"]; [r appendString:@"name=blah"]; [r appendString:@"&"]; [r appendString:@"user="]; [r appendString: [username stringByUrlEncoding] ]; [r appendString:@"&"]; [r appendString:@"password="]; [r appendString: [password stringByUrlEncoding] ]; return r; } #define yourUrl [NSURL URLWithString:@"http://blah.com/json/blah"] -(void)fetchTheUsersFiles:(NSString *)user pass:(NSString *)pass then:(void(^)(void))after { NSString *postString = [self postStringUser:user pass:pass]; NSLog(@"postString is %@ ", postString ); NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:yourUrl]; request.HTTPMethod = @"POST"; request.HTTPBody = [ postString dataUsingEncoding:NSUTF8StringEncoding]; [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField: @"Content-Type"]; [APP huddie]; // use MBProgress everywhere and always at all times in all apps always APP.hud.labelText = @"Connecting to the cloud..."; // 1 get the data // 2 make it a jdic // 3 make it an array of the "files" [NSURLConnection sendAsynchronousRequest: request queue: [NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *r, NSData *data, NSError *error) { [APP.hud hide:YES]; NSLog(@"Done... %@", r); self.rawGetFilesFromCloud = data; NSError* err; NSDictionary* jdic = [NSJSONSerialization JSONObjectWithData:self.rawGetFilesFromCloud options:kNilOptions error:&err]; //dev only NSLog(@"Here's the whole damned jdic, for GetFiles\n%@", jdic); if ( ! jdic ) { [APP simpleOK:@"Wrong username or pass? Or no files found."]; } else { // the user has "logged in" so something like STATE.currentUsername = user; STATE.currentPassword = pass; // naturally you have a STATE singleton, every app needs one self.rawArrayFromCloud = [jdic objectForKey:@"data"]; NSInteger kUserFiles = self.rawArrayFromCloud.count; NSString *sayString = [NSString stringWithFormat: @"We found %lu files of yours on the damned cloud.", kUserFiles]; /* and for example... STATE.fileZero = self.rawArrayFromCloud[0]; or for example... NSDictionary *oneStubDict = self.rawArrayFromCloud[17]; NSString *subjectName = oneStubDict[@"subjectName"]; NSString *mainBody = oneStubDict[@"mainBody"]; NSString *authorField = oneStubDict[@"authorField"]; */ [APP simpleOK: sayString then:^{ [STATE showFileInterface]; } ]; } if (after) after(); }]; } 

注意关键代码只是……

 NSMutableURLRequest *request = ... [NSURLConnection sendAsynchronousRequest: request ... NSDictionary* jdic = [NSJSONSerialization JSONObjectWithData:result ... NSArray *theFiles = [jdic objectForKey:@"theFiles"]; NSString *aField = theFiles[13]["coverInfo"]["aField"]; 

希望能帮助到你!