Let's say I define a generic class in Swift, similar to the following:
class MyArray<T> {
func addObject(object: T) {
// do something... hopefully
}
}
(I know there is a slightly better implementation of array, this is merely an example.)
In Swift I can now use this class very easily:
let a = MyArray<String>()
a.addObject("abc")
With Xcode 7, we now have generics in Objective-C, so I would assume that I could use this class in Objective-C:
MyArray<NSString*> *a = [[MyArray<NSString*> alloc] init];
[a addObject:@"abc"];
However, MyArray is never added to my Project-Swift.h
file. Even if I change it to inherit from NSObject, it still doesn't appear in my Swift.h file.
Is there any way to create a generic Swift class and then use it in Objective-C?
Update: If I try to inherit from NSObject and annotate with @objc:
@objc(MyArray)
class MyArray<T>: NSObject {
func addObject(object: T) {
// do something... hopefully
}
}
I get the following compiler error:
Generic subclasses of '@objc' classes cannot have an explicit '@objc' attribute because they are not directly visible from Objective-C.
Does this mean there is no way to use a generic Swift class in Objective-C?
How does one indirectly reference the class?
You can work with types declared in Swift from within the Objective-C code in your project by importing an Xcode-generated header file. This file is an Objective-C header that declares the Swift interfaces in your target, and you can think of it as an umbrella header for your Swift code.
Objective-C supports lightweight Generics since 2015, with the Xcode 7.
Swift classes that are inherited from OBJC classes are bridged automatically. That means any class inherited from, for example, UIViewController is automatically seen in the OBJC runtime. If you're creating a class that doesn't inherit from anything, then make it an NSObject subclass, as you would in OBJC.
Swift generic types cannot be used in Objective-C.
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-ID136
This excludes Swift-only features such as those listed here:
- Generics
- ...
There is a workaround for some situations, when you need to import Swift generic class into Objective-C.
Let's say you have Swift REST service, which uses Generics. I'm using Moya
framework and that's how my service looks like:
class AuthService: BaseService<AuthAPI> {
func register(email: String) {
// ...
}
}
It's inherited from base service using generics, so I can not use it directly in my Objective-C code.
So here is a workaround:
Lets create AuthServiceProtocol
:
@objc protocol AuthServiceProtocol {
func register(email: String)
}
Then let's create a factory for service (or a singleton method, no difference):
@objc class Services: NSObject {
static let authService: AuthServiceProtocol = AuthService()
}
Then I'm able to call my generic Swift auth service from Objective-C code:
- (void)someObjcMethod {
[Services.authService registerWithEmail:self.email];
}
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