我对两件事感到好奇:
1 设计与 API 通信的对象与 View Controller 之间的通信的高效且易于扩展的方法是什么
2如何设计通信对象本身(如何设计可扩展的方法,..)
(我知道下面提到的我的方法很困惑,但最后期限很疯狂,直到现在我还没有时间真正考虑它。)
让我介绍一下我正在处理的任务:
我必须根据与 API 的通信编写 2-3 个应用程序。 API 响应了大约 10-15 种不同的方法(通过 http POST 发送,结果为 JSON)。当然,通信必须是异步的。
我的方法:
因此,与 API(简称 apiComm)的对象通信由所有 UIViewController 共享。 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 所以这一切都变得没有实际意义,幸运的是:)
这几乎是“我正在与一个尚未转移到 bAA 的客户(‘不,真的!’)一起工作的情况,所以我如何保持网络代码整洁……!”呵呵。
再简单不过了,只需写一个漂亮的单例即可。
将它放在任何需要它的应用中。
如今在 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 和其他 bAA。没有其他现实的 future ,今年年底之后不会有太多的“服务器端”。
所以在实践中,这些简单的单例变得更加简单——它们只是连接到 Parse 的几行代码。享受吧!
因此 TBC 上面的代码示例来自“古老的网络服务器”情况。
这是获取“用户文件”的示例..(请注意用于组装该死的 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"];
希望对您有所帮助!
关于iOS - API 对象和 Controller 之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23801085/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调