Swift
Objective-C
Swift struct
iOS development
programming integration

How to use Swift struct in Objective-C

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Pure Swift structs are not directly visible to Objective-C because Objective-C interoperability is built around classes, protocols, and Objective-C-compatible runtime types. If you need Objective-C code to work with data defined in a Swift struct, the usual solution is to wrap that struct in an Objective-C-compatible Swift class or convert it into Foundation-friendly values.

Why Objective-C Cannot See the Struct Directly

Swift structs are value types and do not live in the Objective-C runtime the way NSObject subclasses do. That means you cannot simply mark a struct with @objc and import it into Objective-C the same way you would with a class.

So this does not work the way many people hope:

swift
1struct Point {
2    let x: Double
3    let y: Double
4}

Objective-C cannot import that struct as a normal Objective-C type from the generated Swift header.

Wrap the Struct in a Swift Class

The standard pattern is to keep the struct for Swift code and expose a wrapper class for Objective-C.

swift
1import Foundation
2
3struct Point {
4    let x: Double
5    let y: Double
6}
7
8@objcMembers
9final class PointBox: NSObject {
10    private let point: Point
11
12    init(x: Double, y: Double) {
13        self.point = Point(x: x, y: y)
14    }
15
16    var x: Double { point.x }
17    var y: Double { point.y }
18}

Because PointBox inherits from NSObject, Objective-C can see it through the generated ProjectName-Swift.h header.

Then in Objective-C:

objective-c
1#import "MyApp-Swift.h"
2
3PointBox *box = [[PointBox alloc] initWithX:10.0 y:20.0];
4NSLog(@"%f %f", box.x, box.y);

This is the most common bridge because it preserves the struct internally while giving Objective-C an object it understands.

Convert Struct Data to Foundation Types

If Objective-C only needs to read or write values, another option is to convert the struct into a dictionary, array, or string representation.

swift
1import Foundation
2
3struct UserInfo {
4    let name: String
5    let age: Int
6}
7
8@objcMembers
9final class UserInfoBridge: NSObject {
10    static func dictionary(from user: UserInfo) -> NSDictionary {
11        return [
12            "name": user.name,
13            "age": user.age
14        ]
15    }
16}

That approach is useful when the Objective-C side does not need rich Swift semantics and just needs portable data.

When a Class Is the Better Real Design

Sometimes the simplest answer is to stop fighting the language boundary and make the shared type a class from the start.

If the data type:

  • must be created and manipulated from both Swift and Objective-C
  • needs to cross the boundary frequently
  • depends on Objective-C frameworks heavily

then an NSObject subclass may be clearer than maintaining a struct plus wrapper layer.

Swift structs are excellent inside pure Swift modules, but once a type becomes a heavily shared interop model, class-based design may be the more pragmatic choice.

Common Pitfalls

The biggest pitfall is expecting @objc to make any Swift type automatically visible to Objective-C. It helps only for Objective-C-compatible declarations, and Swift structs are not one of them.

Another common mistake is exposing Swift-only features, such as generic fields or non-bridged types, through a wrapper that Objective-C still cannot understand. The wrapper class must expose Objective-C-friendly properties and methods.

Developers also sometimes forget the generated Swift header import. Even a correct wrapper class will not be visible to Objective-C files unless the project imports the generated ProjectName-Swift.h header where appropriate.

Summary

  • Swift structs are not directly exposed to Objective-C.
  • The usual solution is a Swift wrapper class that inherits from NSObject.
  • For simple interop, converting struct data to Foundation types can be enough.
  • If the type crosses the Swift and Objective-C boundary constantly, a class may be the cleaner shared model.
  • '@objc helps with Objective-C-compatible declarations, but it does not make pure Swift structs directly importable.'

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.