Cocoa
01 / 02

Foundation, NSObject & Core Patterns

Cocoa: Foundation, NSObject & Core Patterns

Cocoa is Apple's native application framework for macOS, built on Foundation (non-UI building blocks) and AppKit (UI). Cocoa Touch is the iOS counterpart, built on Foundation and UIKit — most Cocoa-era patterns (delegation, KVO, target-action, MVC) apply to both.

NSObject & the Root Class

// Nearly every Cocoa class inherits from NSObject, which provides:
// - Memory management hooks (retain/release under the hood, ARC-managed)
// - isEqual: / hash for use in NSSet/NSDictionary
// - description for debugging/NSLog output
// - respondsToSelector: / isKindOfClass: introspection

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end

@implementation Person

- (BOOL)isEqual:(id)other {
    if (![other isKindOfClass:[Person class]]) return NO;
    return [self.name isEqualToString:((Person *)other).name];
}

- (NSUInteger)hash {
    return self.name.hash; // must stay consistent with isEqual:
}

- (NSString *)description {
    return [NSString stringWithFormat:@"<Person: %@>", self.name];
}

@end

// UIApplication.shared / NSApplication.shared — the canonical Cocoa singleton
UIApplication *app = UIApplication.shared;
id<UIApplicationDelegate> delegate = app.delegate;

MVC & the Responder Chain

  • Model: your data and business logic — knows nothing about the UI.

  • View: `UIView`/`NSView` subclasses — knows nothing about your data model.

  • Controller: `UIViewController`/`NSViewController` — mediates between Model and View, the traditional Cocoa glue layer.

  • Responder chain: an unhandled event (keyboard shortcut, unhandled gesture) walks up from the first responder → superviews → view controller → window → app delegate until something handles it.

  • First responder: the object currently positioned to receive events first — e.g. the focused `UITextField` for keystrokes.

Target-Action & Delegation

// Target-action — a control calls a method on a target when triggered
button.addTarget(self, action: #selector(didTapSubmit), for: .touchUpInside)

@objc func didTapSubmit() {
    print("Submit tapped")
}

// Delegation — one object hands off responsibility via a protocol,
// rather than being subclassed. The delegate is typically weak.
protocol PersonDelegate: AnyObject {
    func person(_ person: Person, didUpdateAge newAge: Int)
}

class Person {
    weak var delegate: PersonDelegate?
    var age = 0 {
        didSet { delegate?.person(self, didUpdateAge: age) }
    }
}

// UIKit itself is built entirely on this pattern:
// UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate, etc.
class ViewController: UIViewController, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
}

Bundles & Info.plist

// A bundle packages the executable together with resources —
// storyboards, images, localized strings, Info.plist.
let mainBundle = Bundle.main
let version = mainBundle.infoDictionary?["CFBundleShortVersionString"] as? String

if let path = mainBundle.path(forResource: "config", ofType: "plist") { }

// Frameworks and plugins ship as their own independently loadable bundles
let frameworkBundle = Bundle(for: SomeClass.self)

// Info.plist declares app metadata read by both the OS and the app itself:
// - CFBundleIdentifier, CFBundleShortVersionString
// - UISupportedInterfaceOrientations
// - NSCameraUsageDescription, NSLocationWhenInUseUsageDescription, etc.
//   (required privacy usage strings — missing one crashes the app when
//   the corresponding API is first accessed)

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free