基于 iOS Swift 的动态框架中的 Objective C 类 [英] Objective C classes within an iOS Swift-based dynamic framework

查看:19
本文介绍了基于 iOS Swift 的动态框架中的 Objective C 类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用 Swift 编写的 iOS 动态框架.我还有一堆用 Objective C 编写的类,我会在我的 Swift 类中使用它们(有些是公共的,有些是私有的).但是,我希望 Objective C 类不要暴露给使用我的框架的项目.

I've got an iOS dyanmic framework written in Swift. I've also got a bunch of classes written in Objective C that I would to use within my Swift classes (some are public, some are private). However, I would like the Objective C classes to not be exposed to projects using my framework.

伞头

据我所知,我应该在我的伞头文件中使用 #import header.h 导入,通常是 FrameworkName.h,然后确保所有我希望包含在我的 Swift 类中的 Objective C 头文件将在 Build Phases -> Headers 下标记为Public".

From what I understand, I should import using #import header.h in my umbrella header file, which is usually FrameworkName.h, and then make sure all the Objective C header files that I wish to include in my Swift classes are to marked as "Public", under Build Phases -> Headers.

但是,这样做会自动将使用我的框架的项目暴露给框架使用的所有私有 Objective C 类.

Doing this, however, automatically exposes the project using my framework to all the private Objective C classes that the framework uses.

模块映射(带有单独的模块)

因此,我研究了使用模块映射,该映射在here.我看过其他用户的帖子,例如 thisthis,以及 这个 Github 存储库.

Because of this, I've looked into using module mapping, which is documented here. I've looked at posts by other users such as this and this, as well as this Github repo.

我成功地完成了以下工作:

I successfully got the following working:

//SharedClasses/module.modulemap
module SharedClasses {
}

//SharedClasses/module.private.modulemap
module SharedClasses.Private {
    header "header.h"
    export *
}

问题是在我的项目中(导入了这个框架),这个:

The problem is that in my project (that has this framework imported), this:

import Framework
import Framework.SharedClasses

是允许的,随后会暴露隐藏的"Objective C 类.也许这就是模块的工作方式?有没有办法让它们真正私密?

is allowed, and subsequently the "hidden" Objective C classes are exposed. Perhaps this is just how modules work? Is there a way to make them truly private?

模块映射(带有框架私有模块)

此外,我尝试在框架的根目录中创建一个 module.private.modulemap 文件,其中包含以下内容:

Also, I've tried creating a module.private.modulemap file at the root of my framework with the following contents:

explicit module Framework.Private {
    header "header.h"
    export *
}

然后将它链接到 MODULEMAP_PRIVATE_FILE 下我的目标构建设置.但是,当我在框架的 Swift 类中执行 import Framework.Private 时,会引发编译器错误:

and then linking it my target's build settings under MODULEMAP_PRIVATE_FILE. However, when I do import Framework.Private in my framework's Swift classes a compiler error is thrown:

没有这样的模块‘Framework.Private’

"No such module 'Framework.Private'

我不明白为什么会出现这个错误.

I don't understand why this error is occurring.

模块映射(带有私有标头)

我注意到在 Clang docs 中,一个 private 提到了说明符:

I noticed that in the Clang docs, a private specifier is mentioned:

不能从模块本身外部包含带有私有说明符的标头.

A header with the private specifier may not be included from outside the module itself.

我的理解是,由于我框架中的所有 Swift 类都已经是模块 Framework 的一部分,如果我创建一个 module.modulemap 文件,如下所示:

My understanding is that since all the Swift classes in my framework are already part of the module Framework, if I create a module.modulemap file with the following:

framework module Framework {
    umbrella header "Framework.h"

    private header "header.h"

    export *
    module * { export * }
}

那么一切都应该正常工作了!Objective C 头文件只能在模块内访问(即框架的 Swift 类),并且不会暴露给任何使用框架的项目.很酷,但它不起作用……编译器只是无法识别 Objective C 类.没有抛出其他错误,但您不能使用标头,因此就好像您没有首先包含标头一样.为什么?那么私有说明符是什么?

then everything should be working! The Objective C headers are only accessible within the module (i.e. the framework's Swift classes), and aren't exposed to any project using the framework. Cool, but it doesn't work...the compiler just doesn't recognise the Objective C classes. No other errors are thrown, but you can't use the headers, so it's like you didn't include the headers in the first place. WHY? And what is the private specifier for then?

Soo,重申我最初的问题:

Soo, reiterating my original question:

有什么方法可以在 iOS 动态框架内导入 Objective C 标头以在 Swift 类中使用,同时保持它们的私密性并且不能从使用所述框架的任何项目访问?

感谢您的阅读,对于长篇博文深表歉意.这是漫长的一天(和夜晚)...

Thanks for reading, and sorry for the long post. It's been a long day (and night)...

推荐答案

快速回答是你不能 :) 即使你声明私有"模块映射,它也可以被你的框架用户.请注意,这通常不是问题,尤其是对于开源.你只是说这是一个内部模块,不要使用它".

The quick answer is you can't :) Even if you declare "private" modulemap, it can be always imported by your framework users. Please note, that usually, it is not a concern, especially with open source. You just say "this is an internal module, don't use it".

但是(总是有但是) - 你可以有行为,有效地工作相同 - 允许你使用具有相同框架目标的 Objective-C 类,而无需将它们公开.它在闭源设置中工作 - 我有一个动态框架交付给外部各方,目的是尽可能少地透露其构造.

But (there is always but) - you can have behavior, that effectively works the same - allows you to use your Objective-C classes withing same framework target, without making them public. It works in closed source setup - I have a dynamic framework shipped to external parties, that has a purpose of revealing as less about its construction as possible.

案例有点复杂,无法将所有内容粘贴到此处.我正在添加一个链接到我关于该主题的文章.这是一个总体思路:

The case a bit too complex to paste everything here. I'm adding a link to my article about the topic. That's a general idea:

  1. 使用 Swift 协议模仿您的 Objective-C 类(需要手动操作)
  2. 在您的 swift 代码中使用这些协议
  3. 在内部将这些 Swift 协议公开给 Objective-C(需要手动操作)
  4. 通过 ObjC 类采用这些协议
  5. 在 Swift 中创建并在 ObjC 中公开一个工厂,这将创建这些协议的实例
  6. 在工厂方法中创建,这将允许您注册具体类型,并将它们公开给 ObjC
  7. 在 Swift 工厂中从 Objective-C 代码注册 ObjC 类型
  8. 使用工厂实例化 ObjC 类,而不实际将 ObjC 暴露给 Swift (欢呼 ;) )

使用私有的 Objective-C 成员创建 Swift 框架.好的、坏的和丑的

Github 示例项目

这篇关于基于 iOS Swift 的动态框架中的 Objective C 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