Objective-C

#21
TIOBE#34
PYPL#10
GitHub#21
RedMonk#17
IEEESpectrum#27
JetBrains#20
programming languageobject-orientediOS developmentmacOS developmentApplesystem development

Programming Language

Objective-C

Overview

Objective-C is a programming language that adds Smalltalk-style object-oriented features to the C language.

Details

Objective-C is a programming language developed by Brad Cox in the early 1980s, combining C language with Smalltalk's message-passing approach to create an object-oriented language. It was adopted by Apple as the primary development language for NeXTSTEP, and later for macOS and iOS, serving as the standard development language for Apple platforms for many years. While Swift has largely replaced it as Apple's preferred language, Objective-C remains important due to the vast existing codebase and libraries built with it, playing a crucial role in legacy system maintenance and compatibility with existing projects.

Code Examples

Hello World

// Basic output
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"Hello, World!");
        
        // Output using variables
        NSString *message = @"Hello, Objective-C!";
        NSLog(@"%@", message);
        
        // Output using format strings
        NSString *name = @"John";
        NSInteger age = 25;
        NSLog(@"My name is %@ and I am %ld years old.", name, (long)age);
    }
    return 0;
}

Variables and Data Types

// Primitive types
NSInteger intValue = 42;
NSUInteger unsignedValue = 100;
CGFloat floatValue = 3.14f;
BOOL boolValue = YES;

// Object types
NSString *text = @"string";
NSNumber *numberObject = @(42);
NSArray *array = @[@"element1", @"element2", @"element3"];
NSDictionary *dictionary = @{
    @"key1": @"value1",
    @"key2": @"value2"
};

// Mutable objects
NSMutableString *mutableText = [NSMutableString stringWithString:@"initial"];
[mutableText appendString:@" appended"];

NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"A", @"B", nil];
[mutableArray addObject:@"C"];

NSLog(@"Integer: %ld", (long)intValue);
NSLog(@"String: %@", text);
NSLog(@"Array count: %lu", (unsigned long)[array count]);

Conditional Statements

// Basic if statement
NSInteger score = 85;
NSString *grade;

if (score >= 90) {
    grade = @"A";
} else if (score >= 80) {
    grade = @"B";
} else if (score >= 70) {
    grade = @"C";
} else {
    grade = @"D";
}

NSLog(@"Score: %ld, Grade: %@", (long)score, grade);

// Boolean conditions
NSInteger age = 20;
BOOL hasLicense = YES;

if (age >= 18 && hasLicense) {
    NSLog(@"You can drive");
} else if (age >= 18) {
    NSLog(@"Please get a license");
} else {
    NSLog(@"Please get a license after turning 18");
}

