Cocoa Design Patterns

Category: Programming
Author: Erik M. Buck, Donald A. Yacktman
All Stack Overflow 18


by anonymous   2017-08-20

Usually communication between unrelated view controllers is a symptom of ugly design. I'd avoid that.

A singleton object might be your best choice. Never ever use the application's delegate or NSUserDefaults to share data between objects. The same applies for saving data in a plist on disk and reload it from the other controller. That's just extremely bad design.

By the way: whatever is your skill level, get this book, Cocoa Design Patterns. It's not directly related to iPhone development, but it explains Cocoa's design and patterns in a clear way. Understanding it will help you a lot in designing your future applications.

by anonymous   2017-08-20

The short answer:

The iOS Developer Collections Reference.

The Whole Story:

I think it would be a good idea to take a broader look at some of the Foundation classes that deal with collections, such as NSArray, NSSet, NSDictionary and if you're feeling particularly esoteric, CFBag.

Your question suggests that you could benefit from reading up on general Cocoa patterns. Indeed, you can pass just about anything from one object to another. An NSArray instance is certainly no different than several NSString instances.

For example, imagine we have an app called "PassingData" (GitHub link). I'm going to define a class which has our data, in this case, several "energyEnhancer" strings.

@interface PDDataSource : NSObject

@property (nonatomic, strong) NSString *engergyEnhancer;
@property (nonatomic, strong) NSString *engergyEnhancer2;
@property (nonatomic, strong) NSString *engergyEnhancer3;


Then in our view controller, we may try to access the energy enhancers, like so:

- (void)logDataSourceWithStrings {

    NSLog(@"Energy enhancer 1: %@", self.dataSource.energyEnhancer);
    NSLog(@"Energy enhancer 2: %@", self.dataSource.energyEnhancer2);
    NSLog(@"Energy enhancer 3: %@", self.dataSource.energyEnhancer3);

Another way to do this is like so:

- (void)logDataSourceWithArray {

    for(NSInteger i = 0; i < self.dataSource.enhancers.count; i++) {
        NSLog(@"Enhancer %i: %@", i, self.dataSource.enhancers[i]);

An added benefit to using an array is that you're no longer limited by the number of variables that you've declared at compile time. Your game or fitness app just got that much more robust.

This is only one way of accessing data that's in another object. Other strong contenders are delegate protocols, notifications, and callback blocks. Typically, if you're directly accessing data in another class, you're probably doing one of three things:

  1. Compositing: Creating a class that contains several objects that exist to help the parent class.
  2. Accessing a singleton. Singleton classes are universally accessible classes that can only be instantiated once. They're controversial, but there are appropriate use cases.
  3. Storing temporary state in an object.

If you want to model more than one kind of data, consider nesting your values (be it arrays, strings, numbers, or whatever) in a dictionary. This isn't always the case, though. I wouldn't want all of my classes to have a single NSDictionary property. Use your best judgement.

Another good strategy when modeling is to use the plist editor in Xcode to mock an object. Then you can make a class (or classes) that match the plist, in code.

It's really worth your time to familiarize yourself with the conventions and Cocoa Design Patterns. Lotsa luck!