iOS布局;我没有得到它

时间:2011-01-13 14:14:54

标签: model-view-controller ios layout

嗯,“没有得到它”太苛刻了;我已经知道它对我来说是一个逻辑设置,但它似乎并不是iOS认为合乎逻辑的。所以我没有得到什么。

假设我有一个显示两条信息的应用程序;日期和表格。根据MVC的方法,我在这里有三个MVC,一个用于日期,一个用于表,一个用于接收这些MCV并将其制作成屏幕,将它们连接起来。

主MVC知道它想要如何/在哪里布局两个子MVC。每个细节MVC仅在主MVC指定的范围内处理其自己的孩子。类似的东西:

- (void)loadView {
    MVC* mvc1 = [[MVC1 alloc] initwithFrame:...]
    [self.view addSubview:mvc1.view];

    MVC* mvc2 = [[MVC2 alloc] initwithFrame:...]
    [self.view addSubview:mvc2.view];
}

如果以上是合乎逻辑的(对我而言)那么我希望任何MVC类都有一个构造函数“initWithFrame”。但MVC没有,只有视图才有这个。

为什么呢?

如何正确布局嵌套的MVC? (当然我没有这两个,但细节MVC再次有子MVC。)


感谢大家的回复。我将研究提供的链接。

让我再试一次解释我的问题,希望能让它更清楚。请注意,我已经发现我的视图与iOS不匹配,因为我不喜欢我的代码所在的位置。

是的,我正在调用UIViewController一个“MVC”,因为它对我来说实现了MVC的所有方面;它有控制器代码和嵌入式视图,加上控制器通常也保存并提供数据(所有TableView示例都像这样实现它)。

MVC可以存在于多个层面;基本上UITextField可以(应该?)是一个MVC;有一个视图,但也涉及控制器逻辑,你不想与其他代码混合。封装。例如:Java的Swing JTextField有一个MVC。 JTable,JList也是如此......多个MVC模式嵌套在其他MVC中以构建整个屏幕。

这是我所期望的,当某个平台说它使用MVC模式时。因此,当我对表进行编码时,我创建了一个MVC,并且只发送带有日期作为参数的loadData消息。它需要照顾其余部分。我有一个可以滑入的细节MVC;然后我告诉它需要显示的对象,它需要照顾其余部分。封装。

所以我有很多带嵌入式UIViews的UIViewControllers。那不是这样做的方式......

4 个答案:

答案 0 :(得分:8)

另一个潜在的联系是WWDC 2010关于MVC的精彩演讲。

http://developer.apple.com/videos/wwdc/2010/

是Session 116 - 适用于iPhone OS的Model-View-Controllr

本次会议充满了关于MVC如何运作的实用建议,是什么让它成为现实,为什么它是好的。但它也有很多介绍性的东西来帮助新概念的人围绕它。

如果我理解你上面关于Java的Swing课程的句子你是在谈论响应事件的匿名类吗?如果是这样,那些不是“MVC”,它们就是所谓的“观察者”,当他们从视图中观察事件时他们会采取一些行动(通常向控制器发送消息)。 Cocoa Touch使用Target / Action范例(和委托)来实现这一目标。

我也强烈建议你接受马修和斯蒂芬的建议并编写一堆代码。如果你没有建立直觉的基础,那么提出正确的问题(这是获得一个好答案所需的大部分内容)是非常困难的。

我真的认为WWDC 2010的演讲会有所帮助。

祝你好运!

答案 1 :(得分:3)

如果我理解你的问题 - 我可能不会,请看我对它的评论 - 我认为你过于细致地应用了MVC设计模式。最常见的是在您描述的设置中,您将拥有一个模型,一个控制器和多个视图,这些视图被分组/组合,如.xib文件中所示。

在Cocoa Touch术语中,你有一个UIView包含一个带有日期的UILabel和一个用于表的UITableView。这些是你的观点。

你肯定会有一个表数据模型,可能是一组数据。您的日期数据可能来自其自己的模型,如果它是从某事物或计算或其他任何地方检索的日期,这些数据完全独立于数据数组。如果它与数组数据相关联 - 它们都是从数据库中提取出来的,或者日期是从数组数据中计算出来的,或者是你有什么 - 那么你就有了一个模型。

如果数据全部来自单个模型,则单个控制器可能没问题。即使数据来自多个源/模型,您可能只需要/需要此设置中的一个控制器。 UITableView将有一个UITableViewController,同样的控制器也可以提供你的日期。

总之,模型视图控制器设计模式不需要拥有一堆嵌套的模型,视图和控制器。它们可能是,并且足够复杂的项目可能需要它。但是,从广义上讲,您将拥有一个与模型和一个或多个视图相关联的控制器,并且该组对象协同工作以提供一项功能。

答案 2 :(得分:0)

TBEE,

我会在这里发布一个很小的代码示例,因为它似乎并没有真正得到它。

@interface MyView : UIView

@property (retain) IBOutlet UIButton *button1;
@property (retain) IBOutlet UIButton *button2;

@property (assign) bool myData;

-(IBAction) doButton1:(id)sender;
-(IBAction) doButton2:(id)sender;

@end;

@implementation MyView

@synthesize button1 = _button1;
@synthesize button2 = _button2;
@synthesize myData = _myData;

// I'm leaving out the initWithNib, viewDidLoad, etc.

- (IBAction) doButton1:(id)sender
{
  // do something as a result of clicking button1
  _myData = YES;
}

- (IBAction) doButton2:(id)sender
{
  // do something as a result of clicking button2
  _myData = NO;
}

@end

在InterfaceBuilder中连接它们,你就有了一个有效的“MVC”。每个按钮都不需要全新的UIViewController。 View的那个负责它。

UITableView并且它的关联视图更复杂,可能需要额外的UIViewController来帮助封装。我真的不建议首先使用它们,但这是一个good tutorial here.它有a lot of images,它将向您展示如何在IB等中连接。这是旧的,所以你的XCode可能看起来不像图像,但它有帮助。

答案 3 :(得分:0)

感谢您的链接,我会调查一下。

到目前为止,我已经将我的大多数应用程序重写为使用视图而不是viewcontrollers(顶级除了),并且它开始与layoutSubviews可用的API调用相匹配。我觉得令人不安的是我现在需要这样做:

[tableDataSource loadData:date];
[tableView reloadData];

在我以前的设置中,我所做的只是:

[tableViewController loadData:date];

但显然这是做到这一点的方法。有一件事我不清楚ATM。由于我在AppViewController中的loadView中构造和布局视图,如果方向发生变化,它们如何被转发。 VC没有layoutSubviews,所以我应该使用didRotateFromInterfaceOrientation并从那里重新定位子视图?

顺便说一句,我不是将匿名内部类注册为侦听器(观察者)。我在编写Swing组件和JavaFX控件时非常有经验。这可能是罪魁祸首,在Java(FX)中,每个组件都有一个视图和一个控制器(并不总是一个模型)。