如何处理iOS应用程序中的模型类

发布于 2024-12-01 00:10:44 字数 353 浏览 3 评论 0原文

我是 iOS 应用程序开发的新手,但我正在尝试学习如何以最好的方式处理 Cocoa。

我试图理解如何正确保存和引用模型对象。

  1. 许多人说编写一个应用程序委托属性来保存模型,然后通过应用程序委托单例的便捷方法引用它。
  2. 其他人说在视图控制器中仅“注入”它需要的模型部分(或其子视图需要),但我不明白如何做到这一点。通过财产?通过 initWithModel: 方法(在这种情况下,我怎么能告诉 IB 使用该方法?)
  3. 其他人再次说模型应该是单例
  4. ,其他人又说使用全局变量(!)

你能给我吗一些提示(和代码示例)?考虑到我很快就会转向核心数据,我想以正确的方式学习这些东西。

I am a newbie in iOS application development, but I am trying to learn how to deal with Cocoa in the best way.

I got stuck trying to understand how to keep and reference the model objects properly.

  1. many say to write an app delegate property to hold the model and then reference it through the convenience methods for the app delegate singleton.
  2. others say to "inject" in the view controller only the part of model which it needs (or its subviews needs), but I don't understand how to do this. Via a property? Via an initWithModel: method (and in this case, how can I say to IB to use that method?)
  3. others again say that the model should be a singleton
  4. and again, others say to use global variables (!)

Could you please give me some hint (and code samples)? I would like to learn the things in the proper manner, considering that soon I will be moving towards Core Data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

拥抱我好吗 2024-12-08 00:10:44

摘要:我仔细阅读了主题Brad Larson 建议的 Cocoa/Cocoa Touch 应用程序中“核心数据堆栈”的放置位置,我编写了一个关于如何处理模型和不同视图控制器的可能解决方案。该解决方案不使用 Core Data,但我相信相同的设计可能适用于 Core Data 应用程序。

场景:让我们考虑一个简单的应用程序,它存储有关产品的信息,例如名称、描述和单价。启动后,应用程序会显示产品列表(带有 UITableView);当用户点击产品名称时,应用程序会在另一个视图中显示产品详细信息,并使用产品名称更新导航栏。

架构 这里的模型非常简单:一组 Product 对象,每个对象都有一个名称、一个描述和一个价格属性。

该应用程序具有三个主要视图,主要由 Xcode 的导航模板创建:UINavigationView(由 UINavigationController 管理,在应用程序委托中实例化)、默认 UITableView(由 RootViewController 管理,这是 UINavigationController 显示的第一个视图)和一个 DetailView(由我们必须编写的 DetailViewController 类管理)。

让我们从模型的角度来看一下大计划是什么:

  1. 模型由 Application delegate 实例化/加载为 Product 对象的 NSMutableArray;
  2. 现在,指向模型的指针通过属性传递给层次结构的第一个视图控制器 UITableViewController。实际上,有人可能会争辩说,层次结构中的第一个控制器是 UINavigationController,因此我们应该传递对它的引用,并从它传递到 UITableViewController,但是......Apple 说 UINavigationController 不应该被子类化,因此我们不能添加任何属性/方法。实际上这是有道理的,因为 UINavigationController 的职责始终只是可视化管理,而不是模型操作。
  3. 当用户选择 UITableCell 时,UITableViewController 会创建一个新的 DetailViewController(具有关联的 DetailView),将单个选定的产品作为属性传递,并将 DetailView 推送到 UINavigation 堆栈的顶部。

下面是一些代码片段:

创建模型:

// SimpleModelAppDelegate.m    

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // products is a protected ivar
    products = [[NSMutableArray alloc] init];

    Product *p1 = [[Product alloc] initWithName:@"Gold" andDescription:@"Expensive metal" andUnitPrice:100];
    Product *p2 = [[Product alloc] initWithName:@"Wood" andDescription:@"Inexpensive building material" andUnitPrice:10];

    [products addObject:p1];
    [products addObject:p2];

    [p1 release];
    [p2 release];

    // Passing the model reference to the first shown controller 
    RootViewController *a = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0];
    a.products = products;

    // Add the navigation controller's view to the window and display
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)dealloc
{
    // The app delegate is the owner of the model so it has to release it.
    [products release];
    [_window release];
    [_navigationController release];

    [super dealloc];
}

RootViewController 可以接收模型引用,因为它有一个 NSMutableArray 属性:

// RootViewController.h

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController

@property (nonatomic, retain) NSMutableArray *products;

@end

当用户点击产品名称时,RootViewController 实例化一个新的 DetailViewController 并将对单个产品的引用传递给它再次使用属性。

// RootViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Passing the model reference...
    detailViewController.product = [products objectAtIndex:indexPath.row];

    [self.navigationController pushViewController:detailViewController animated:YES];

    [detailViewController release];
}

最后,DetailViewController 在 vi​​ewDidLoad 方法中显示设置其出口的模型信息。

// DetailViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = product.name;
    self.descriptionLabel.text = product.description;
    self.priceLabel.text = [NSString stringWithFormat:@"%.2f eur", product.unitPrice];
}

您可以在此处下载完整的项目:http://dl.dropbox。 com/u/1232650/linked/stackoverflow/SimpleModel.zip

