混编扫盲

一. 在同一个app或者Unit Test混编

我们先建两个文件, 一个oc, 一个swift

@interface FirstOC : NSObject
- (void)logOC;
@end

@implementation FirstOC
- (void)logOC {
    NSLog(@"%@", _cmd);
}
@end
class FirstSwift : NSObject {
    @objc func logSwift() {
        print(#function)
    }
}

1.1 oc调用swift

我们需要在oc文件里面这样使用, 导入#import "hybirdTest-Swift.h"就能使用使用swift这个类了。 其中hybirdTest是项目名称,-Swift.h是固定后缀。

#import "hybirdTest-Swift.h"
1.1.1 为啥呢?

打开看看, 搜索FirstSwift,发现xcode将swift代码导出为oc的方法声明,这样就能编译通过了。

图片.png

1.2 swift调用oc

我们需要在hybirdTest-Bridging-Header中导入swift类需要用到的OC类, 这样就可以做到swift调用oc了。

图片.png
1.2.1 为啥呢?

具体实现不详, 猜测是找到SWIFT_OBJC_BRIDGING_HEADER这个环境变量,然后将其中的OC代码导出为swift的声明

图片.png

二. 不同组件或者同一组件之间的混编

早些时候都是主工程和组件都是OC代码的时候, 我们要使用组件代码,只需要`#import<A/A.h>即可。
但是后来swift的比重越来越大, 怎么引用组件中swift的代码就成了一个问题。

2.1 头文件的各种导入方式

  • #include:C/C++导入头文件的关键字, 原理是简单粗暴的将要导入的文件代码复制到当前文件,会导致重复导入,效率低下
  • #import:OC的头文件导入方式,它能保证同一个头文件不会被重复包含
  • @class: 告诉编译期我有这个类,先别急着报错,我会在稍后的文件里#import具体的类实现的,可以解决头文件的相互包含的问题
  • @import: OC中用来导入模块的方式
  • import: swift中用来导入模块的方式

2.2 search paths

  • Header search paths:和下面的差不多,如果编译器不支持user headers概念,会从header search paths中去寻找
  • user header search paths:和上面差不多
  • use header maps:生成hmap文件,记录了头文件名称及其对应的磁盘位置
  • 上面3个一般配合使用

  • Enable Modules: 允许使用模块,也就是可以使用@import和import

2.3 组件A引用混编的组件B失败

在A的podspec中添加以下代码

    search_paths = ["\"${PODS_ROOT}/Headers/Public/ZZUI\"",
                    "\"${PODS_ROOT}/Headers/Private/ZZUI\"",
                    ]
    ss.pod_target_xcconfig = {
      'HEADER_SEARCH_PATHS' => search_paths.join(' '),
      'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES'
    }

对比下xcconfig, 发现HEADER_SEARCH_PATHS多了ZZUI,这样就能找到了。

//加了代码
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ModuleSearchFilter" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SQLiteRepairKit" "${PODS_ROOT}/Headers/Public/WCDB" "${PODS_ROOT}/Headers/Public/WCDBOptimizedSQLCipher" "${PODS_ROOT}/Headers/Public/ZZUI" "${PODS_ROOT}/Headers/Private/ZZUI"

//没加代码
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ModuleSearchFilter" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SQLiteRepairKit" "${PODS_ROOT}/Headers/Public/WCDB" "${PODS_ROOT}/Headers/Public/WCDBOptimizedSQLCipher"

2.4 SWIFT_INCLUDE_PATHS

需要注意的点:

引用组件文件的时候,尽量不要使用import"", 这样会导致开启module的时候报错

参考:

综合篇
clang官网中的module实现
oc swift的api交互
详解
错误排查
实战一下

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容