4

I need to create a class controller to manage the behavior of a custom view I created. The standard approach is to subclass UIViewController, but in my case I instead decided to subclass the NSObject essentially for three reasons:

  • my view needs to be added as small subview of the main view controller (it will not be displayed using something like presentModalViewController or pushViewController...) and it does not require any kind of toolbar or navigation control inside of it
  • Most probably my controller will not need to be notified for device orientation because its view will be always used in portrait format, so I'm not interested to receive the usual rotation messages willRotateToInterfaceOrientation etc...
  • I need to keep this class as lightweight as possible minimizing memory consumption. Not subclassing UIViewController have the advantage to obtain a lighter class without a bunch of methods that I will never need to use

The interface of my controller is pretty simple, example:

@interface MyScrollTabBarController : NSObject <MyTabBarViewDelegate> { }

/**
 * The view is created internally by the controller and the client class
 * can access to it in readonly mode
 */
@property (nonatomic, readonly) UIView *view;

/**
 * A Property to change the view appearance
 */
@property (nonatomic, assign) MyScrollTabBarViewState viewState;

/**
 * Others properties used to construct the view's subviews
 */
@property (nonatomic, retain) Location *rootLocation;
@property (nonatomic, readonly, retain) Place *place;

/**
 * Designated initializer
 */
- (id)initWithPlace:(Place *)aPlace;

- (void)setRootLocation:(Location *)location animated:(BOOL)animated;

@end

To display its internal view from the parent view controller, I will use something like this:

tabBarController = [[MyScrollTabBarController alloc] initWithPlace:aPlace];
tabBarController.viewState = MyScrollTabBarViewStateXX;
tabBarController.view.frame = CGRectMake(...); 
[self.view addSubview:tabBarController.view];

I'd like to know what do you think about my choice, if you think that there could be drawbacks in it and what do you usually do when you need to write a controller for a view which is not fullscreen like mine.

Thanks

ggould75
  • 880
  • 2
  • 14
  • 23

4 Answers4

1

I think this is an acceptable solution.

Another solution would be creating a "fat" view that does its controlling itself (like, for instance, MKMapView, UITextView etc.). This might make things a little more manageable, and if the view is very specialized, and its controller is intended to only work with this one class of view, you don't really lose any reusability (because there isn't much).

fzwo
  • 9,842
  • 3
  • 37
  • 57
  • Yes, this is the other possibility I was thinking about. Embedding all in a "fat" view instead of using a controller has perhaps another benefit: it simplify the memory warning and viewDidUnload situations. With a controller (in the case it inherit from NSObject) I usually have to forward every viewDidUnload event that happen from the main controller to my controller. On the other hand using a custom fat view I can do a simple self.myView = nil; – ggould75 Jan 19 '12 at 12:08
1

Yes, this is the correct approach.

UIViewControllers are specifically for controlling full-screen views, not for sub-screens. In iOS5 there is a mechanism for composing sub-screen viewcontrollers in this way, but that's not available in iOS4 without lots of hackery.

In cases where the view and controller are inherently coupled, you could also consider making a custom view subclass that is its own controller, so for example you could have a self-contained table view subclass that managed its own data and could just be dropped into a page.

Nick Lockwood
  • 40,865
  • 11
  • 112
  • 103
  • Unfortunately I can not take advantage of the new iOS5 features because my application have to support iOS 4 a later – ggould75 Jan 19 '12 at 12:21
  • Yes, I assumed that was the case. That's why using an NSObject or using your view as its own controller is the correct approach. – Nick Lockwood Jan 19 '12 at 17:14
0

what do you usually do when you need to write a controller for a view which is not fullscreen like mine

It is not important that your view is not displayed full screen. It is possible (and usual) to have views consisting of subviews which each have their own controller.

I need to keep this class as lightweight as possible minimizing memory consumption. Not subclassing UIViewController have the advantage to obtain a lighter class without a bunch of methods that I will never need to use

Subclassing UIViewController does not consume an unreasonable amount of memory, so this should not be part of the consideration.

[...] if you think that there could be drawbacks in it [...]

With your solution you loose flexibility. It is likely that you will reuse your solution in a context where you need to respond to UILifecyle-Messages or use other UIViewController features.

If your views shall be lightweight you could consider using a UIView subclass and use a delegate for the logic behind your view.

Ben-G
  • 4,996
  • 27
  • 33
  • 1
    Using UIViewControllers for non-fullscreen views is not supported prior to iOS 5 and even in iOS 5 remains the exception rather than the rule - which is not to say one shouldn't do it in the right circumstances. It *could* be done in this case (if no compatibility with iOS 4 is needed), but I see no compelling reason. Flexibility probably also doesn't factor in in this case, because the views are likely very specialized, so won't be reused elsewhere. Also, using a custom NSObject contoller instead of a custom UIViewController is explicitly recommended in the docs. – fzwo Jan 19 '12 at 16:12
  • fzwo, do you remember where in the docs did you read that? I'd like to read it – ggould75 Jan 19 '12 at 16:40
  • See the dire warning at the bottom of this docs page: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/UsingViewControllersinYourApplication/UsingViewControllersinYourApplication.html – Nick Lockwood Jan 19 '12 at 17:22
  • Basically, view controllers should either be managing the root view on screen, or should be a child of a container view controller, which prior to iOS5 meant a tabbarcontroller or navigationcontroller, as there was no way to make your own. Creating view controllers that manage a subview of the screen but are not themselves a child of a container controller is not, and has never been supported because it screws up event forwarding (e.g. viewDidAppear, screen rotation events, etc) – Nick Lockwood Jan 19 '12 at 17:25
  • @ggould75 I'm sorry, I can't seem to find where I read this. But in Session 102 of the WWDC 2011 videos, they also mention in passing that using view controller containment will not be necessary for a majority of applications (or something to that effect), IIRC. – fzwo Jan 20 '12 at 14:44
0

Hi You are subclassing NSObject and declaring a UIView inside it

@interface MyScrollTabBarController : NSObject <MyTabBarViewDelegate> { }

@property (nonatomic, readonly) UIView *view;

I Suggest you should subclass UIView, so you will not have to declare an additional view object.

so instead of self.view you can simply refer as self

tabBarController = [[MyScrollTabBarController alloc] initWithPlace:aPlace];
tabBarController.viewState = MyScrollTabBarViewStateXX;
tabBarController.frame = CGRectMake(...); 
[self.view addSubview:tabBarController];
Krrish
  • 2,256
  • 18
  • 21