~/src/www.mokhan.ca/xlgmokha [main]
cat objective-c.md
objective-c.md 50362 bytes | 2013-05-08 09:22
symlink: /dev/random/objective-c.md

SAIT - CPRG-190: Objective-C Course Notes

Key Terminology

  • OTA: Over The Air download
  • xcodeproj: Xcode project file
  • IPA: iOS Application Archive (compiled app package)
  • Provisioning Profile: Certificate that allows apps to run on devices

Historical Context

Why “NS” Prefix?

Objective-C was created by NeXT (the company founded by Steve Jobs after leaving Apple). NeXT introduced their object-oriented operating system called NeXTSTEP in the late 80s. Many Objective-C classes still use the “NS” prefix as a reference to NeXTSTEP.

Why “@” Symbol for Strings?

Objective-C is a strict superset of C, meaning you can compile any C code in an Objective-C project. However, in Objective-C we use object-oriented NSStrings instead of C strings. The @ symbol tells the compiler that what follows is an Objective-C NSString, not a C string.

Data Types

Primitive Data Types (5 total)

  1. int - integer (32-bit signed)
  2. float - floating point number (32-bit)
  3. double - double precision floating point number (64-bit)
  4. char - single character (8-bit)
  5. BOOL - YES or NO (essentially a char with special meaning)

Important: Everything else is a Class data type.

Additional Primitive Types

  • NSInteger - Platform-specific integer (32-bit on 32-bit systems, 64-bit on 64-bit)
  • NSUInteger - Unsigned platform-specific integer
  • CGFloat - Platform-specific floating point (float on 32-bit, double on 64-bit)

Variables

  • Variables identify values and are always strongly typed
  • Every variable must be declared with one specific data type
// Variable declaration and assignment
int myInt;
myInt = 5;

// Declaration and initialization in one line
int myInt = 5;

// Platform-specific types (recommended for iOS)
NSInteger betterInt = 42;
CGFloat screenWidth = 320.0;

Format Specifiers for NSLog

  • %d - int
  • %ld - NSInteger (long)
  • %f - float, double
  • %c - char
  • %@ - any object (e.g., NSString)
  • %p - pointer address

Note: For BOOL values, use %d to get the integer value (0 for NO, 1 for YES)

NSString (Object Type)

All objects use pointers. A pointer holds a reference to a memory address instead of the actual value.

NSString *myString = @"Hello";
NSLog(@"What the what? %@", myString);

// String formatting
NSString *formatted = [NSString stringWithFormat:@"Number: %d", 42];

// Literal syntax (modern)
NSString *literal = @"This is a string literal";

Operators

Arithmetic Operators

  • + Add
  • - Subtract
  • * Multiply
  • / Divide
  • % Remainder (modulus)
  • = Assignment
  • += Add right to left, assign to left
  • -= Subtract right from left, assign to left
  • *= Multiply left by right, assign to left
  • /= Divide left by right, assign to left
  • %= Left modulus right, assign to left
  • ++ Increment by 1
  • -- Decrement by 1

Relational Operators

Work the same as other C-based languages:

  • == Equal to
  • != Not equal to
  • < Less than
  • <= Less than or equal to
  • > Greater than
  • >= Greater than or equal to

Logical Operators

Work the same as other C-based languages:

  • && AND
  • || OR
  • ! NOT

Custom Classes

Class Structure

  • NSObject is the top-level parent class of all Objective-C classes
  • Objective-C classes consist of two files:
    • Interface file (.h) - “header” file containing class declarations
    • Implementation file (.m) - contains actual class content

Interface File (.h)

Contains declarations visible to other classes, wrapped in @interface and @end:

#import <Foundation/Foundation.h>

@interface Person : NSObject

// Properties
@property (strong, nonatomic) NSString *firstName;
@property (strong, nonatomic) NSString *lastName;
@property (assign, nonatomic) NSInteger age;

// Method declarations
-(void)name:(NSString *)theName age:(int)theAge;
-(NSString *)fullName;
+(Person *)personWithName:(NSString *)name; // Class method

@end

Implementation File (.m)

Contains actual class content, wrapped in @implementation and @end:

#import "Person.h"

@implementation Person

-(void)name:(NSString *)theName age:(int)theAge
{
    self.firstName = theName;
    self.age = theAge;
}

