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

简介:

前言

为什么要写这样一篇文章,因为昨天和一个朋友讨论到Swift和Objective C如何混合开发Framework,中途发现了很多有意思的坑。

用Swift封装OC的库是一件比较常见的事情,毕竟对于大多数公司来说,老的代码都是用OC写的,而且经过多次迭代,这些OC的代码已经被验证了是稳定的,用Swift重写代价太大。这就引入了一个需求:

  • 用Swift和OC来混编一个Framework。

如果你之前没有用Swift和Objective C混合开发,建议看看这篇文档:

  • Swift and Objective-C in the Same Project

https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

按照文档一步一步来

新建一个基于单页面工程,然后新建一个一个Target,选中Cocoa Touch Framework。然后,分别新建一个Swift文件和Objective C类,注意Target Member Ship选中Framework。类的内容如下:

OCSource.h


  
  
  1. #import <span class="hljs-title"><Foundation/Foundation.h></span> 
  2.  
  3.   
  4.  
  5. @interface OCSource : NSObject 
  6.  
  7. - (void)functionFromOC; 
  8.  
  9. @end  

OCSource.m


  
  
  1. #import "OCSource.h" 
  2.  
  3.   
  4.  
  5. @implementation OCSource 
  6.  
  7.   
  8.  
  9. - (void)functionFromOC{ 
  10.  
  11.     NSLog(@"%@",@"Log from objective c in framework"); 
  12.  
  13.  
  14. @end  

Swift调用OC

新建SwiftSource.swift


  
  
  1. open class SwiftIt{ 
  2.  
  3.     public init(){} 
  4.  
  5.     let ocObject = OCSource() 
  6.  
  7.     public func encapsulate(){ 
  8.  
  9.         ocObject.functionFromOC() 
  10.  
  11.     } 
  12.  
  13.  

然后,按照文档中,为了让Swift文件访问Objective C文件,我们应该在umbrella header,也就是MixFramework.h中,暴露所需要的header。

也就是,MixFramework.h,


  
  
  1. #import <MixFramework/OCSource.h> 

然后,自信满满的点击build。

Boom~~~,编译不通过。

原因:OCSource.h默认编译的时候是Project权限. 为了在umbrella header中使用,要把这个文件的权限改成Public

按照图中的方式拖过去即可。

嗯,现在build,可以看到build成功了。

OC调用Swift

在SwiftSource.swift中,增加一个类,


  
  
  1. open class ClassForOC:NSObject{ 
  2.  
  3.     public static let textForOC = "textForOC" 
  4.  
  5.  

然后,为了在OC中调用Swift的方法,我们需要导入头文件,这时候,OCSource.m文件内容如下


  
  
  1. #import "OCSource.h" 
  2.  
  3. #import <MixFramework/MixFramework-Swift.h> 
  4.  
  5.   
  6.  
  7. @implementation OCSource 
  8.  
  9.   
  10.  
  11. - (void)functionFromOC{ 
  12.  
  13.     NSLog(@"%@",[ClassForOC textForOC]); 
  14.  
  15.  
  16. @end  

然后,build,发现成功了,很开心。

外部调用

在ViewController.swift中,我们调用Framework中的内容。


  
  
  1. import MixFramework 
  2.  
  3. class ViewController: UIViewController { 
  4.  
  5.     var t = SwiftIt() 
  6.  
  7.     override func viewDidLoad() { 
  8.  
  9.         super.viewDidLoad() 
  10.  
  11.         t.encapsulate() 
  12.  
  13.         // Do any additional setup after loading the view, typically from a nib. 
  14.  
  15.     } 
  16.  
  17.   
  18.  
  19.     override func didReceiveMemoryWarning() { 
  20.  
  21.         super.didReceiveMemoryWarning() 
  22.  
  23.         // Dispose of any resources that can be recreated. 
  24.  
  25.     } 
  26.  
  27.  

然后运行,发现控制台打印出


  
  
  1. 2017-03-02 16:08:24.000 HostApplication[19524:167669] textForOC 

嗯,framework打包成功了。

问题

通常,我们希望暴露给外部的接口是纯Swift,而OC文件的具体接口应该隐藏,这就是我标题中的优雅两个字的含义。

如果你好奇,你会发现,在ViewController.swift中你可以这么调用


  
  
  1. var s = OCSource() 

也就是说,OC的内容也暴露出来了,这破坏了Framework的封装特性。

通过查看MixFramework的编译结果,发现最后暴露出的接口是这样子的


  
  
  1. import Foundation 
  2.  
  3. import MixFramework.OCSource 
  4.  
  5. import MixFramework 
  6.  
  7. import MixFramework.Swift 
  8.  
  9. import SwiftOnoneSupport 
  10.  
  11. import UIKit 
  12.  
  13.   
  14.  
  15. // 
  16.  
  17. //  MixFramework.h 
  18.  
  19. //  MixFramework 
  20.  
  21. // 
  22.  
  23. //  Created by Leo on 2017/3/2. 
  24.  
  25. //  Copyright © 2017年 Leo Huang. All rights reserved. 
  26.  
  27. // 
  28.  
  29.   
  30.  
  31. //! Project version number for MixFramework. 
  32.  
  33. public var MixFrameworkVersionNumber: Double 
  34.  
  35. open class ClassForOC : NSObject { 
  36.  
  37.   
  38.  
  39.     public static let textForOC: String 
  40.  
  41.  
  42.   
  43.  
  44. open class SwiftIt { 
  45.  
  46.   
  47.  
  48.     public init() 
  49.  
  50.   
  51.  
  52.     public func encapsulate() 
  53.  
  54.  

这一行,把OC对应的实现暴露出来了


  
  
  1. import MixFramework.OCSource 

优雅的解决方案

不再通过umbrella header的方式让framework中的Swift调用OC方法。而是通过modulemap。

新建一个module.modulemap文件,内容如下


  
  
  1. module OCSource [system] { 
  2.  
  3.     //由于module.modulemap和OCSource.h是在同一个文件夹的,如果不是同一个,路径要写全 
  4.  
  5.     header "OCSource.h" 
  6.  
  7.     export * 
  8.  
  9.   

这里的#(SRCROOT)是XCode的宏,会自动替换成项目所在的根目录,这里输入的路径是module.modulemap文件所在的路径。

然后,删除MixFramework.h(umbrella header)中#import 的OC header。

把OCSource.h的权限改回默认的project。

再编译,发现OC的类被隐藏了。

总结

如果你要开发一个framework,一定要想清楚哪些接口暴露出去,哪些封装起来,framework不是简单把一包文件加个壳子。




本文作者:佚名
来源:51CTO
目录
相关文章
|
1天前
|
机器学习/深度学习 TensorFlow Swift
Swift语言适合多个领域的开发
Swift语言适合多个领域的开发
18 9
|
1天前
|
安全 编译器 Swift
Swift开发
Swift开发
16 9
|
4天前
|
安全 数据处理 Swift
深入探索iOS开发中的Swift语言特性
本文旨在为开发者提供对Swift语言在iOS平台开发的深度理解,涵盖从基础语法到高级特性的全面分析。通过具体案例和代码示例,揭示Swift如何简化编程过程、提高代码效率,并促进iOS应用的创新。文章不仅适合初学者作为入门指南,也适合有经验的开发者深化对Swift语言的认识。
19 9
|
17天前
|
安全 API Swift
探索iOS开发中的Swift语言之美
【10月更文挑战第23天】在数字时代的浪潮中,iOS开发如同一艘航船,而Swift语言则是推动这艘船前进的风帆。本文将带你领略Swift的独特魅力,从语法到设计哲学,再到实际应用案例,我们将一步步深入这个现代编程语言的世界。你将发现,Swift不仅仅是一种编程语言,它是苹果生态系统中的一个创新工具,它让iOS开发变得更加高效、安全和有趣。让我们一起启航,探索Swift的奥秘,感受编程的乐趣。
|
1月前
|
安全 Swift iOS开发
探索iOS开发中的Swift语言之美
在数字时代的浪潮中,移动应用已成为日常生活的延伸。本文将深入探讨iOS平台上的Swift编程语言,揭示其背后的设计哲学、语法特性以及如何利用Swift进行高效开发。我们将通过实际代码示例,展示Swift语言的强大功能和优雅简洁的编程风格,引导读者理解并运用Swift解决实际问题。
|
iOS开发
Objective-C调用Swift
<p><span style="font-size:14px;">如果已经有了一个老的iOS应用,它是使用Objective-C编写的,而它的一些新功能需要采用Swift来编写,这时就可以从Objective-C调用Swift。</span></p> <p><span style="font-size:14px;">Objective-C调用Swift时不需要桥接头文件,而是需要Xcode生成
1431 0
|
6月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
388 2
|
4月前
|
开发工具 iOS开发 容器
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
iOS Objective-C 应用连接Azure Storage时,若不关闭账号的匿名访问,程序能正常运行。但关闭匿名访问后,上传到容器时会出现错误:“Public access is not permitted”。解决方法是将创建容器时的公共访问类型从`AZSContainerPublicAccessTypeContainer`改为`AZSContainerPublicAccessTypeOff`,以确保通过授权请求访问。
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
|
6月前
|
缓存 开发工具 iOS开发
优化iOS中Objective-C代码调起支付流程的速度
优化iOS中Objective-C代码调起支付流程的速度
102 2
|
6月前
|
安全 JavaScript 前端开发
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
262 0