28
votes

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

3 Answers

58
votes

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.

3
votes

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.

-2
votes

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