4

I have a framework building where it combines both Objective-C and Swift. My issue is that some of the Objective-C code within the framework needs to use some of the Swift classes in the framework. In order to do this, I do:

#import "FrameworkName-Swift.h" 

in my Objective-C code in the framework. And here the first problem arises. The -Swift.h header is not located by Xcode this way. Digging around in the Derived Data, it turns out the -Swift.h file is located in the Framework/Headers folder, which in of itself seems odd. Should the -Swift.h file really be an exposed header for the framework? The -Swift.h file is an intermediary .h file, right?

To work around this issue of not locating the -Swift.h, I tried:

#import <FrameworkName/FrameworkName-Swift.h>

BUT, while now locating the -Swift.h file, this causes a severe and compilation-fatal rash of cyclic dependencies in Xcode, with messages like:

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

Here's what those look like in-situ:

enter image description here

Thoughts?

2
  • 1
    Did you take look at "Importing Code from Within the Same Framework Target"developer.apple.com/library/ios/documentation/Swift/Conceptual/… Commented Oct 3, 2015 at 6:00
  • Thanks @Shripada. I took a look at that now, and according to Apple I'm doing things correctly. Have worked around this problem and understand it a little more now, and will put in an answer below. Commented Oct 4, 2015 at 0:07

1 Answer 1

4

I have an incomplete answer to this, which is more of a partial explanation and a workaround that works for me. Here's what I think is causing the issue.

While Apple let's you call Swift code that is in the framework, from your Objective-C in the framework, if the same Objective-C class also needs to be used from Swift you run into an include/import cycle. Here's the situation I have.

Call my Objective-C class Objc with files Objc.m and Objc.h

Now, since Objc has to use Swift code it needs an import something like this:

#import <FrameworkName/FrameworkName-Swift.h>

which in my case goes in the Objc.m file.

And since the Swift code needs to use the Objc class, you need the following in the Framework umbrella .h file (the umbrella .h file is named FrameworkName.h):

#import <FrameworkName/Objc.h>

Now, if you take a look at the FrameworkName-Swift.h file that is generated by Xcode (Xcode 7.0.1 in my case), you find that it has an import of #import <FrameworkName/FrameworkName.h>, which forms a cycle back to Objc.m.

My workaround for this was no more than a situation specific hack. It turns out that in my case Objc.m didn't critically need the Swift code. It just made the code look nicer and better engineered. So, with a comment and a couple of extra lines of (Objective-C) code in Objc.m, I worked around my issue.

Very insidiously, Xcode 7 (at least) is really resistant to getting out of this issue once you are in it. That is, when you get this cyclic dependency error, it can be very difficult to have Xcode stop telling you you have it, even if you have taken the cyclic dependency out of the code. I tried many things including removing all of the Derived Data files/folders, quitting Xcode, and restarting my Mac, and found nothing that worked consistently to have Xcode stop believing it had a cyclic dependency even though I'd fixed the issue.

This resulted in the more difficult fix. I had to effectively rebuild my Framework from scratch, every step along the way building and saving to my version control system so I'd be darn sure I could recover if Xcode started being convinced I had one of these cyclic dependencies. Makes me have even less faith in Xcode. :(.

Second fix: A workaround (10/9/15)

I've found a fix that works in some other cases:

1) Clean/remove your Xcode Derived Data, including the ModuleCache

2) Build a known working copy of your Xcode project (in my case, I had a revision before I started adding the framework)

3) Now, go back to your Xcode project with the framework included and attempt a build. For me, this now works.

This is strictly a work-around, and resolves a cyclic dependency issue that appears in somewhat different framework conditions for me than I described in the present question. I'm talking to Apple engineer right now about this issue, so will see if I can get a better fix. I'd rather not have to apply this workaround.

"Final Solution": Namespace pollution (10/22/15)

I have figured out what was going on!! It was a case of include file name space pollution. I had an Objective-C class named "Assert" (note the upper case "A"), with files Assert.h and Assert.m. I have been using this Objective-C class (part of my internal debugging) for quite a while. At least a year if not more, to no apparent problem with Xcode. Now, when I started using it in conjunction with a Cocoa Touch Framework of my own construction, a problem came up. It turns out that if I cleaned the Derived Data first, that the /usr/include/assert.h file was being picked up, and not my own Assert.h Really odd.

And, if the Derived Data was not cleaned and I'd built a non-framework version of my project first (for the specific platform, e.g., for my iPhone if I was building for that), then my own Assert.h would get picked up.

My fix was pretty simple-- took about 10 minutes. I changed the name of my file/class to SMAssert with files SMAssert.h/.m. And then changed the references to the file in the various places that imported it. Voila!

Sign up to request clarification or add additional context in comments.

2 Comments

I haven't sent in a bug report to Apple on this yet. Give me some feedback if you've encountered this too, and I will do so.
I just filed a bug report on this. Here's the (redundant) radar: openradar.appspot.com/23218303

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.