我对两件事感到好奇:
1在与 API 和 View Controller 通信的对象之间设计通信的高效且易于扩展的方式是什么
2如何设计通信对象本身(如何设计可扩展的方法,..)
(我知道,我在下面提到的方法很困惑,但截止日期很疯狂,直到现在我都没有时间真正考虑它。)
让我介绍一下我正在处理的任务:
根据与 API 的通信,我必须编写 2-3 个应用程序。 API 响应了大约 10-15 种不同的方法(通过 http POST 发送,结果为 JSON)。当然,通信必须是异步的。
我的方法:
因此,与 API 的对象通信(简称apiComm)由所有 UIViewControllers 共享。 apiComm 有 10-15 个方法,每个方法对应 API 能够处理的方法;各个请求内容之间存在很大差异.. => 问题 2
当 apiComm 从 API 收到数据时,它会在 [NSNotificationCenter defaultCenter] 上发布通知。这意味着,每个想要使用 apiComm 的 UIViewController 都必须为通知注册自己并实现处理传入通知的方法。由于一些 UIViewController 不得不处理更多的 API 请求,这种方法变得令人讨厌,... => 问题 1
我想知道在设计这些问题时是否可以使用通用模式.. 对于这个问题的任何部分,我将不胜感激。
对我来说,解决这个棘手问题的唯一真正答案或方向是:
正如@liamnichols 指出的那样,一定要使用某种类似于抽象类的模式
如果您正在阅读这篇 iOS 新书,使用“after...” block 模式是绝对必要的(下面代码中的示例)
在这一点上,这是 iOS/objective-C 中的一个绝对关键点 https://stackoverflow.com/a/20760583/294884 ..如何使 block 成为属性
纯粹是 IMO,我从来没有找到一个大项目,其中“15 个项目”实际上可以真正合理化。它只是还没有发生。所以对我们来说最好的办法是仔细 - 至少 - 包装它,以便(以一种或另一种方式)您将“15 个项目”称为这样的东西 .. CLOUD.NOTES .. CLOUD.PROFILE .. CLOUD.SCORES .. 和从你的代码的其余部分等等。
当然要为网络系统使用单例
为网络系统同时使用 KVO 和 NSNotifications 至关重要
值得注意的是,如今在 iOS 世界中处理 JSON 非常容易,以至于(幸运的是)“只有 15 个单独的文件”{一种或另一种方式} 确实不错很容易将其视为您可以做出的最明确的合理化。
所以,只是一些复杂的想法。最后一点 - 一切都只是转移到 parse.com 所以这一切都变得毫无意义,幸运的是
这几乎是“我正在与一个还没有搬到 bAAs 的客户合作('不,真的!')所以我如何保持网络代码整洁......!”呵呵。
再简单不过了,写一个漂亮的单例。
将它放在任何需要它的应用程序中。
如今,在 iOS 中处理 JSON 非常容易。所以,我所描述的往往是微不足道的......不过是几十行代码。
您的“云”文件将包含如此简单的例程......这个单例将被称为“BLANKS”或类似的......它从服务器获取一些“空白”用户文件类型,比方说。
-(void)loadIfNeededThenvoid(^)(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)_refreshThenvoid(^)(void))after
{
dispatch_async(dispatch_get_main_queue(),
^{
self.rawBlanksFromCloud = [NSData dataWithContentsOfURL:uBlanks];
[self _doShowAllOnLog];
after();
});
}
值得意识到的是,所有都在转移到 Parse.com 和其他 bAA。没有其他现实的 future ,今年年底之后不会有太多“服务器端”。
所以在实践中,这些简单的单例变得更加简单——它们只是连接到 Parse 的几行代码。享受吧!
所以 TBC 上面的代码示例来自“ye olde web server”的情况。
这是一个获取“用户文件”的示例..(注意方便的例程 postStringUser 用于组装该死的 url 调用..我从来没有找到一个真正巧妙的方法来做到这一点!)...
-(NSString *)postStringUserNSString *)user passNSString *)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)fetchTheUsersFilesNSString *)user passNSString *)pass thenvoid(^)(void))after
{
NSString *postString = [self postStringUser:user pass:pass];
NSLog(@"postString is %@ ", postString );
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:yourUrl];
request.HTTPMethod = @"OST";
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"];
希望对你有帮助!
关于iOS - API 对象和 Controller 之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23801085/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |