Objective-C
iOS development
data types
iOS programming
Objective-C types

Types in Objective-C on iOS

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Objective-C on iOS mixes C types, Objective-C object types, and Apple framework-specific aliases. That combination is powerful, but it also confuses newcomers because similar-looking types serve very different purposes. The most useful mental model is to separate primitive values, object references, and Cocoa convenience types such as NSInteger and CGFloat.

Primitive C Types Still Matter

Objective-C inherits its primitive types directly from C. These are value types, not objects.

objective-c
1#import <Foundation/Foundation.h>
2
3int main(int argc, const char * argv[]) {
4    @autoreleasepool {
5        int count = 42;
6        double price = 19.99;
7        char initial = 'A';
8        BOOL enabled = YES;
9
10        NSLog(@"count=%d price=%.2f initial=%c enabled=%@", count, price, initial, enabled ? @"YES" : @"NO");
11    }
12    return 0;
13}

These types are fast and compact, but they do not support Objective-C messaging because they are not objects.

On iOS, BOOL is the usual boolean type, with YES and NO rather than C99 true and false in most Objective-C codebases.

Object Types Are Pointers

Objective-C objects are referenced by pointers. NSString *, NSArray *, and NSObject * all point to heap-allocated objects.

objective-c
1#import <Foundation/Foundation.h>
2
3int main(int argc, const char * argv[]) {
4    @autoreleasepool {
5        NSString *name = @"Taylor";
6        NSArray<NSString *> *roles = @[@"admin", @"editor"];
7
8        NSLog(@"%@ %@", name, roles);
9    }
10    return 0;
11}

The * matters. It tells you the variable stores a reference, not the object contents inline.

This is also why nil is valid for object references but not for primitive values like int or double.

Prefer Cocoa Aliases for Platform-Aware Numeric Types

Apple frameworks use types such as NSInteger, NSUInteger, and CGFloat because their size maps cleanly to the platform architecture.

objective-c
NSInteger itemCount = 10;
NSUInteger index = 2;
CGFloat width = 120.5;

Why use them instead of plain int or float?

  • 'NSInteger and NSUInteger match the natural integer width of the platform'
  • 'CGFloat matches the floating-point type expected by UIKit and Core Graphics'
  • framework APIs already use these types, so matching them reduces conversion noise

For UIKit geometry, you will see structs built from these aliases:

objective-c
CGRect frame = CGRectMake(0, 0, 100, 44);
CGPoint center = CGPointMake(50, 22);
CGSize size = CGSizeMake(100, 44);

These are structs, not objects, which is why they are passed by value.

Understand id, instancetype, and Class

Three Objective-C types come up often in APIs:

  • 'id means "an object of some unknown Objective-C type"'
  • 'instancetype means "the concrete type returned by this initializer or factory"'
  • 'Class means "an Objective-C class object"'

Example:

objective-c
1- (instancetype)initWithTitle:(NSString *)title {
2    self = [super init];
3    if (self) {
4        _title = [title copy];
5    }
6    return self;
7}

instancetype is better than id for initializers because the compiler can preserve the specific return type for subclasses.

Use id when you genuinely want dynamic typing, not as a shortcut to avoid thinking about types.

Box Primitive Values When Collections Need Objects

Objective-C collections such as NSArray and NSDictionary store objects, not primitive values directly. When you need to put an int or BOOL into a collection, use NSNumber.

objective-c
1NSNumber *age = @(34);
2NSNumber *isAdmin = @(YES);
3
4NSArray *values = @[age, isAdmin];
5NSLog(@"%@", values);

This boxing behavior is common in Cocoa APIs. The same idea applies to wrapping structs with NSValue when necessary.

Nullability and Modern Objective-C

Modern Objective-C code often annotates pointers with nullability:

objective-c
- (nullable NSString *)displayNameForUserId:(nonnull NSString *)userId;

These annotations improve Swift interoperability and make intent clearer in mixed-language iOS apps. They are especially important in public headers and framework code.

Common Pitfalls

  • Treating primitive C values and Objective-C object references as if they behaved the same way.
  • Using plain int everywhere instead of framework-friendly aliases such as NSInteger.
  • Returning id from initializers where instancetype is the correct type.
  • Forgetting that collections store objects, not raw primitive values.
  • Ignoring nullability annotations in code that interoperates with Swift.

Summary

  • Objective-C uses both C primitive types and Objective-C object pointer types.
  • Framework aliases such as NSInteger and CGFloat are preferred for iOS APIs.
  • 'id, instancetype, and Class have distinct roles and should not be used interchangeably.'
  • Collections require object values, so primitives are boxed with NSNumber or NSValue.
  • Nullability annotations make modern Objective-C clearer and much safer in mixed Swift projects.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.