iOS 具有 Swift 和 Objective-C 的框架 Objective-C 使用 Swift C

iOS Framework With Swift and Objective-C Where the Objective-C Uses Swift C

我有一个框架构建,它结合了 Objective-C 和 Swift。我的问题是框架内的一些Objective-C代码需要使用框架内的一些Swift类。为此,我这样做:

#import "FrameworkName-Swift.h" 

在我的 Objective-C 框架代码中。这里出现了第一个问题。 -Swift.h header 不是由 Xcode 这样定位的。在派生数据中四处挖掘,结果发现 -Swift.h 文件位于 Framework/Headers 文件夹中,这本身看起来很奇怪。 -Swift.h 文件真的应该是框架的公开 header 吗? -Swift.h 文件是一个中间.h 文件,对吗?

为了解决这个找不到 -Swift.h 的问题,我尝试了:

#import <FrameworkName/FrameworkName-Swift.h>

但是,在现在定位 -Swift.h 文件时,这会导致 Xcode 中出现严重的 compilation-fatal 循环依赖,并显示如下消息:

Cyclic dependency in module 'FrameworkName'
Could not build module 'UIKit'

这些看起来像这样 in-situ:

想法?

我对此的回答不完整,这更多是部分解释和适合我的解决方法。这是我认为导致问题的原因。

虽然 Apple 让您从框架中的 Objective-C 调用框架中的 Swift 代码,如果 相同 Objective-C class还需要用到从Swift你运行进入一个include/import循环。这是我的情况。

使用文件 Objc.mObjc.h

调用我的 Objective-C class 对象

现在,由于 Objc 必须使用 Swift 代码,因此需要像这样导入:

#import <FrameworkName/FrameworkName-Swift.h>

我的例子是 Objc.m 文件。

并且由于Swift代码需要使用Objc class,所以需要在Framework umbrella .h文件中添加以下内容(umbrella .h文件名为FrameworkName.h) :

#import <FrameworkName/Objc.h>

现在,如果您查看由 Xcode(在我的例子中为 Xcode 7.0.1)生成的 FrameworkName-Swift.h 文件,您会发现它有一个导入#import <FrameworkName/FrameworkName.h>,形成一个循环回到 Objc.m

我对此的解决方法只不过是针对特定情况的黑客攻击。事实证明,在我的例子中 Objc.m 并不迫切需要 Swift 代码。它只是让代码看起来更好,设计得更好。因此,通过 Objc.m 中的注释和几行额外的 (Objective-C) 代码,我解决了我的问题。

非常阴险,Xcode 7(至少)一旦你进入这个问题真的很难摆脱它。也就是说,当您遇到此循环依赖错误时,很难让 Xcode 停止告诉您您拥有它,即使您已将循环依赖从代码中移除。我尝试了很多方法,包括删除所有派生数据 files/folders、退出 Xcode 并重新启动我的 Mac,但没有发现任何东西始终如一地让 Xcode 停止相信它有循环依赖,即使我已经解决了这个问题。

这导致更难修复。我必须从头开始有效地重建我的框架,构建和保存到我的版本控制系统的每一步,所以如果 Xcode 开始确信我有这些循环依赖项之一,我肯定可以恢复。更让我对Xcode没信心了。 :(.

第二个修复:解决方法 (10/9/15)

我发现了一个在其他一些情况下有效的修复方法:

1) Clean/remove 您的 Xcode 派生数据,包括 ModuleCache

2) 构建您的 Xcode 项目的已知工作副本(就我而言,在 我开始添加框架之前 我进行了修订)

3) 现在,返回包含框架的 Xcode 项目并尝试构建。对我来说,现在可以了。

这完全是一种解决方法,它解决了一个循环依赖问题,该问题出现在与我在当前问题中描述的框架条件略有不同的框架条件下。我现在正在与 Apple 工程师讨论这个问题,所以我会看看我是否能得到更好的解决方案。我宁愿不必应用此解决方法。

"Final Solution": 名称space 污染 (10/22/15)

我明白是怎么回事了!!这是包含文件名 space 污染的情况。我有一个名为 "Assert" 的 Objective-C class(注意大写 "A"),其中包含文件 Assert.h 和 Assert.m。我使用这个 Objective-C class(我内部调试的一部分)已经有一段时间了。至少一年,如果不是更长时间,Xcode 没有明显的问题。现在,当我开始将它与我自己构建的 Cocoa Touch Framework 结合使用时,出现了一个问题。事实证明,如果我先清理派生数据,则会拾取 /usr/include/assert.h 文件,而不是我自己的 Assert.h 真奇怪。

而且,如果派生数据没有清理,我首先构建了我的项目的非框架版本(针对特定平台,例如,如果我正在为此构建我的iPhone) , 然后我自己的 Assert.h 就会被捡起来。

我的修复非常简单 -- 大约需要 10 分钟。我用文件 SMAssert.h/.m 将 file/class 的名称更改为 SMAssert。然后在导入它的各个地方更改对该文件的引用。瞧!