Objective-C
programming error
forward declaration
class property
debugging

Property cannot be found in forward class object

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

The Objective-C compiler error "Property 'X' cannot be found in forward class object 'Y'" occurs when you use @class to forward-declare a class but then try to access its properties without importing its header file. A forward declaration (@class ClassName;) tells the compiler a class exists but does not reveal its properties, methods, or protocol conformances. The fix is to #import the full header in the implementation file (.m) where you access properties, and use @class only in header files (.h) where you just need to reference the type.

The Error

objectivec
1// PersonViewController.h
2@class Person;  // Forward declaration — compiler knows Person is a class, nothing more
3
4@interface PersonViewController : UIViewController
5@property (nonatomic, strong) Person *person;
6@end
objectivec
1// PersonViewController.m
2#import "PersonViewController.h"
3// Missing: #import "Person.h"
4
5@implementation PersonViewController
6
7- (void)viewDidLoad {
8    [super viewDidLoad];
9    NSString *name = self.person.name;
10    // ERROR: Property 'name' cannot be found in forward class object 'Person'
11}
12
13@end

The compiler sees Person as a forward-declared class and does not know it has a name property.

The Fix: Import the Header

objectivec
1// PersonViewController.m
2#import "PersonViewController.h"
3#import "Person.h"  // <-- Add this import
4
5@implementation PersonViewController
6
7- (void)viewDidLoad {
8    [super viewDidLoad];
9    NSString *name = self.person.name;  // Works — compiler now knows Person's properties
10}
11
12@end

By importing Person.h in the implementation file, the compiler has access to the full class interface including properties and methods.

When to Use @class vs #import

objectivec
1// Person.h
2@interface Person : NSObject
3@property (nonatomic, copy) NSString *name;
4@property (nonatomic, assign) NSInteger age;
5- (NSString *)fullDescription;
6@end
objectivec
1// PersonViewController.h — USE @class
2@class Person;  // Only need to know Person is a type for the property declaration
3
4@interface PersonViewController : UIViewController
5@property (nonatomic, strong) Person *person;
6- (void)configurePerson:(Person *)aPerson;
7@end
objectivec
1// PersonViewController.m — USE #import
2#import "Person.h"  // Need full interface to access properties and methods
3
4@implementation PersonViewController
5
6- (void)configurePerson:(Person *)aPerson {
7    self.person = aPerson;
8    self.titleLabel.text = aPerson.name;       // Needs #import
9    self.detailLabel.text = [aPerson fullDescription];  // Needs #import
10}
11
12@end

Rule of thumb: Use @class in headers, #import in implementations.

Why @class Exists

Forward declarations solve circular dependency problems. Without @class, two classes that reference each other would create an import cycle:

objectivec
1// Without @class — circular import (compiler error)
2// Parent.h
3#import "Child.h"   // Child.h imports Parent.h → infinite loop
4
5@interface Parent : NSObject
6@property (nonatomic, strong) Child *child;
7@end
objectivec
1// With @class — no cycle
2// Parent.h
3@class Child;  // Just say "Child is a class" — no import needed
4
5@interface Parent : NSObject
6@property (nonatomic, strong) Child *child;
7@end
8
9// Parent.m
10#import "Parent.h"
11#import "Child.h"  // Import here where you actually use Child's properties
objectivec
1// Child.h
2@class Parent;  // Forward declare Parent
3
4@interface Child : NSObject
5@property (nonatomic, weak) Parent *parent;
6@end
7
8// Child.m
9#import "Child.h"
10#import "Parent.h"  // Import here

Protocols and Forward Declarations

The same issue occurs with protocols. Use @protocol for forward declaration:

objectivec
1// MyViewController.h
2@protocol DataSource;  // Forward declare the protocol
3
4@interface MyViewController : UIViewController
5@property (nonatomic, weak) id<DataSource> dataSource;
6// ERROR if DataSource protocol is not declared or imported
7@end
objectivec
1// MyViewController.m
2#import "DataSource.h"  // Import the protocol header
3
4@implementation MyViewController
5
6- (void)loadData {
7    NSArray *items = [self.dataSource fetchItems];  // Needs full protocol definition
8}
9
10@end

Categories and Extensions

Accessing properties defined in a class extension or category also requires importing the relevant header:

objectivec
1// Person+Internal.h (class extension in a separate header)
2@interface Person ()
3@property (nonatomic, copy) NSString *internalID;
4@end
objectivec
1// SomeClass.m
2#import "Person.h"
3// Missing: #import "Person+Internal.h"
4
5Person *p = [[Person alloc] init];
6p.internalID = @"abc";
7// ERROR: Property 'internalID' cannot be found in object of type 'Person *'
8// (Not a forward class error, but same root cause — missing header)

Common Pitfalls

  • Using @class in .m files instead of #import: Forward declarations in implementation files prevent access to properties and methods. Always #import in .m files where you interact with the class.
  • Importing headers in other headers unnecessarily: Importing full headers in .h files increases compile time and risks circular dependencies. Use @class in headers and #import in implementations.
  • Forgetting to import category headers: Properties and methods added in categories or class extensions are not visible without importing their specific headers, even if the base class header is imported.
  • Confusing #import with #include: #import is an Objective-C directive that prevents duplicate inclusion automatically. #include (from C) does not prevent duplicates and requires include guards. Always use #import in Objective-C.
  • Not importing the header for superclass properties: If class B inherits from class A, and you forward-declare A in B's header, accessing A's properties through a B instance in the .m file still requires importing A's header.

Summary

  • The error occurs because @class forward declarations do not expose properties, methods, or protocols
  • Use @class ClassName; in header files (.h) where you only need the type name
  • Use #import "ClassName.h" in implementation files (.m) where you access properties or call methods
  • Forward declarations exist to prevent circular import dependencies between headers
  • Always #import the full header of any class whose properties or methods you use in your implementation

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.