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