OC调Swift的问题记录

Swift调OC比较简单,之所以这么说,是因为Swift覆盖OC的大部分功能,即使有些没有覆盖,官方肯定也会给出解决方法。而OC相对于Swift而言,很多Swift特有的新功能OC是没有的,所以,OC可能在调用Swift的时候,会将Swift特有的功能引入OC,这个时候就会出错,因为,OC支持不了Swift的新功能。

OC调用Swift,需要先#import "工程名-swift.h"

1.如果Swift类没有继承自NSObject,那么OC不能调用,给类加上: NSObject。系统会给继承自NSObject的类,自动加上@objc修饰,除了private修饰的方法和属性。

2.不是继承自:NSObject的类,需要手动在方法或属性前加上@objc,Swift之后,即使是继承自:NSObject的类,也需要显式添加@objc才能访问。之前是默认添加的。

3.Swift中的枚举,OC中不能使用,OC中枚举实际都是Int型:

enum MethodType {
    case POST
    case GET
    case DELETE
}

改成:

@objc enum MethodType: Int {
    case POST
    case GET
    case DELETE
}

注意,要继承Int,加上@objc

5.在Swift中是结构体类型,但是在OC中是基本数据类型,所以,如果在Swift只是表示一个简单的基本数据类型的话,OC可以转换,如果表示的是一个结构体才有的功能,那么OC无法转换。

class ViewController: UIViewController {

    @objc var a: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

}

这里的变量a可以转换,查看一下工程名-Swift.h文件,的确生成了OC头文件:

SWIFT_CLASS("_TtC4TEST14ViewController")
@interface ViewController : UIViewController
@property (nonatomic, copy) NSString * _Nullable a;
- (void)viewDidLoad;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
@end

如果将这里的a类型改为Int会怎么样:

class ViewController: UIViewController {

    @objc var a: Int?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

}

会报错:Property cannot be marked @objc because its type cannot be represented in Objective-C

今天正在导致我发现这个问题的是下面的代码:

typealias TestClouse = (String,Int?) -> ()

class ViewController: UIViewController {

    
    @objc var clouse: TestClouse?
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

}

系统会报上面提到的错误,但是停在clouse变量这行。道理还是一样的。

这里就是上面解释的,当Int成为可选类型的时候,这里的Int已经不光是表示一个简单的Int类型了,而是带有明显的结构体属性,因为是可选,即表示,可能是nil,而OC里的Int类型或者NSInteger都是基本数据类型,不能为nil

所以,要解决这个问题,只能在Swift中避免将OC中的基本数据类型设置为可选类型。

附上系统转换的OC头文件代码:

@interface ViewController : UIViewController
@property (nonatomic, copy) void (^ _Nullable clouse)(NSString * _Nonnull, NSInteger);
- (void)viewDidLoad;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
@end

6.OC不支持Swift中的泛型,虽然从Xcode7,OC就引入了泛型的支持,但是这个泛型,我们称作轻量级泛型,和Swift中的重量级泛型还是对不上,当然,硬是要去对接,苹果应该也能做,但毕竟不是同一个东西,强行对接反而不好。
参考Stack Overflow上的讨论

目前遇到这几个问题,后面有新问题再更新

参考资料:swift: @objc的使用

你可能感兴趣的:(OC调Swift的问题记录)