0

I recently asked a question regarding my incorrect use of instance variables on UIViewControllers. The answers I got brought to light another fundamental issue: I think I might be using UIViewControllers all wrong as well.

My typical storyboard looks something like this:

enter image description here

As you can see, each view controller has a custom class. One of those custom classes might look like this:

//  SecondViewController.h

#import <UIKit/UIKit.h>
#import "MasterViewController.h"

@interface SecondViewController : MasterViewController

@property (strong, nonatomic) NSData *incomingData;

@end


//  SecondViewController.m

#import "SecondViewController.h"
#import "ThirdViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // do stuff with data, then pass it on to next view controller.
}

@end

Each view controller is a subclass of MasterViewController. In MasterViewController, I'll usually put global things like user state validation, for example. That way every view controller in the app can validate user state without reimplementing it each time.

About that incomingData property...I wasn't sure how else to pass data between UIViewControllers without using a property on a custom class...hence three separate custom classes, each one not doing all that much.

So here's where it gets murky for me...

  • Should I be keeping important methods and instance variables in a "master" view controller so all other view controllers can subclass it and have access to those methods and variables? Or is that ridiculous?
  • Am I causing more work for myself by not using proper class extensions or categories? Would those help me keep things a little more streamlined and organized?

My current system works for the most part, but it can get unwieldy when I have lots and lots of view controllers, each with its own custom class.

Community
  • 1
  • 1
jmoneystl
  • 773
  • 1
  • 8
  • 23
  • Personally, I will create a singleton that will help me manage my data that may need to be accessed by multiple view controllers (things such as a REST Client). – AdamPro13 Sep 30 '14 at 22:47

3 Answers3

0

What you have here is Strong coupling, which is considered to be a bad thing.

Lets say you want to create a new application, and you want to copy a view controller from the old application, at the moment it would be very difficult for you as you would have to modify a lot of things.

The goal is to achieve weak coupling, which means that every class in your project can work independently from one another.

Allan Spreys
  • 5,287
  • 5
  • 39
  • 44
  • it is hard to have weak coupling between your model and your controller, which is the objects that are being referred to here – Paulw11 Sep 30 '14 at 22:54
  • @Paulw11 Yes it is, and I was not saying that it needs to be done. However, a single MVC can easily be an independent model. – Allan Spreys Oct 01 '14 at 01:30
0

You can store your data as a property on your App Delegate, which is a singleton, so you can get an reference from an any class using AppDelegate *appDelegate=[UIApplication sharedApplication].delegate;. Or you can define a new singleton object to store the data.

The pattern you are using is dependency injection, which many people prefer to the singleton pattern.

If all of your view controllers are inheriting from the same superclass (MasterViewController) and all have that same property then you can simply define the property in the superclass.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
0

Obviously, the first step which you may have done, and whether you've completely grasped or not, is to really understand the Model-View-Controller pattern. A pretty good tutorial I did with a quick google search is here: http://codewithchris.com/how-to-make-iphone-apps-mvc-one-pattern-to-rule-them-all/.

The next thing I'd suggest is that your controllers don't need to be subclasses of anything but UIViewController. There's a difference between the view hierarchy and the class hierarchy. In your storyboard, you're outlining a view hierarchy - which view/controller leads to the next view/controller. They can all be independent. They can still pass data even without being subclasses of each other, or of a previous controller.

You can still pass data directly through properties. Why not be more specific about what data needs to be sent? Instead of sending a generic NSData blob, specify what you need one controller to tell the next. For example, if you're passing in a username from one to the next, use:

@property (nonatomic, strong) NSString *username;

for the second controller, and in your first controller, set it:

self.secondController.username = @"my name";

If from the second controller to the third controller, you don't need the username, don't make it a property of the third controller. Maybe the third controller only displays a number:

@property (nonatomic, strong) NSNumber *someNumber;

From the second controller, just set its value:

self.thirdController.someNumber = @5;

Now, I like to use some global variables and methods. Those are sometimes useful when you have helper classes that don't need to be instantiated. One way to do this is to just have a class variable:

FirstController.h:

+(NSString *)defaultName;

FirstController.m

+(NSString *)defaultName {
    return @"Default";
}

Then in second controller, you can do something like

self.username = [FirstController defaultName]

There are other patterns, like delegate patterns, where the second controller asks its delegate (the first controller) what the username should be:

self.username = [self.delegate username];

But for this you have to set up a protocol. Ray Wenderlich usually has very good tutorials: http://www.raywenderlich.com/46988/ios-design-patterns

mitrenegade
  • 1,834
  • 18
  • 28
  • `They can all be independent. They can still pass data even without being subclasses of each other, or of a previous controller.` But wouldn't all of your examples require the view controller to have a custom subclass? Otherwise, how would they have custom properties like `someNumber`? – jmoneystl Oct 16 '14 at 18:46
  • yes, each controller is just a subclass of UIViewController. Typically that's what all your controllers should be if they have any parameters. That's what I mean...they don't need to be subclasses of each other. – mitrenegade Oct 16 '14 at 23:12