How should a Swift + Objective-C project be setup

2019-01-17 03:06发布

问题:

I'm finding it very hard to find out how to configure test targets in Xcode 6b4. Can someone point me in the right direction given this scenario.

I have a mostly Swift project. However, there are some 3rd party Objective-C dependencies, which get put into the application's bridging header. I want to write tests for my Swift code. Ideally, in Swift. The problem I have is this....

  1. If I create a Swift test case, then the compiler complains that it can't find the Objective-C headers in the application's bridging header.

  2. If I create an Objective-C test case, then I cannot import the Swift classes which I want to test.

The only thing which I can do is write Objective-C tests cases, which don't touch any Swift. I cannot write "purely Swift code/tests" due to the Objective-C dependencies.

Does anyone have any advice or had success on this. Or is this the current state of things in Beta 4?

回答1:

I am not sure if you are still looking for this as XCode 6 is not in beta any more, but you can add your Objective-C Bridging Header file to your Unit Test Target in the target settings. This fixed the issue for me.



回答2:

From Xcode 6 Beta 4 release notes known issues:

Testing

• Unit tests written in Objective-C cannot currently import the Swift generated interfaces header ("$(PRODUCT_MODULE_NAME)-Swift.h") for application targets, and therefore cannot be used to test code that requires this header. (16931027)

• Workaround: Unit tests for Swift code should be written in Swift. Unit tests written in Objective-C for framework targets can access the Swift generated interfaces by importing the framework module using '@import FrameworkName;’.

So, you can't currently test Swift code in Objective-C.

Also from the release notes:

A limitation of the access control system is that unit tests cannot interact with the classes and methods in an application unless they are marked public. This is because the unit test target is not part of the application module.

Chris Lattner has stated on this post on the Developer Forums that they are still evaluating the situation to see how they can conciliate unit tests and the newly implemented access controls.

So, I'd expect many changes to unit testing both in Swift by itself, as well as in projects that use both Swift and Objective-C.



回答3:

We made this working, i saw all the possible errors along the way: module name errors when getting a VC from storyboard, MyType_MyType_ errors specific to coredata entities, and so on but this were the worst.

The trick is to use the -Swift.h file from the build target instead the tests target, because in the tests target sometimes you have to include objc files but not swift files and objc will not recognise those if they are linked together, but in the build target everything is there.

  • First thing make sure the -Swift.h of the tests target is not named the same as the build target.

  • Include in the tests .pch or in each individual file the -Swift from debug target.

  • Let the compiler know where is that file (in derivedsources) by editing the User Header Search Paths with: $(OBJROOT)/MyProjectName.build/Debug-iphonesimulator/MyProjectTarget.build/DerivedSources If not sure just go inFinder and find the names. If there are spaces in the names you need to add \ before space

  • You can find more about the project variables here: How do I print a list of "Build Settings" in Xcode project?

  • Always search User Paths should be set to YES

  • Don't include the swift files in the tests target, but use @testable

I hope Apple did fix this in the next xcode.



回答4:

I made working by updating "Objective-c generated Interface Header Name" to "YourApplication-Swift.h"

By default settings for this is to generate TargetName-Swift.h, compiler never generate YourApplicaitonTest-Swift.h



回答5:

I came across this question when trying to figure out how to access my project's Swift code from my Swift tests. Both my project and tests were originally started in Objective-C so they have all the bridging headers setup.

In order to access the Swift classes from my project I had to add:

@testable import MyProjectName

To the top of my Swift test file. After building it for the tests then Xcode recognized my swift code.

I hope that helps someone else.



回答6:

I had this problem and tried to solve it in build settings for the test target. By changing search paths, importing swift header, importing things in the bridging header. However it turned out to be in my podfile. I had to add a link_with with the test target. Like this:

platform :ios, '8.0'
link_with 'YourApp', 'YourAppTests'
pod 'ThePopularPod', '1.2.3', :inhibit_warnings => true


回答7:

Try putting the #import "xyz-Swift.h" statements into your precompiled header files. That way you have different import statements for all of your Obj-C headers, depending on the target:

MyProject-Prefix.pch (app target):

#import "MyProject-Swift.h"

MyProjectTests-Prefix.pch (test target):

#import "MyProjectTests-Swift.h"