我非常感谢对我的解决方案的任何评论,我渴望学习;)

Abstract: I read carefully the topic Where to place the "Core Data Stack" in a Cocoa/Cocoa Touch application suggested by Brad Larson and I wrote a possible solution on how to deal with a model and different view controllers. The solution doesn't use Core Data, but I believe that the same design may be applied to Core Data apps.

Scenario: let's consider a simple application which stores information about products, such as name, description and price/unit. Once launched, the application shows a list of products (with a UITableView); when the user taps on a product name, the application presents product details in another view, updating the navigation bar with the product name.

Architecture The model is pretty simple here: an array of Product objects, each one with a name, a description and a price property.

The application has got three main views, mostly created by the Navigation template of Xcode: a UINavigationView (managed by the UINavigationController, instantiated in the app delegate), the default UITableView (managed by RootViewController and which is the first view shown by the UINavigationController) and a DetailView (managed by the DetailViewController class we have to write).

Let's see what's the big plan from the model point of view:

  1. The model is instantiated/loaded by the Application delegate as a NSMutableArray of Product objects;
  2. The pointer to the model is now passed to the first view controller of our hierarchy, UITableViewController, through a property. Actually, one could argue that the first controller in the hierarchy is the UINavigationController, so we should pass the reference to it and from it to the UITableViewController but... Apple says that UINavigationController shouldn't be subclassed, so we cannot add any property/method. And actually it makes sense, because the responsibility of an UINavigationController is always just the visualization management, not the model manipulation.
  3. When the user select a UITableCell, the UITableViewController creates a new DetailViewController (with the associated DetailView), passes the single selected product as a property and pushes the DetailView on the top of the UINavigation stack.

Here some code snippets:

Creation of the model:

// SimpleModelAppDelegate.m    

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // products is a protected ivar
    products = [[NSMutableArray alloc] init];

    Product *p1 = [[Product alloc] initWithName:@"Gold" andDescription:@"Expensive metal" andUnitPrice:100];
    Product *p2 = [[Product alloc] initWithName:@"Wood" andDescription:@"Inexpensive building material" andUnitPrice:10];

    [products addObject:p1];
    [products addObject:p2];

    [p1 release];
    [p2 release];

    // Passing the model reference to the first shown controller 
    RootViewController *a = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0];
    a.products = products;

    // Add the navigation controller's view to the window and display
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)dealloc
{
    // The app delegate is the owner of the model so it has to release it.
    [products release];
    [_window release];
    [_navigationController release];

    [super dealloc];
}

The RootViewController can receive the model reference, since it has a NSMutableArray property:

// RootViewController.h

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController

@property (nonatomic, retain) NSMutableArray *products;

@end

When the user taps on a product name, the RootViewController instantiates a new DetailViewController and passes the reference to the single product to it using a property again.

// RootViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Passing the model reference...
    detailViewController.product = [products objectAtIndex:indexPath.row];

    [self.navigationController pushViewController:detailViewController animated:YES];

    [detailViewController release];
}

And, at the end, the DetailViewController shows the model information setting its outlets in the viewDidLoad method.

// DetailViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = product.name;
    self.descriptionLabel.text = product.description;
    self.priceLabel.text = [NSString stringWithFormat:@"%.2f eur", product.unitPrice];
}

You can download the full project here: http://dl.dropbox.com/u/1232650/linked/stackoverflow/SimpleModel.zip

I will really appreciate any comment to my solution, I am eager to learn ;)

悲念泪 2024-12-08 00:10:44

更有经验的同事建议在AppDelegate中拥有相关属性。
IMO 最好在特定控制器中使用特定的模型集。

More experienced colleagues recommend to have relevant property in AppDelegate.
IMO it is better to use specific set of models in specific controller.

把回忆走一遍 2024-12-08 00:10:44

我也是菜鸟,但这就是我所做的。它最像#2。

在 applicationDidFinishLaunching 中,应用程序委托创建模型的实例。

我的视图控制器声明一个指向模型的属性,但类型是一个协议(在我的例子中 id。协议中的许多属性都声明为只读。

在 applicationDidFinishLaunching 中,应用程序委托将属性设置为指向它创建的模型

一。您的视图控制器不必了解应用程序委托的结构。您可能会在另一个应用程序中重用相同的视图控制器。 ,有一个不同的应用程序委托类型。您可以对视图控制器代码进行简单的更改来解决这个问题,或者还有其他方法可以解决这个问题,但为什么要让它变得困难呢?

三。如果您想加载多个模型怎么办?!

?!四个。

I'm a noob too but here's what I did. It's most like #2.

In applicationDidFinishLaunching, the app delegate creates an instance of the model.

My view controllers declare a property pointing to the model, but the type is a protocol (in my case id <GameModel>. Many of the properties in the protocol are declared as readonly.

In applicationDidFinishLaunching, the app delegate sets the property to point to the model it created.

What I don't like about:

One. Your view controllers shouldn't have to know about the structure of your app delegate. You might reuse the same view controller in another app, with a different app delegate type. You could make simple changes to your view controller code to fix that, or there are other ways to get around it, but why make it hard?

Three. I am not as fond of singletons as most people. The problem is they're single. What if you want to have multiple models loaded?

Four. ?!?!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文