Objective-C
Swift
code interoperability
class extensions
programming languages

Can Objective-C code call Swift class extensions?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Yes, Objective-C can call methods defined in Swift extensions, but only when those methods are exposed to the Objective-C runtime. Interoperability depends on inheritance, visibility, and @objc compatibility. If any requirement is missed, the method will not appear in the generated Swift header and Objective-C code cannot call it.

Minimum Interoperability Setup

Start with a Swift class that inherits from NSObject. Methods that should be visible to Objective-C need Objective-C-compatible signatures.

swift
1import Foundation
2
3@objcMembers
4class PaymentManager: NSObject {
5    func start() {
6        print("Payment flow started")
7    }
8}
9
10extension PaymentManager {
11    @objc func stopWithReason(_ reason: String) {
12        print("Stopped: \(reason)")
13    }
14}

@objcMembers marks compatible members for Objective-C exposure. You can still use explicit @objc on extension methods when you want tighter control.

Call Swift Extension Methods From Objective-C

In Objective-C source, import the generated header and call methods normally.

objective-c
1#import "YourModuleName-Swift.h"
2
3void runPaymentFlow(void) {
4    PaymentManager *manager = [PaymentManager new];
5    [manager start];
6    [manager stopWithReason:@"user cancelled"];
7}

If stopWithReason is not found, check whether it appears in YourModuleName-Swift.h first. Missing there means Swift exposure failed before Objective-C compilation even begins.

Common Reasons Methods Do Not Appear

Several Swift features are not bridgeable to Objective-C.

  • Generic methods are usually not Objective-C visible.
  • Swift structs and enums without Objective-C bridges are not valid parameter types.
  • Methods with Swift-only types may compile in Swift but disappear from Objective-C.

Use Objective-C friendly types such as NSString, NSNumber, NSArray, and NSDictionary bridges where needed.

swift
1extension PaymentManager {
2    @objc func configure(with options: [String: String]) {
3        print(options)
4    }
5}

The dictionary above bridges to NSDictionary and is callable from Objective-C.

Extension Limits to Remember

Swift extensions cannot add stored properties. If Objective-C code expects property-backed state, define stored properties in the main class declaration. Use computed properties in extensions only when they can derive from existing state.

swift
1extension PaymentManager {
2    @objc var statusText: String {
3        return "ready"
4    }
5}

This is valid because it is computed, not stored.

Access Control and Module Boundaries

For app targets, internal is typically enough. For framework targets consumed by another module, exposed APIs usually need public access and Objective-C annotations.

swift
1import Foundation
2
3@objcMembers
4public class SDKBridge: NSObject {
5    public func ping() {
6        print("pong")
7    }
8}

When testing framework interoperability, always build the framework and inspect its generated interface.

Debugging the Generated Header

When interoperability fails, inspect the generated Swift interface directly. In Xcode build products, find YourModuleName-Swift.h and confirm whether the method is present. If it is missing, fix Swift exposure first.

Checklist that usually resolves missing symbols:

  • Ensure the Swift declaration has Objective-C compatible types.
  • Ensure visibility is correct for the target boundary.
  • Ensure the target has Defines Module enabled when needed.
  • Ensure Objective-C files import the correct module header name.
swift
1@objcMembers
2class BridgeExample: NSObject {
3    @objc func performAction(_ value: NSString) {
4        print(value)
5    }
6}
objective-c
1#import "YourModuleName-Swift.h"
2
3BridgeExample *bridge = [BridgeExample new];
4[bridge performAction:@"ok"];

This small verification loop saves a lot of time when mixed-language targets become complex.

Common Pitfalls

A frequent pitfall is forgetting NSObject inheritance. Without Objective-C runtime compatibility, methods may not bridge as expected. Another issue is relying on @objcMembers alone while using Swift-only parameter types, which still prevents exposure. Teams also often debug in the wrong place by looking only at compiler errors in Objective-C files. The fastest check is opening the generated Swift header to confirm what is exported. Finally, extension methods that are not marked for Objective-C visibility can silently remain Swift-only even though the class itself is bridgeable.

Summary

  • Objective-C can call Swift extension methods when they are Objective-C visible.
  • Use NSObject inheritance and Objective-C compatible method signatures.
  • Import the generated Swift header and verify exported symbols there first.
  • Avoid Swift-only features in APIs that must be called from Objective-C.
  • Keep stored state in the main class, not in extensions.

Course illustration
Course illustration

All Rights Reserved.