如何在objective-c中识别模型,视图和控制器?

时间:2013-09-14 20:10:46

标签: ios objective-c cocoa-touch cocoa model-view-controller

在sublime文本编辑器中来自ruby on rails我的文件夹布局中有模型,视图和控制器文件夹,他可以很容易地识别出什么是。

在objective-c中,我刚刚为我正在关注的新教程创建了一个新项目。我有文件:

BullsEyeViewController.h BullsEyeViewController.m BullsEyeViewController.xib

似乎xib文件是视图。我知道.h文件用于声明,而.m用于我对这些声明的实现。这两个文件会被归类为控制器吗?

如果是这样,我如何识别模型?我已经完成了来自大书呆子牧场的枯燥但必要的Objective-c编程书,但在目标c中谈到MVC时仍然发现自己有点困惑。

我现在正在做另一个课程,我想我会一劳永逸地解决这个问题。在轨道上的红宝石中,我说我可以很容易地识别模型视图和控制器,但是当我试图让我开始感到困惑时,在目标c中。

xib是一个视图?但是它的名字中有viewcontroller,它稍微扭曲了我。非常感谢帮助清除这一切。让我们说我想创建一个处理我所有存储并与数据库通信的文件..在文件名结构方面看起来怎么样?

此外,我现在将appdelegate文件放在支持文件夹中,以减少混淆。 我想做的是创建一个模型,视图和控制器文件夹,并将相关文件放在其中。

5 个答案:

答案 0 :(得分:5)

我只是保持这种结构。

|view
|--all the .xib's and Storyboard
|Controller
|--All the View Controller both .h and .m file
|model
|--.h and .m file for each controller which would be call models.

实施例

|view
|--login.xib
|Controller
|--loginViewController.h
|--loginViewController.m
|model
|--loginModel.h
|--loginModel.m

在LoginModel中,我通常处理API调用并将所有json转换为对象NSMutableDictionary并将数据发送到控制器以进行进一步处理。

在我的loginController中,它将对收到的数据执行操作。

示例:我正在使用AFNetworking进行API调用。

<强> AFHTTPAPIClient.h

#import "AFHTTPClient.h"
#import "AFJSONRequestOperation.h"

@interface AFHTTPAPIClient : AFHTTPClient

+ (AFHTTPAPIClient *)sharedClient;

@end

<强> AFHTTPAPIClient.m

#import "AFHTTPAPIClient.h"

@implementation AFHTTPAPIClient

// Singleton Instance
+ (AFHTTPAPIClient *)sharedClient {
    static AFHTTPAPIClient *sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedClient = [[AFHTTPAPIClient alloc] initWithBaseURL:[NSURL URLWithString:@"www.yourdomain.com"]];
    });
    return sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {

    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }
    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"application/json"];

    return self;
}

@end

<强> loginModel.h

#import "AFHTTPAPIClient.h"

+ (void)loginWith:(NSDictionary *)parameters withBlock:(void (^)(NSMutableDictionary *, NSError *))block;

<强> LoginModel.m

+ (void)loginWith:(NSDictionary *)parameters withBlock:(void (^)(NSMutableDictionary *, NSError *))block {
[[AFHTTPAPIClient sharedClient] postPath:@"/api/login" parameters:parameters
                                 success:^(AFHTTPRequestOperation *operation, id responseObject){
                                     NSLog(@"%@",responseObject);
                                     if (block) {
                                         block(responseObject, nil);
                                     }

                                 }
                                 failure:^(AFHTTPRequestOperation *operation,NSError *error){
                                     if (block) {
                                         block([NSArray array], error);
                                     }
                                 }];
}

然后最终在控制器中使用它们。

<强> loginViewController.m

NSDictionary * loginParametes = [[NSDictionary alloc] initWithObjectsAndKeys:_txtUsername.text,@"username", _txtPassword.text,@"password",nil];
[LoginModel loginWith:loginParametes withBlock:^(NSMutableDictionary *loginInfo, NSError *error) {
    if (!error) {                    
        if([[loginInfo objectForKey:@"status"] boolValue]==YES){
                // Login Success
        }
        else {
                // Login Failure
        }
    }
    else {
                // API Responce failure if content type is not a valid json or valid status code.
    }
}];

答案 1 :(得分:4)

没有编程语言能够真正实现MVC分离。像Ruby of Rails这样的框架有助于引导您使用Ruby语言进行MVC分离。

您可以安全地将文件移动到文件夹中,而不会出现太多问题,从而使您的项目更容易理解。

在UIKit中,会发生以下情况:

浏览

UIView对象通常是视图。 UIViews可以与零到一个UIViewController相关联。 UIView可以序列化为XIB文件或故事板。

控制器

UIViewController是视图控制器。实现UIApplicationDelegate的对象是主应用程序的控制器控制器。 UIViewController也可以通过一种方式进行子类化,使其也成为UISplitViewController,UINavigationController和UITabBarController等控制器的控制器。

那么为什么Xcode将XIB文件命名为与相应的UIViewController相同的名称?

UIViewController的loadView实现分三个阶段搜索指定包中的XIB文件。

  1. 对于名为nibName的nib,如果nibName在指定的包中不为nil。
  2. 对于名为类名的笔尖减去指定包中的“控制器”一词。
  3. 对于在指定包中命名为类名的nib。
  4. 这就是为什么当你在子类中重写loadView时,没有加载任何nib。

    因此,您可以安全地重命名XIB文件以删除单词“Controller”,只要您的UIViewController未在其nibName属性中指定值,一切都将仍然有效。为什么Apple决定让Xcode选择第三种情况作为默认值,当有人猜测自动创建带控制器的笔尖时。

    模型

    模型通常是NSObject的子类。使用Core Data时,模型是NSManagedObject的子类。它创建的xml文件就像一个nib文件 - 它只是模型元数据的序列化。

