29

I'm successfully mixing and matching Obj-C and Swift in an Xcode 7 project. However, I can't seem to figure out how, in an Objective C class, to inherit from a Swift class (and yes I know about declaring that Swift class as @objc for visibility). In this case the desired Swift superclass MySwiftViewController is a subclass of UIViewController. For now, in Obj-C, I'm inheriting directly from UIViewController and not gaining access to the capabilities I added in MySwiftViewController.

Here's what i understand:

-- To declare an Obj-C class as inheriting from something, that must be in the .h file after the ':':

#import <UIKit/UIKit.h>
@interface RootViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@end

-- To make Swift classes visible, that is #imported:

#import "MyProject-Swift.h"

However, you cannot import the Swift auto-generated bridging header into the Obj-C .h file. You also cannot forward-declare an opaque superclass with @class. So, is this possible and how?

3 Answers 3

64

Unfortunately, it's not possible to subclass a Swift class in Objective-C. Straight from the docs:

You cannot subclass a Swift class in Objective-C.

See Apple's guide on interoperability for more details on what you can and cannot access with Objective-C.

1
3

As for Xcode 8.0 and earlier there is dirty-hacky solution, that probably will be fixed in the future.

If you want to subclass from swift file, you can add objc_subclassing_restricted attribute. You can make it as macro for convenience. Code:

Swift class.

import Foundation

class SwiftClass : NSObject {
  func say() {
    print("hi");
  }
}

Objc class:

#import <Foundation/Foundation.h>

#import "test-Swift.h"

#define SWIFT_SUBCLASS __attribute__((objc_subclassing_restricted))

SWIFT_SUBCLASS
@interface ObjcClass : SwiftClass
- (instancetype)init;
@end
@implementation ObjcClass
- (void)say {
  NSLog(@"oops");
}
@end

But, as I understand, it is not supported, and you may have any sort of bugs because of it. So it is not guide to action, and more like curious thing to know.

3
  • I can confirm that this workaround compiles successfully on Xcode 8.1 but the class is not there, so the build fails in linker phase. Commented Nov 25, 2016 at 10:46
  • Can you provide more specific example? I just build and run above code on Xcode 8.2.1. It works well, and even more [[ObjcClass alloc] init] say] prints out "oops" without any error. Commented Jan 13, 2017 at 13:26
  • Not working for me on Xcode 8.3.2. Get the "cannot subclass" error on the @implementation line (without the attribute, I already get it on the @interface line)
    – ernesto
    Commented May 24, 2017 at 12:57
-1

In fact, it can be achieved by category:

Swift code

import UIKit

@objc open class TestModel: NSObject {
    @objc var testName: String = String()
}

Objective C .h file code

#import <Foundation/Foundation.h>

#import "Test-Swift.h"


@interface TestModel (Add)
- (void)configTestName;
@end

Objective C .m file code

#import "TestModel+Add.h"

@implementation TestModel (Add)

- (void)configTestName {
    self.testName = @"12323";
}

@end

Not the answer you're looking for? Browse other questions tagged or ask your own question.