如何防止 Cocoa 控制器变得太大?

发布于 2024-09-01 16:07:28 字数 242 浏览 4 评论 0原文

您是否有一些技巧或技巧可以将 Cocoa 控制器类分解为更小的块?我发现无论我做什么,控制器最终都会成为我设计中更复杂的类之一。基本的东西很简单,但是一旦我运行了几个弹出窗口或操作表,事情就会变得非常复杂。这并不是那么糟糕,但我仍然想将代码重构为几个独立的部分。

我考虑过类别,但代码并不是那么独立(例如,很多时候它需要利用 viewWillAppear),而且我发现我花了很长时间与编译器作斗争。我还考虑过使用继承在层中添加功能,但这感觉就像一个黑客。

Do you have some tricks or techniques to break Cocoa controller classes into smaller chunks? I find that whatever I do the controllers end up being one of the more complicated classes in my design. The basic stuff is simple, but once I have several pop-overs or action sheets running, things get uncomfortably complex. It's not that bad, but still I would like to refactor the code into several standalone parts.

I thought about categories, but the code is not that independent (a lot of times it needs to tap into viewWillAppear, for example) and I find that I spend a long time fighting the compiler. I also thought about adding functionality in layers using inheritance, but that feels like a hack.

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

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

发布评论

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

评论(3

寒江雪… 2024-09-08 16:07:28

问题不在于规模,而在于责任。您的控制器是否戴着不止一顶帽子?如果是这样,请将其分解为多个、每类一个作业的控制器。

类别有助于确定规模,但无助于确定责任。如果你仍然在一个(合并的)班级中做多项事情,那么你仍然有一个问题;将它们移动到单独的文件中并没有解决问题。

单个类上有多个类别会带来方法冲突的风险:在多个类别中实现相同的方法,可能是在类别 B 中实现它,而忘记类别 A 已经有一个方法。当对象向自己发送消息并期望一个类别对该消息的响应并获取另一个类别的响应时,这将导致问题。

在主类标头中声明所有类别可以减轻这种风险,因为您可以看到另一个类别已经具有您要输入的名称的方法。但是,您添加的每个方法都会延长头文件,从而减轻缓解措施。

如果你的控制器戴着不止一顶帽子,请将其分解为多个类别。

我推荐Martin Fowler 的书《重构》。重构你的代码就是清理它,而破坏太大的类(以及方法和函数)是这种清理的一个子集。

当然,曾经是一个整体的多个类需要替代以前在类内部进行的通信。 Cocoa 提供了多种解决方案:

您不需要精确选择一个,也不需要需要全部使用它们。哪种解决方案合适将取决于新班级之间的沟通需求。

The issue is not size, but responsibility. Is your controller wearing more than one hat? If so, blow it up into multiple, one-job-per-class controllers.

Categories help with size, but not responsibility. If you're still doing multiple things in one (amalgamated) class, then you still have a problem; moving them into separate files did not solve it.

Having many categories on a single class brings a risk of method collisions: implementing the same method in multiple categories, probably by implementing it in category B while forgetting that category A already has one. This will cause a problem when the object sends itself a message, expecting one category's response to that message and getting the other's.

Declaring all of the categories in the main class header mitigates that risk, as you can see that another category already has a method by the name you're about to enter. However, every method you add, thereby lengthening the header file, mitigates the mitigation.

If your controller is wearing more than one hat, blow it up into multiple classes.

I recommend Martin Fowler's book “Refactoring”. Refactoring your code is cleaning it up, and blowing up too-big classes (and methods and functions) is a subset of such clean-up.

Of course, multiple classes that once were one need a replacement for the communication that was previously internal within the class. Cocoa provides a number of solutions:

You don't need to pick exactly one, nor do you need to use them all. Which solutions are appropriate will depend on exactly what communication needs your new classes will have with each other.

还在原地等你 2024-09-08 16:07:28

类别是必经之路。技巧(对于“不是那么独立”的东西)是在主控制器 .h 文件中声明类别方法(不是单独的控制器+category.h 文件,不会有),然后在控制器+类别中实现它们。 .m 文件。像这样:

//******************
// MyController.h
//******************
#import <Cocoa/Cocoa.h>

@interface MyContoller : NSObject 
{
    NSWindow   *window;

    // stuff to implement in the category
    NSComboBox *someCombo;
    NSButton       *someButton; 
}

@property IBOutlet NSWindow   *window;

@property IBOutlet NSComboBox *someCombo;
@property IBOutlet NSButton   *someButton;

@end

@interface  MyController (MyCategory)

- (IBAction)someComboSelected:(id)sender;
- (IBAction)someButtonPressed:(id)sender;

@end

//**************************
// MyController+MyCategory.m
//**************************
#import <Cocoa/Cocoa.h>
#import "MyController.h"

@implementation MyContoller (MyCategory)

- (IBAction)someComboSelected:(id)sender
{
    ....
}

- (IBAction)someButtonPressed:(id)sender
{
    ....
}

显然,我没有包含“MyController.m”,您可以在其中放置“@synthesize”内容以及主控制器/awake-from-nib/其他内容所需的其他内容。无论如何,这样做可以让您的控制器方法访问类别方法,反之亦然,并且类别方法可以访问所有属性。

Categories is the way to go. The trick (for your "not that independent" stuff) is to declare the category methods in your main controller .h file (not a separate controller+category.h file, there will be none) then implement them in your controller+category.m file. Like this:

//******************
// MyController.h
//******************
#import <Cocoa/Cocoa.h>

@interface MyContoller : NSObject 
{
    NSWindow   *window;

    // stuff to implement in the category
    NSComboBox *someCombo;
    NSButton       *someButton; 
}

@property IBOutlet NSWindow   *window;

@property IBOutlet NSComboBox *someCombo;
@property IBOutlet NSButton   *someButton;

@end

@interface  MyController (MyCategory)

- (IBAction)someComboSelected:(id)sender;
- (IBAction)someButtonPressed:(id)sender;

@end

//**************************
// MyController+MyCategory.m
//**************************
#import <Cocoa/Cocoa.h>
#import "MyController.h"

@implementation MyContoller (MyCategory)

- (IBAction)someComboSelected:(id)sender
{
    ....
}

- (IBAction)someButtonPressed:(id)sender
{
    ....
}

Obviously, I didn't include "MyController.m", where you put the "@synthesize" stuff and whatever else is needed for the main controller/awake-from-nib/whatever. Anyway, doing it this way gives your controller methods access to the category methods and vise-versa, and the category methods have access to all the properties.

听风吹 2024-09-08 16:07:28

在常规的 Cocoa 中,NSViewController 可用于通过允许窗口内的“组件”拥有自己的整体控制器来管理控制器的复杂性。

您也许可以使用 UIViewController 执行类似的操作,或者您可能希望在视图/视图控制器层次结构之外创建“协调控制器”以单独管理模型对象的行为。

In regular Cocoa, NSViewController can be used to manage controller complexity by allowing "components" within a window to have their own overall controllers.

You may be able to do something similar with UIViewController, or you may want to create "coordinating controllers" outside your view/view controller hierarchy to manage your model objects' behaviors separately.

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