I have several simple structs
written in swift inside .swift files.
These structs
are very simple and contain almost only Strings:
struct Letter {
struct A {
static let aSome : String = "descASome"
static let aSomeMore : String = "descASomeMore"
}
struct B {
static let bNow : String = "descBNow"
static let bLater : String = "descBLater"
}
...
}
I want to use those structs inside a project which contains Objective-C code because I'm writing a cross platform framework.
I have read: ObjectiveC - Swift interoperability by Apple which clearly states that Swift written structs can't be used by ObjectiveC. Excluded are (among other features):
Structures defined in Swift
Solution 1:
I have found a SO solution which solves the issue by using classes:
@objc class Letter : NSObject {
@objc class A : NSObject {
static let aSome : String = "descASome"
static let aSomeMore : String = "descASomeMore"
}
@objc class B : NSObject {
static let bNow : String = "descBNow"
static let bLater : String = "descBLater"
}
...
}
This solution works, however I have to rewrite all the structs to classes. They are also not lightweight like structs (among other things). Besides I feel like I am going backwards to solve the problem.
Q1. Is there any other way to use Swift structs inside ObjectiveC beside solution 1 which doesn't fit well for my project/situation? (enums can be used if their rawValue is Int)
Q2. Is there a way to use #define SomeConst for ObjectiveC access and stucts for Swift access like :
#if macOS // if Swift?
#endif
Swift Struct is not available in Objective-C. Enum only Int types are available in Objective-C. Swift functions with default parameter values are available in Objective-C but you will have to give values to each parameter.
You can use regular C structs all you want. Your example tries to put references to an Objective-C object, NSString , into a struct , which is incompatible with ARC. Structs are typically used for simple data structures. Examples that you are likely to come across in Objective-C code are CGPoint and CGRect .
To access and use swift classes or libraries in objective-c files start with an objective-c project that already contains some files. Add a new Swift file to the project. In the menu select File>New>File… then select Swift File, instead of Cocoa Touch Class. Name the file and hit create.
First, there is an element of performance: structs are simpler and faster than classes. I say an element of performance because lots of people think this is the primary reason SwiftUI uses structs, when really it's just one part of the bigger picture.
As of now, NO. You will need Classes to store model objects.
@objcMembers public class Car: NSObject {
public var mileage: NSNumber?
}
@objcMember virtually converts them to Objective-c readable format and can be accessed from Objective-C classes. This will make your code interoperable.
Note: Make sure the class type is NSObject.
You can't do this without doing some rewriting: Swift structs are simply not visible from ObjC.
You need to write an ObjC-visible Swift class to expose the values, sort of the inverse of Swift Foundation's "overlay" types.
One option is to follow the structure of the Swift code as closely as possible. Note that nested classes are disallowed, and that the ObjC "overlay" must have a different name than the Swift struct. This is unfortunate but impossible to work around, since this Swift code is visible in the same places that the original struct is.
import Foundation
@objc class OCLetters : NSObject {
static let A = _A.self
static let B = _B.self
}
@objc class _A : NSObject {
static let some = Letters.A.some
static let someMore = Letters.A.someMore
}
@objc class _B : NSObject {
static let now = Letters.B.now
static let later = Letters.B.later
}
If you want to use dot notation for the values in your ObjC code, however, this won't work. This is probably a bug, but the .some
in OCLetters.A.some
is treated as a struct member reference, which fails. (Changing the properties to computed class properties doesn't work either.) You must write [[OCLetters A] some]
(or [OCLetters.A some]
).
To be able to use dot notation, you'll have to change the structure slightly so that the properties are actually instances:
import Foundation
@objc class OCLetters : NSObject {
static let A = _A()
static let B = _B()
}
@objc class _A : NSObject {
let some = Letters.A.some
let someMore = Letters.A.someMore
}
@objc class _B : NSObject {
let now = Letters.B.now
let later = Letters.B.later
}
Also note that you unfortunately can't restrict the visibility in ObjC of the helper _A
and _B
classes, because if they are not visible, neither will OCLetters
's properties be.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With