-(NSString *)fullName
{
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

+(Person *)personWithName:(NSString *)name
{
    Person *person = [[Person alloc] init];
    person.firstName = name;
    return person;
}

@end

Key Point: Everything inherits from NSObject - this is the foundation of the Objective-C class hierarchy.

Object Creation and Usage

Message Passing Philosophy

In Objective-C, you don’t “call methods” or “invoke functions” - you “send messages” to objects. This is a fundamental concept that distinguishes Objective-C from other languages.

Creating Objects

Class Methods vs Instance Methods

// Sending message to CLASS (class method)
Person *person = [Person new];

// Sending message to INSTANCE (instance method)
[person sayHi];

The new Method vs alloc/init

// Basic instantiation using new (rarely seen in practice)
Person *person = [Person new];

// Preferred method - explicit two-step process
Person *person = [[Person alloc] init];

// Custom initialization
Person *person = [[Person alloc] initWithName:@"John"];

Why the two-step approach is preferred:

  1. alloc - Allocate memory for the object
  2. init - Initialize the object (can use different init methods)

Property Access

Message Syntax

Person *person = [[Person alloc] init];

// Setting property via message
[person setFirstName:@"Mo"];

// Getting property via message
NSLog(@"%@", [person firstName]);

Dot Syntax (Syntactic Sugar)

Person *person = [[Person alloc] init];

// Setting property with dot syntax
person.firstName = @"Mo";

// Getting property with dot syntax
NSLog(@"%@", person.firstName);

Note: Both approaches are equivalent - dot syntax is just cleaner to read and write.

Methods (Messages)

Basic Method Syntax

// Instance method with no parameters
-(void)doSomething
{
}

// Instance method with one parameter
-(void)doSomething:(NSString *)firstThing
{
}

// Method with return value
-(NSString *)getFullName
{
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

// Class method (static)
+(Person *)createDefaultPerson
{
    return [[Person alloc] init];
}

Named Parameters (Method Labels)

Objective-C supports descriptive method names with multiple labeled parameters:

// Interface declaration
@interface Person : NSObject
-(void)setName:(NSString *)theName age:(int)theAge;
-(void)moveToLocation:(NSString *)location withDistance:(float)distance;
@end

// Implementation
@implementation Person
-(void)setName:(NSString *)theName age:(int)theAge
{
    self.firstName = theName;
    self.age = theAge;
}
@end

// Usage
Person *person = [[Person alloc] init];
[person setName:@"John" age:25];

Method Components

  • + Class method (static)
  • - Instance method
  • (void) Return type
  • Colon required if there’s at least one argument
  • Data type must be stated for parameters
  • Each argument gets a name

Access Control

Properties

// Public property (in .h file)
@property (strong, nonatomic) NSString *firstName;

// Private property (in .m file, above @implementation)
@interface Person()
@property (strong, nonatomic) NSString *privateData;
@property (assign, nonatomic) BOOL isInitialized;
@end

Property Attributes

  • strong - Strong reference (default for objects)
  • weak - Weak reference (prevents retain cycles)
  • assign - Simple assignment (default for primitives)
  • copy - Makes a copy of the object
  • atomic - Thread-safe (default, but slower)
  • nonatomic - Not thread-safe (faster, commonly used)
  • readonly - Only getter is generated
  • readwrite - Both getter and setter generated (default)

Memory Management

Strong vs Weak References: The Dog Analogy

Strong Reference: Think of it like a dog on a leash. The dog wants to run away, but the strong reference is like the leash - as long as the pointer is strong, the dog (object) can’t run away (be deallocated).

Weak Reference: With a weak reference, the dog can run away. The object can be deallocated even if weak references still exist.

// Strong reference (default) - object stays alive
@property (strong, nonatomic) NSString *firstName;

// Weak reference - object can be deallocated
@property (weak, nonatomic) id<SomeDelegate> delegate;

// Copy - makes a copy of the object
@property (copy, nonatomic) NSString *immutableString;

When to use:

  • Strong: Use for most cases (default behavior)
  • Weak: Use for delegates and to prevent retain cycles
  • Copy: Use for NSString and other value objects

MVC (Model View Controller)

Core Architecture Pattern

  • Model - Data and business logic
  • View - User interface elements
  • Controller - Mediator between Model and View

Key MVC Principles

  • Controller interacts with both Model and View
  • Model and View should never communicate directly
  • Every view has a controller, but not every controller has a view
  • Some special controllers, called “controller of controllers” handle navigation

Interface Builder Connections

Connecting Views to Controllers

Connection process in Xcode:

  1. Ctrl+click and drag UI elements to code editor
  2. Choose connection type (IBOutlet or IBAction)

IBOutlet vs IBAction

// IBOutlet - allows code to reference UI elements
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UITextField *nameTextField;

// IBAction - handles user interactions (same as void)
-(IBAction)buttonTapped:(id)sender {
    self.nameLabel.text = self.nameTextField.text;
}

Key Differences:

  • IBOutlet: For displaying/reading UI elements (labels, text fields, etc.)
  • IBAction: For responding to user interactions (button taps, etc.)

Simulator Controls

Rotation and Settings

  • Command+Left or Command+Right rotates the simulator
  • Can disable rotation by unchecking “Use Autolayout” in File Inspector for .xib file
  • Apple Design Decision: Views won’t rotate when phone is upside down

Useful Simulator Shortcuts

  • Command+Shift+H - Home button
  • Command+K - Toggle software keyboard
  • Hardware > Shake Gesture - Simulate device shake

Collections

Overview

Objective-C collection types:

  • NSArray/NSMutableArray - Ordered list of objects
  • NSSet/NSMutableSet - Unordered collection of unique objects
  • NSDictionary/NSMutableDictionary - Key-value pairs

Important: Collections can only contain references to objects (not primitives directly).

NSArray (Immutable)

Must be completely populated at instantiation:

// Traditional syntax
NSArray *items = [[NSArray alloc] initWithObjects:@"ruby", @"c", @"c#", nil];

// Modern literal syntax (preferred)
NSArray *modernItems = @[@"swift", @"objective-c", @"javascript"];

// Accessing elements
NSString *firstItem = items[0]; // Modern syntax
NSString *firstItemOld = [items objectAtIndex:0]; // Traditional syntax

NSMutableArray

Can be modified after creation:

// Create empty mutable array
NSMutableArray *mutableItems = [[NSMutableArray alloc] init];

// Add objects
[mutableItems addObject:@"swift"];
[mutableItems insertObject:@"python" atIndex:0];

// Remove objects
[mutableItems removeObjectAtIndex:0];
[mutableItems removeObject:@"swift"];

Storing Primitives in Collections

Since collections only hold objects, wrap primitives in NSNumber:

// Storing numbers (traditional)
NSArray *numbers = @[[NSNumber numberWithInt:5], [NSNumber numberWithFloat:3.14]];

// Modern literal syntax for numbers
NSArray *modernNumbers = @[@5, @3.14, @YES];

// Retrieving values
int intValue = [numbers[0] intValue];
float floatValue = [numbers[1] floatValue];

NSDictionary

Key-value storage:

// Traditional syntax
NSDictionary *person = [[NSDictionary alloc] initWithObjectsAndKeys:
                        @"John", @"firstName",
                        @"Doe", @"lastName",
                        @25, @"age", nil];

// Modern literal syntax (preferred)
NSDictionary *modernPerson = @{
    @"firstName": @"John",
    @"lastName": @"Doe",
    @"age": @25
};

// Accessing values
NSString *firstName = modernPerson[@"firstName"];

UI Controls and Interface

Labels

  • Used for displaying text to users
  • The view is always controlled by the ViewController (the “file owner”)
  • Connected via IBOutlet for programmatic updates
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;

// Updating label text
self.statusLabel.text = @"Ready";
self.statusLabel.textColor = [UIColor redColor];

Buttons

  • Primary user interaction element
  • Touch Up Inside: Most common event - triggered when user touches and releases
-(IBAction)buttonPressed:(UIButton *)sender {
    sender.backgroundColor = [UIColor blueColor];
    self.statusLabel.text = @"Button was pressed!";
}

Text Fields

@property (weak, nonatomic) IBOutlet UITextField *nameField;

// Getting text input
NSString *userInput = self.nameField.text;

// Setting placeholder text
self.nameField.placeholder = @"Enter your name";

The 44-Point Touch Target Rule

44x44 points is the minimum recommended touch target size for interactive elements.

This ensures:

  • Comfortable tapping for all users
  • Accessibility compliance
  • Good user experience across different finger sizes
// Creating a properly-sized button programmatically
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(100, 100, 44, 44);
[button setTitle:@"Tap" forState:UIControlStateNormal];

Protocols and Delegates

Understanding Protocols

Protocols define a contract that classes can adopt:

// Protocol definition
@protocol PersonDelegate <NSObject>
@required
-(void)personDidChangeName:(Person *)person;

@optional
-(void)personDidChangeAge:(Person *)person;
@end

// Class adopting protocol
@interface PersonViewController : UIViewController <PersonDelegate>
@end

Delegate Pattern

// In the delegating class
@property (weak, nonatomic) id<PersonDelegate> delegate;

// Calling delegate methods
if ([self.delegate respondsToSelector:@selector(personDidChangeName:)]) {
    [self.delegate personDidChangeName:self];
}

Common Patterns and Best Practices

Initialization Patterns

// Custom initializer
-(instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
    self = [super init];
    if (self) {
        _firstName = [name copy];
        _age = age;
    }
    return self;
}

// Convenience constructor
+(instancetype)personWithName:(NSString *)name
{
    return [[self alloc] initWithName:name age:0];
}

Error Handling

NSError *error = nil;
BOOL success = [self doSomethingThatMightFail:&error];
if (!success) {
    NSLog(@"Error: %@", error.localizedDescription);
}

Key Concepts to Remember

  1. Message Passing: In Objective-C, you don’t “call methods” - you “send messages”
  2. Square Bracket Syntax: [object message] is the standard way to send messages
  3. Property Keywords: @property with appropriate attributes for memory management
  4. Two-File System: Always maintain both .h and .m files for custom classes
  5. NSObject Inheritance: All custom classes should inherit from NSObject
  6. MVC Pattern: Keep Model, View, and Controller responsibilities separate
  7. 44-Point Touch Targets: Minimum size for interactive elements
  8. Collections Hold Objects: Use NSNumber to wrap primitives for arrays
  9. Strong vs Weak: Understand memory management implications
  10. Protocols: Use for defining contracts and enabling loose coupling