答案 2 :(得分:2)

这是我过去几周所了解的关于iOS中MVC范例的内容。 与其他语言相比,iOS编程中的MVC设计模式在目标C中实现时采用略有不同的方法。根据MVC范例,您的类BullsEyeViewController是您的控制器。您的.xib文件是您的视图。 Xcode遵循根据您在create-project窗口中指定的类命名文件的模式。您的模型类将实现您的应用程序逻辑。您的大多数数据库管理都将由您的控制器处理。要在此处遵守MVC,您必须以不同方式创建模型类。模型类将通知控制器。控制器将完成更新视图和模型的工作。并响应视图中的用户操作。

答案 3 :(得分:1)

正如您所见,XCode不像Rails那样强制执行MVC结构。自从我使用Rails已经有几年了,所以我可能已经过时了,但我记得这一点:当你启动Rails项目时,你可以提供数据库文件,Rails将使用这些来生成模型对象来描述数据库实体,以及查看/编辑这些模型对象的视图,以及用于连接模型和视图的控制器。

在XCode中创建新的单视图应用程序时,它不会为您生成任何模型文件。它不能,因为它不会让您有机会在创建项目之前指定模型的外观。它只知道您将拥有一个视图,因此它会为您创建该视图(在.xib文件中)和该视图的控制器(在.h和.m文件中)。

.xib文件以控制器命名。我总是觉得这很令人困惑,但这是Apple做出的决定。

您可以通过进入Core Data编辑器并创建新的Core Data Model(文件 - &gt; New - &gt; File - &gt; Core Data - &gt; Data Model)来模拟XCode中的模型创建。当您填写此模型时,您可以通过选择您创建的实体并转到编辑器来创建描述新模型对象的文件 - &gt;创建NSManagedObject子类;这将生成包含您描述的模型对象的.h和.m文件。

当然,您的模型对象不必由持久性存储支持;您可以为它们创建新文件,而无需使用Core Data路径。但是XCode没有强制执行Rails所做的目录结构。它会很乐意将所有MVC文件放在同一目录中。如果你需要,你可以自己创建这个结构。

  

xib是一个视图?但它的名字中有viewcontroller,它稍微扭曲了我。

是的 - 我同意,这很令人困惑。 XCode在其控制器对象之后命名视图文件(.xibs)。我不认为这是一个很好的方法,但你有它。

简而言之:每当您向项目添加新的视图文件时,XCode都会自动为您创建视图和控制器文件。从来没有(据我所知)为你明确创建一个模型文件,除非你使用核心数据编辑器,即使这样它也没有将“模型”放在文件名中 - 它只是在实体之后命名文件你创造了。

答案 4 :(得分:1)

不要被“视图控制器”中的“视图”混淆。

通常是你的“控制者”。如果你使用xib文件或故事板,那么它们通常就是你的“视图”。

模型,明确分离应该在单独的文件中,但是,在许多教程中,模型将由“视图控制器”中的代码表示,并且通常是由数组或字典组成的数据存储。

区域会让您在学习时感到困惑,当您发现“查看”代码时,实际上是在代码中。当您看到[self.view addSubView:someOtherView]等代码以及许多创建UI元素的代码并设置其框架和蒙版等时,通常可以识别出这一点。

不要让这让你感到困惑。它们应该也可能位于不同的文件中,但通常不会混入。即使它位于“视图控制器”中,它实际上也是MVC中的“V”。

在某些例子中,我记得读书,我当时并不知道,但后来意识到他们已经在一个视图控制器中代表了整个MVC。这很有可能,但显然不建议。

其他可能令人困惑的事情: 类属性可以作为模型。例如,25张照片的阵列。您可以找到显示代码以在“视图控制器”侧面进行网络连接和检索照片的示例,但这实际上是“M”代码。检索并存储照片后,该数据的持有者将成为模型。正确的方法是设计一个类来执行网络调用并将照片返回给控制器(视图控制器),然后调用一个用新数据更新UI(视图)的方法。通常这会被混合到视图控制器中,您可能会看到类似于提供完成块的网络调用,并且在完成块中,视图上的属性正在更新。在小型“场景”中,网络调用是引入模型数据的唯一标注,那么在控制器(视图控制器)中使用单个块语句可能真的更简单,更有效。但是,如果为检索数据做了很多标注,那么它确实应该在它自己的类文件中被隔离并且是一个“M”。

在大多数IOS应用程序中,您实际上为每个“场景”或呈现的新视图获得了新的MVC。你真的没有一个控制器,而是很多。用我自己的话说,我也会说你在IOS应用程序中有“控制器控制器”的概念。这些示例包括appDelegate,导航控制器,tabbar控制器,拆分视图控制器。您可能还有一个模型控制器,例如Core Data,一个通过其上下文控制许多模型对象的大控制器。如果你想一想,故事板真的只是一个观点的控制者。在这些情况下,您可以为每个场景挑选出所需的特定控制器,视图和模型对象,并将它们连接在一起。

希望这有助于而且不会引起更多混乱。 好吧。