// Switch statement
typedef NS_ENUM(NSInteger, DayOfWeek) {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

DayOfWeek today = Wednesday;
switch (today) {
    case Monday:
    case Tuesday:
    case Wednesday:
    case Thursday:
    case Friday:
        NSLog(@"It's a weekday");
        break;
    case Saturday:
    case Sunday:
        NSLog(@"It's weekend");
        break;
}

Arrays and Dictionaries

// Array operations
NSArray *fruits = @[@"apple", @"banana", @"orange"];
NSLog(@"First fruit: %@", [fruits firstObject]);
NSLog(@"Fruit count: %lu", (unsigned long)[fruits count]);

// Processing array elements
for (NSString *fruit in fruits) {
    NSLog(@"Fruit: %@", fruit);
}

// Index-based processing
for (NSUInteger i = 0; i < [fruits count]; i++) {
    NSLog(@"Index %lu: %@", (unsigned long)i, fruits[i]);
}

// Mutable array
NSMutableArray *mutableFruits = [NSMutableArray arrayWithArray:fruits];
[mutableFruits addObject:@"grape"];
[mutableFruits insertObject:@"strawberry" atIndex:1];

// Dictionary operations
NSDictionary *person = @{
    @"name": @"John Doe",
    @"age": @30,
    @"city": @"Tokyo"
};

NSLog(@"Name: %@", person[@"name"]);
NSLog(@"Age: %@", person[@"age"]);

// Processing dictionary keys and values
for (NSString *key in person) {
    NSLog(@"%@: %@", key, person[key]);
}

// Mutable dictionary
NSMutableDictionary *mutablePerson = [NSMutableDictionary dictionaryWithDictionary:person];
mutablePerson[@"job"] = @"Engineer";

Loops and Iteration

// for-in loop
NSArray *numbers = @[@1, @2, @3, @4, @5];
for (NSNumber *number in numbers) {
    NSInteger value = [number integerValue];
    NSLog(@"Number: %ld, Double: %ld", (long)value, (long)(value * 2));
}

// Traditional for loop
for (NSInteger i = 1; i <= 5; i++) {
    NSLog(@"Square of %ld is %ld", (long)i, (long)(i * i));
}

// while loop
NSInteger count = 0;
while (count < 5) {
    NSLog(@"Count: %ld", (long)count);
    count++;
}

// do-while loop
NSInteger counter = 0;
do {
    NSLog(@"Execution count: %ld", (long)(counter + 1));
    counter++;
} while (counter < 3);

Class Definition and Usage

// Header file (.h)
@interface Car : NSObject

@property (nonatomic, strong) NSString *make;
@property (nonatomic, strong) NSString *model;
@property (nonatomic, assign) NSInteger year;
@property (nonatomic, assign) NSInteger mileage;

- (instancetype)initWithMake:(NSString *)make model:(NSString *)model year:(NSInteger)year;
- (void)driveDistance:(NSInteger)distance;
- (NSString *)getInfo;

@end

// Implementation file (.m)
@implementation Car

- (instancetype)initWithMake:(NSString *)make model:(NSString *)model year:(NSInteger)year {
    self = [super init];
    if (self) {
        _make = make;
        _model = model;
        _year = year;
        _mileage = 0;
    }
    return self;
}

- (void)driveDistance:(NSInteger)distance {
    self.mileage += distance;
    NSLog(@"Drove %ldkm. Total mileage: %ldkm", (long)distance, (long)self.mileage);
}

- (NSString *)getInfo {
    return [NSString stringWithFormat:@"%ld %@ %@", (long)self.year, self.make, self.model];
}

@end

// Usage example
Car *myCar = [[Car alloc] initWithMake:@"Toyota" model:@"Prius" year:2022];
NSLog(@"%@", [myCar getInfo]);
[myCar driveDistance:50];
[myCar driveDistance:30];

Protocols (Interfaces)

// Protocol definition
@protocol Drawable <NSObject>
@required
- (void)draw;
- (CGSize)getSize;

@optional
- (void)setColor:(UIColor *)color;
@end

// Class implementing protocol
@interface Circle : NSObject <Drawable>
@property (nonatomic, assign) CGFloat radius;
@end

@implementation Circle

- (void)draw {
    NSLog(@"Drawing circle with radius %.2f", self.radius);
}

- (CGSize)getSize {
    CGFloat diameter = self.radius * 2;
    return CGSizeMake(diameter, diameter);
}

- (void)setColor:(UIColor *)color {
    NSLog(@"Setting circle color");
}

@end

Categories (Extending Existing Classes)

// NSString category definition
@interface NSString (Utilities)
- (BOOL)isValidEmail;
- (NSString *)reverseString;
@end

@implementation NSString (Utilities)

- (BOOL)isValidEmail {
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:self];
}

- (NSString *)reverseString {
    NSMutableString *reversedString = [NSMutableString string];
    for (NSInteger i = [self length] - 1; i >= 0; i--) {
        [reversedString appendString:[NSString stringWithFormat:@"%C", [self characterAtIndex:i]]];
    }
    return reversedString;
}

@end

// Usage example
NSString *email = @"[email protected]";
NSLog(@"Valid email: %@", [email isValidEmail] ? @"YES" : @"NO");

NSString *text = @"Hello";
NSLog(@"Reversed: %@", [text reverseString]);

Special Features

Memory Management (ARC and Manual)

// With ARC (Automatic Reference Counting)
@property (nonatomic, strong) NSString *strongProperty;  // Strong reference
@property (nonatomic, weak) id<SomeDelegate> weakProperty;  // Weak reference
@property (nonatomic, copy) NSString *copyProperty;  // Copy property

// Blocks (closures)
typedef void (^CompletionBlock)(BOOL success, NSError *error);

- (void)performTaskWithCompletion:(CompletionBlock)completion {
    // Asynchronous processing
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Some processing
        BOOL success = YES;
        NSError *error = nil;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (completion) {
                completion(success, error);
            }
        });
    });
}

KVO (Key-Value Observing)

// Register observer
[self addObserver:self 
       forKeyPath:@"someProperty" 
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 
          context:nil];

// Receive change notifications
- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change 
                       context:(void *)context {
    if ([keyPath isEqualToString:@"someProperty"]) {
        NSLog(@"Property changed: %@ -> %@", 
              change[NSKeyValueChangeOldKey], 
              change[NSKeyValueChangeNewKey]);
    }
}

// Remove observer (important)
- (void)dealloc {
    [self removeObserver:self forKeyPath:@"someProperty"];
}

Versions

Version Status Key Features Release Year
Objective-C 2.0 Current Properties, Garbage Collection 2007
Objective-C 1.0 Legacy Basic object-oriented features 1988

Reference Pages

Official Documentation

Learning Resources

Development Tools

  • Xcode - Apple's official IDE
  • CocoaPods - Dependency management tool
  • Carthage - Lightweight dependency management tool