2

我有一个想要重构的当前代码库。控制器(或熟悉 iOS 的人的视图控制器)大约有 2000 行,并且做了很多事情。

控制器负责:
1)视图和模型之间的通信

1.1) 处理视图中的回调/动作
1.2) 处理手势。
1.3) 将数据从模型传递到视图。

2) 如果模型为空,则发出 Web 请求。

2.1)准备URL并向连接处理程序发送请求。
2.2) 解析逻辑

3) 自定义用户界面

3.1) 小的 UI 修改。

4)业务逻辑。

4.1) 一些代码处理计算一些报告的业务逻辑。

我正在考虑将一些职责委托给模型和视图。关于如何去做的任何想法?

另外,更具体地说,我想知道谁负责制作 Web 请求模型或控制器?

4

2 回答 2

2

在编写易于维护的代码时,有几个概念对我很有用:

  1. 除了具体的模型对象(例如,如果从服务请求天气信息,您可能有一个Weather表示特定天气报告的类,例如 a city、 atemperaturenarrative属性),我还将使用一个数据控制器对象来协调从缓存、持久存储或网络请求对象,视情况而定(通常按此顺序)。您要警惕仅依赖于 Web 服务的简单请求,因为缓存等在设计响应式 UI 时可能非常重要。

    对我来说,关键是我很少希望视图或视图控制器处理这种细节级别(尽管我承认,在琐碎的情况下,我直接从控制器完成了请求)。理想情况下,视图控制器将启动我的数据控制器的异步请求,向它传递一个带有参数的完成块(a)正在检索的模型对象;(b) 一个NSError

    我将在下面包含一个示例。

  2. 正如您可能从上面推断的那样,我经常也将 Web 请求的启动和将响应解析为它们自己的对象的细节抽象出来(因为数据控制器可能足够复杂,管理缓存、持久存储等) . 我通常将NSOperation子类用于请求/解析任务(它适用于带有完成块的异步请求;如果 UI 移动到其他内容,则能够取消挂起的请求等)。因此,如果我的数据控制器断定缓存和/或持久存储不能满足请求,它将启动异步请求/解析操作。

  3. 您列出了分配给视图控制器的其他一些职责,但最好也将其抽象出来:

    • 1.2) 处理手势 - 如果手势变得有点复杂(例如仅水平,从边缘滑动等),我实际上将继承手势处理程序,大大简化视图控制器自己与手势处理程序的交互。

    • 3) 定制 UI - 如果 UI 需要大量定制,我也会经常将适当的视图子类化。特别是使用UITableViewCelland UICollectionViewCell,这可以极大地简化一个视图控制器的代码。任何需要任何材质定制的视图通常都可以在视图本身的子类中更优雅地完成。


示例数据控制器抽象

所以,我可能有一个这样定义的完成块:

typedef void(^WeatherRequestCompletion)(WeatherReport *weatherReport, NSError *error);

然后我的数据控制器中可能有一个方法,其接口如下:

- (WeatherRequest *)requestWeatherWithIdentifier:(CityIdentifier)cityIdentifier completion:(WeatherRequestCompletion)completion;

我的视图控制器会像这样使用它:

typeof(self) __weak weakSelf = self;

self.weatherRequest = [[WeatherModel sharedController] requestWeatherWithIdentifier:self.cityIdentifier completion:^(WeatherReport *weatherReport, NSError *error) {
    if (error) {
        // handle error
    }
    if (weatherReport) {
        weakSelf.cityLabel.text       = weatherReport.city;
        weakSelf.tempLabel.text       = [weatherReport.temperature stringValue];
        weakSelf.narrativeLabel.text  = weatherReport.narrative;
    }
}];

视图控制器不应该担心请求的格式或响应的解析方式(这是我的网络请求NSOperation子类的工作)。视图控制器也不应该过多地参与缓存和/或持久存储逻辑(这是我的数据控制器的工作)。因此,视图控制器应该被提炼成非常合乎逻辑且易于理解的东西。

请注意,您会注意到我的数据控制器正在返回一个请求对象(对我来说,这通常只是一个 typedef 到 a NSOperation)。我将让我的视图控制器维护weak对此的引用,以便我可以在需要时轻松取消请求,例如在dealloc视图控制器中):

- (void)dealloc
{
    [_weatherRequest cancel];
}
于 2013-08-14T19:44:46.210 回答
1

其中大部分似乎是典型的 ViewController 行为。苹果确实有一个很好的文档详细描述了 MVC 架构:http: //developer.apple.com/library/ios/documentation/general/conceptual/devpedia-cocoacore/MVC.html

“当模型对象发生变化时(例如,通过网络连接接收到新数据),它会通知控制器对象,控制器对象会更新相应的视图对象。”

这表明您的模型适合处理网络活动和更新。您唯一可以更改的另一件事是将尽可能多的 UI 工作放在视图中。

于 2013-08-14T19:05:24.610 回答