swift&oc混编的一些限制整理

0、导入头文件。

oc类使用swift类,必须导入头文件appname-swift.h,该文件不可见,但可以点进去。swift调用oc类,必须在文件appNme-Bridging-Header.h中导入oc类的头文件。

1、swift类可以继承oc类,oc类不能继承swift类(即使该swift类的父类是oc类也不行)。

如,创建一个oc类OCObj
OCObj.h:

#import 
@class SubOfNSObj;
@class NotSubNSObj; //HB2-Swift.h里没有

@interface OCObj : NSObject

//@property (nonatomic, copy) NSString * _Nullable name;
@property (nonatomic, copy) NSString *name;

@property (nonatomic, copy) NSString * _Nullable name2;

@end

OCObj.m

#import "OCObj.h"

@implementation OCObj

@end

创建一个继承于NSObject的swift类:

class SubOfNSObj: NSObject {
    let name: String
    let age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

创建一个没有父类的swift类:

class NotSubNSObj {
    
    let name: String
    let age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    //swift可以使用oc的类
    func testOCObj() {
        let ocObj = OCObj()
        ocObj.name = "张三"
        
        let name1: String = ocObj.name
        let name2: String = ocObj.name2!
        print(name1)
        print(name2)
    }

}

创建一个继承于OCObj的swift类:

class SwiftTestClass: OCObj {
    //swift类可以继承oc类,oc不能继承swift类
}

如果强行创建一个oc类继承于swift类:

//swift类可以继承oc类,oc不能继承swift类。如果直接创建oc文件,可以选择swift类作为父类,但创建后会报错。
//@interface OCObjTestSubSwift : SubOfNSObj
////错误:Attempting to use the forward class ......
//@end

2、oc类在使用swift类时,该swift类必须继承于oc类。

如,在oc类ViewController中使用时:

- (void)test
{
    SubOfNSObj *obj1 = [[SubOfNSObj alloc] initWithName:@"lisi" age:4];
    NSLog(@"%@", obj1.name);
    //没有继承nsobject的swift类不能在oc中使用
//    NotSubNSObj *obj1 = [NotSubNSObj new];//use of undeclaerd identifier 'NotSubNSObj'
}

3、swift中没有宏,可以使用全局常量、全局函数代替部分宏。

swift中是不能使用宏定义语法,但是因为命名空间的缘故,在其中,我们将原本oc中不需要接受参数的宏,定义成let常量或枚举,将需要接受参数的宏定义成函数。
⚠️横屏后kScreenHeight及kScreenWidth是不会变化的,因为是常量,只会赋值一次。OC中则会实时变化,因为不是赋值,是宏替换。
⚠️ 这里定义的常量oc中并不能使用,可以定义一个类,然后将所有的全局变量和常量改成这个类的属性。
如oc中常用的几个宏:

 #define kIOS7   [UIDevice currentDevice].systemVersion.doubleValue>=7.0 ? 1 :0
 #define kIOS8   [UIDevice currentDevice].systemVersion.doubleValue>=8.0 ? 1 :0
 #define kScreenHeight     [UIScreen mainScreen].bounds.size.height
 #define kScreenWidth      [UIScreen mainScreen].bounds.size.width

在swift中定义为全局常量:

let kIOS7 = Double(UIDevice().systemVersion)! >= 7.0 ? 1 : 0
let kIOS8 = Double(UIDevice().systemVersion)! >= 8.0 ? 1 : 0
let kSCREEN_HEIGHT = UIScreen.main.bounds.height
let kSCREEN_WIDTH = UIScreen.main.bounds.width

定义成枚举、全局函数举例:

//MARK:时间格式:
enum TimeFormat: String {
    case common = "yyy-MM-dd HH:mm:ss"
    case yyMdHm = "yy-MM-dd HH:mm"
}
/MARK:沙盒路径
//Documnets目录
func pathForDocument() -> String {
    let ducumentPath = NSHomeDirectory() + "/Documents"
    return ducumentPath
}

使用:

let timeFormatStr = TimeFormat.yyMdHm.rawValue
let formatter = DateFormatter();
formatter.dateFormat = timeFormatSt
let timeStr = formatter.string(from: Date())
print(timeStr)

let path = pathForDocument()
print(path)

4、swift枚举类型在oc中使用

如果需要在oc类中使用时只能使用带@objc的枚举,带@objc的枚举必须时Int类型,否则会报错。

enum Direction {
    case Up
    case Down
    case Left
    case Right
}

enum Direction2: Int {
    case Up2
    case Down2
    case Left2
    case Right

@objc enum Direction3: Int {
    case Up3
    case Down3
    case Left3
    case Right3
}

以上三个枚举,只有Direction3能在oc类中使用, Direction、Direction2都不能在oc类中使用。

5、swift中使用oc的NS_OPTIONS类型枚举

swift中没有“|”,
如,下面写法是错误的

let options : NSStringDrawingOptions = .UsesLineFragmentOrigin | .UsesFontLeading

比较蹩脚的解决办法:
创建OC类,类中定义个方法,然后在swift的调用这个方法。
(注:swift中与NS_OPTIONS相似的是struck实现 OptionSet 协议。)

6、oc使用swift定义的协议

//如果要在oc中使用swift定义的协议,则需要加上@objc,且如果是不必实现的函数,函数前要加上 @objc optional。
如:

@objc protocol AlertViewProtocol {
    func didSelect(_ row: Int) //必须实现的协议
    @objc optional func onPickerCancel() //不必实现的协议
    @objc optional func showed()
}

7、其他swift中有而oc中没有的

1、元组:对于oc可能用到的:方法,返回不能是元组,参数能不能是元组。属性不能是元组。
2、范型(Generics)范型
3、Swift 中定义的结构体(Structures defined in Swift)不能在oc中使用,OC中必须继承nsobj
4、Swift 中定义的顶层函数(Top-level functions defined in Swift)
5、Swift 中定义的全局变量(Global variables defined in Swift)
6、Swift 中定义的类型别名(Typealiases defined in Swift)
7、Swift风格可变参数(Swift-style variadics)
8、嵌套类型(Nested types)
9、柯里化函数(Curried functions)

8、单例

swift创建单例比较方便、安全。
在swift写的模块中,Manager单例的代码如下

@objc public class Manager: NSObject {
    public static let shared = Manager()
}

但这样写在oc模块中不能获取单例.
可以添加一个供oc调用的函数

@objc public class Manager: NSObject {
    public static let shared = Manager()
    
    @objc public static func sharedInstance() -> Manager {
        return shared
    }
}

oc中使用

Manager *training = [Manager sharedInstance];

(如有错误欢迎斧正)

你可能感兴趣的:(swift&oc混编的一些限制整理)