当前位置: 首页 > 科技观察

Swift和Objective-C混合Framework的优雅开发

时间:2023-03-13 05:56:17 科技观察

前言为什么要写这样一篇文章,因为昨天跟朋友讨论了如何混合Swift和Objective-C开发Framework,发现中间有很多有趣的坑。用Swift封装OC库是比较常见的事情。毕竟对于大多数公司来说,旧的代码都是用OC写的,而且经过多次迭代,这些OC代码已经被验证是稳定的。在Swift中重写太昂贵了。这就引入一个需求:用Swift和OC混合一个Framework。如果你之前没有用过Swift和ObjectiveC混合开发,建议你看看这篇文档:SwiftandObjective-CintheSameProjecthttps://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html按照文档一步步创建一个单页项目,然后新建一个Target,选择CocoaTouchFramework。然后,分别新建一个Swift文件和ObjectiveC类,注意TargetMemberShip选择了Framework。类的内容如下:OCSource.h#import@interfaceOCSource:NSObject-(void)functionFromOC;@endOCSource.m#import"OCSource.h"@implementationOCSource-(void)functionFromOC{NSLog(@"%@",@"Logfromobjectivecinframework");}@endSwift调用OC创建一个新的SwiftSource.swiftopenclassSwiftIt{publicinit(){}letocObject=OCSource()publicfuncencapsulate(){ocObject.functionFromOC()}}然后,根据文档,为了让Swift文件访问ObjectiveC文件,我们应该在伞形标头中公开所需的标头,即MixFramework.h。也就是MixFramework.h,#import然后,放心点击build。咚~~~,编译失败。原因:OCSource.h默认是用Project权限编译的。为了在伞头中使用它,你需要将这个文件的权限更改为Public,然后将它拖过来,如图所示。好了,现在build,可以看到build成功了。OC调用Swift。在SwiftSource.swift中,添加一个类,openclassClassForOC:NSObject{publicstaticlettextForOC="textForOC"}然后,为了调用OC中的Swift方法,我们需要导入头文件。此时OCSource.m文件内容如下#import"OCSource.h"#import@implementationOCSource-(void)functionFromOC{NSLog(@"%@",[ClassForOCtextForOC]);}@end然后,build,发现成功,很开心。外部调用在ViewController.swift中,我们调用了Framework中的内容。importMixFrameworkclassViewController:UIViewController{vart=SwiftIt()overridefuncviewDidLoad(){super.viewDidLoad()t.encapsulate()//加载view后做任何额外的设置,典型的frommanib.}overridefuncdidReceiveMemoryWarning(){super.didReceivereceiveresourceWarning()//Disposeofberany}eccontrol}站打印2017-03-0216:08:24.000HostApplication[19524:167669]textForOC好了,框架打包成功。问题通常我们要对外暴露的接口是纯Swift的,而OC文件的具体接口应该是隐藏的,这就是我题目中优雅二字的意思。如果你好奇的话,你会发现在ViewController.swift中可以这样调用vars=OCSource(),也就是OC的内容也暴露了,打破了Framework的封装特性。通过查看MixFramework的编译结果,我发现暴露最多的接口是这样的.Allrightsreserved.////!ProjectversionnumberforMixFramework.publicvarMixFrameworkVersionNumber:DoubleopenclassClassForOC:NSObject{publicstaticlettextForOC:String}openclassSwiftIt{publicinit()publicfuncencapsulate()}这行暴露了OC的对应实现。importMixFramework.OCSource的优雅方案不再是让框架中的Swift通过伞头的方式调用OC方法。相反,通过模块映射。新建一个module.modulemap文件,内容如下moduleOCSource[system]{//因为module.modulemap和OCSource.h在同一个文件夹下,如果不一样,路径要写完整的header"OCSource.h"export*}#(SRCROOT)这里是XCode的一个宏,会自动替换成项目所在的根目录。这里输入的路径就是module.modulemap文件所在的路径。然后,删除MixFramework.h(umbrellaheader)中#import的OC头。将OCSource.h的权限更改回默认项目。再次编译,发现隐藏了OC类。总结如果要开发一个框架,你必须想好哪些接口是暴露的,哪些是封装的。框架不仅仅是将文件包添加到shell。