开发者

How do you keep Cocoa controllers from getting too big?

开发者 https://www.devze.com 2022-12-30 13:22 出处:网络
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. Th

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 i开发者_如何学Gon layers using inheritance, but that feels like a hack.


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:

  • Accessors
  • Delegation
  • Notifications
  • Key-Value Observing
  • Target-action
  • Blocks

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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消