0

修改...

该应用程序的关键是与数据库服务器进行通信。从服务器到应用程序的响应都是 XML 格式的。有几个屏幕。例如,屏幕 1 列出了用户的信息,屏幕 2 列出了用户过去的交易,允许新的交易,等等。

这是我的 AppDelegate 中的一些代码:

StartViewController *svc = [[StartViewController alloc] init];
TradeViewController *tvc = [[TradeViewController alloc] init];
CashViewController *cvc = [[CashViewController alloc] init];
ComViewController *covc = [[ComViewController alloc] init];
PrefsViewController *pvc = [[PrefsViewController alloc] init];

NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:5];
UITabBarController *tabBarController = [[UITabBarController alloc] init];

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:svc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:tvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:cvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:covc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:pvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

[tabBarController setViewControllers:tabBarViewControllers];

[[self window] setRootViewController:tabBarController];

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

试图坚持 MVC 风格,我有一个单例类来完成所有的“处理”。

现在是我如何撞墙的示例……用户可以在屏幕 5 上更改他们的电子邮件地址。在文本字段中输入新的电子邮件地址,然后单击保存按钮。然后该按钮从单例类中调用一个方法,该方法将新的电子邮件地址发送到服务器并(通过 URL)并接收确认更改的 XML 响应。

以下是我的问题: 1. 在进行单例类方法调用之前,我从视图控制器启动微调器 - 但不知道应用程序到服务器的发送/接收何时完成,如何让微调器在正确的时间停止?我不能从单例类中获得它,我试过了。据我所知,它必须来自 VC 内部,或者有没有办法从我的单例类中更改 VC 输出?

  1. 单例类 NSURLConnection 正在处理我的所有通信。从简单的电子邮件更改一直到更新事务表的所有内容。这对我来说似乎是错误的,并且很难跟踪谁在打电话。同样,我将按照我对 MVC 的解释进行说明。我认为为每个 VC 设置一个 NSURLConnection 并在这些类中进行一些处理会容易得多。但是,这不是 MVC(ish)。

  2. 我的单例类中有近 100 个变量、数组等...... 这对我来说似乎也是错误的,但我想不出任何其他方式。

4

5 回答 5

3

如何在 NSURLConnection 委托 (connectionDidFinishLoading) 中区分正在进行哪个 URL 调用?

每个委托方法(例如-connectionDidFinishLoading:)都有一个connection参数,告诉您哪个连接发送了消息。给定的连接一次只能加载一个 URL,因此 URL 和连接之间存在一对一的对应关系。

下载完成后,如何在“connectionDidFinishLoading”之外进行判断?

该方法会告诉您连接何时完成。您可以将这些信息存储在对您的应用程序有用的地方。

更新:根据您添加的内容,您的“处理”类是您应用的模型。应用程序的其余部分不应该关心每个事务都涉及到服务器的消息——这只是模型的业务。此外,模型没有理由必须是单个对象(更不用说单例了)——它可以是一组协同工作的对象。

因此,您可能有一个类(我们称其为处理器),它表示应用程序与模型的接口(有些人甚至称其为“模型控制器”)。Processor 的一个实例可能会创建一个本地数据库来存储应用程序的当前本地状态。您可能还有一个 Transaction 类,它表示与服务器的单个事务。事务可以创建一个请求,将其发送到服务器,获取响应,更新数据库,并告诉处理器事务已完成。或者,也许当应用程序的其他部分(如您的视图控制器之一)要求处理器处理新事务时,处理器将请求对象传递给它创建的事务,以便事务可以直接更新请求者。

如果不知道您打算在哪里使用它,很难说出您的应用程序的最佳计划是什么,但通常的指导方针是:

  • 把你的问题分解成更容易解决的部分

  • 限制每个类的职责范围

  • 如果某些事情看起来很复杂,那可能是

将你的模型分成几个类也会更容易测试。您可以想象为 Transaction 类编写一组单元测试是多么容易。处理器也是如此——如果服务器事务属于不同的类,则更容易测试处理器是否在做正确的事情。

于 2012-06-04T18:31:35.390 回答
1

如果您有多个 NSURLConnections 用于同一个委托,请考虑使用全局(好吧,我们说是一个实例变量)NSMutableDictionary 实例,您可以根据调用的 NSURLConnection 来存储数据。例如,您可以使用转换为 NSString 的连接的内存地址(类似于

[NSString stringWithFormat:@"%p", connection]

应该做的伎俩)。

此外,在connectionDidFinishLoading:andconnection:didFailLoadWithError:方法中,删除与 NSURLConnections 对应的键。因此,如果连接完成,您可以从“外部”告诉它:只需检查它是否在字典中。

于 2012-06-04T18:30:10.930 回答
1

如果您通过网络连接下载任何数据,我建议您使用ASIHttpRequest。这将允许您异步下载文件,这意味着您的界面在下载过程中不会冻结。

如果使用ASIHttpRequest,还可以设置didFinishSelector。通过这样做,您可以控制在特定 URL 完成加载时调用哪个方法。

看看这个:

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

[request setDelegate:self];
[request startAsynchronous];
[request setDidFinishSelector:@selector(requestDone:)];

然后:

- (void)requestDone:(ASIHTTPRequest *)request
{
   // Use when fetching text data
   NSString *responseString = [request responseString];

   // Use when fetching binary data
   NSData *responseData = [request responseData];

   // If you want, you can get the url of the request like this
   NSURL *url = [request url];
}

至于你问题的第二部分,如果该requestDone:方法没有被调用,你就知道下载没有完成。

如果您想通过多次下载来做一些更复杂的事情,也ASIHttpRequest可以提供队列功能。看看这里

于 2012-06-04T18:39:45.940 回答
1

我建议继承 NSURLConnection。只需添加两个属性:一个 NSInteger tag, 和一个 BOOL, isFinished。这样,您可以#define为每个不同的请求添加标签,然后在您的委托方法中通过标签来识别它们。在connectionDidFinishLoading中,您可以将isFinishedBOOL 设置为 YES,然后您可以在其他方法中检查连接是否完成。


这是我自己的 NSURLConnection 子类 TTURLConnection:

TTURLConnection.h:

#import <Foundation/Foundation.h>

@interface TTURLConnection : NSURLConnection <NSURLConnectionDelegate>

@property (nonatomic) NSInteger tag;
@property (nonatomic) BOOL isLocked;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam;

@end

TTURLConnection.m:

#import "TTURLConnection.h"

@implementation TTURLConnection

@synthesize tag;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam {
    self = [super initWithRequest:request delegate:delegate 
        startImmediately:startImmediately];

    if(self) {
        self.tag = tagParam;
    }

    return self;
}

@end
于 2012-06-04T18:55:20.660 回答
1

希望这会帮助你。

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{   
    NSString *urlString = [[[connection originalRequest] URL] absoluteString];
    if ([urlString caseInsensitiveCompare:@"http://www.apple.com"] == NSOrderedSame) {
        //Do Task#1
    }
    else if ([urlString caseInsensitiveCompare:@"http://www.google.com"] == NSOrderedSame)
    {
        //Do Task#2
    }
}
于 2012-06-04T19:08:17.953 回答