Unit Tests for Swift & Objective C files - ios

I’m having trouble setting up Unit tests (XCTestCase) for my Xcode Project.
The project contains Objective C and Swift files.
'Enable testability' and 'Defines Module' is set to 'YES'
I imported the main project with: #testable import Projectname
I created a separate (empty) Bridging header . And made sure that all te frameworks are imported in the Unit testing Target (through Project > Build Phases).
This works fine for all the Objective C classes/files. But not with the swift classes with have Objective C functions in it.
When i’m running the test it fails. And almost all the #import lines in the main bridging header get the same warning: “Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)”
I also get a warning for the class i try to import:
“Undefined symbols for architecture x86_64:
“Project.BaseController.__allocating_init () -> Project.BaseController", referenced from:
Main_App.ProjectTests.setUp () -> () in ProjectTests.o
"type metadata accessor for Flitsmeister.BaseController", referenced from:
Main_App.ProjectTests.setUp () -> () in ProjectTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)”
Is it possible to test Swift files with imported Objective C code?
Are there workarounds?

Related

Calling swift function from objective c gives linker error

I am trying to call swift function from objective c file.
Swift function implementation:
#objc class FXFormVariables : NSObject {
class func FXFontName() -> String { return fontName }
class func FXFontSize() -> CGFloat { return fontSizeLarge }
class func FXHiddenCell() -> NSArray { return hiddenElementFromFormIndex as NSArray }
}
Objective C:
NSArray *hideArray = [FXFormVariables FXHiddenCell];
if ([hideArray containsObject:#(cellIndexPath)]){
return 0.0;
}
Linker error in Buildtime:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$__TtCC13Social_Engine11AppDelegate15FXFormVariables", referenced from:
objc-class-ref in FXForms.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This code works fine in Xcode 7.3 but after upgrade to 8.3 it start throwing linker error.
Please help. Thanks in advance.
Import file named Project name appending by -Swift.h in your Objective-C file
Please check below example of import file
#import “ProjectName-Swift.h”
Xcode will generate this file when you build your project with .swift files.
Also, you can check from below question:
How to import Swift code to Objective-C
you can get this type of error check your class is listed under the "Compile Sources" step of the "Build Phases" tab of your target. Normally Xcode does this for you, but sometimes it loses the plot and you need to add the class file manually.
To do this:
TargetSettings -> Build Phases -> Compile Sources -> add your class -.swift >Build and Run

.c File via Bridging Header Not Working After Xcode 8 Update

The app I've been working on uses an external library, pdlib, which has it's own externals (.c files) which I've been importing via the bridging header #import "Uzi.c" and calling in my main Swift file via Uzi.c's setup function Uzi_setup() in my ViewController class. I've had no problem with this until after updating to new public Xcode 8 a few days ago (I had no problem with Xcode 8 Beta 1 over the Summer).
Here are the 7 errors I get, listed under a single "Mach-O Linker Error" umbrella:
Undefined symbols for architecture x86_64:
"_Uzi_bang", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_class", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_float", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_new", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_pause", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_resume", referenced from:
_Uzi_setup in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Those undefined symbols are 6 functions and a class declare from Uzi.c. Here's a link to the whole c file: https://github.com/electrickery/pd-miXedSon/blob/master/hammer/Uzi.c
I've tried every solution I've found online for dealing with similar problems, with no solution yet... I tried changing the "Architecture" and "Valid Architecture" settings to only armv7 and armv7s (no arm64) and changed "Build Active Architecture Only" to "No". These step seem to help others in similar situations, but they didn't work for me (and taking away arm64 causes additional errors to appear).
XCode 8 is pretty recent (the public version was released Sept. 13), so there are virtually no other questions about this upgrade causing a similar problem.
Any help would be greatly appreciated!
Solved by #danomatika on GitHub: https://github.com/libpd/libpd/issues/149
"You generally shouldn't include/import an implementation file aka .c, .cpp, .m, etc. This is what is causing the duplicate symbol issue.
This is what the "forward function declaration" in the header file is for: to tell the compiler that a function exists and what data it takes/returns. The compiler then assumes the actual implementation of the function exists in an implementation file. If it can't be found, then you get an "undefined symbol error." If you somehow end up declaring the function twice, aka include both a header with the forward declaration and the implemetaton of the function itself in the .c file, then you get a "duplicate symbol error."
This is all lower-level stuff that is only really an issue since Pd externals are designed around being dynamic libraries, so are not built or provided with headers which include the function declarations. This is why you have to do a little extra work and do it yourself.
Their are two easy fixes for this, both of which involve declaring the required function you want to call from the .c file in a header file.
Simply declare the function in the bridging header:
void uzi_setup();
Create a header, say Externals.h, and declare all of the externals stuff there:
// forward declare setup functions only found in .c implementations
void uzi_setup();
// convenience wrapper function
void externals_setup() {
uzi_setup();
}
Then import the file in your bridging header:
#import "Externals.h"
And in swift, you can now do:
externals_setup()

Admob Conversion Tracking in Swift

I tried to set conversion tracking in my iOS game, but I didn't be able to do that. The tutorial can be found here: https://developers.google.com/app-conversion-tracking/ios/?hl=it#usage_and_disclosure
I integrate the GoogleConversionTrackingSDK to my project, load AdSupport framework and type -ObjC in Other linker flags.
I tried to convert this snippet from Obj-C:
[ACTConversionReporter reportWithConversionID:#"MY_ID" label:#"MY_LABEL" value:#"MY_VALUE" isRepeatable:NO];
to Swift:
ACTConversionReporter.reportWithConversionID("MY_ID", label: "MY_LABEL", value: "MY_VALUE", isRepeatable: false)
and I put that in didFinishLaunchingWithOptions method of AppDelegate.swift, but I get the error:
Use of unresolved identifier 'ACTConversionReporter'
If I type in Obj-C bridging header in Swift Compiler - Code Generation in Build Settings "ACTReporter.h" (without qm), I put the header file in the folder of my game or if I type the whole path of "ACTReporter.h" ending with its name, I fail the build and I get 2 errors:
Undefined symbols for architecture armv7:
"_OBJC_CLASS_$_ACTConversionReporter", referenced from:
type metadata accessor for __ObjC.ACTConversionReporter in AppDelegate.o
ld: symbol(s) not found for architecture armv7 clang: error: linker
command failed with exit code 1 (use -v to see invocation)
I don't know what to do. I hope there is someone who can fix this.
You need to add to your project "YourProjectName-Bridging-Header.h" file
Here you can see how to add the file
in Bridging Header file add #import "ACTReporter.h"
Then it will work for you!

Linker error when implementing NSObject protocol while using enums?

Here is a distilled version of the code I am having trouble with in Swift:
enum E {
case C
}
class Test: NSObject {
var v: E = .C
}
When I attempt to build, I get the following error:
Undefined symbols for architecture x86_64:
"__TWvdvC8TestTest4Test1vOS_1E", referenced from:
__TFC8TestTest4Testm1vOS_1E in AppDelegate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
To reproduce this, simply make a new Swift project and paste the above code right into "AppDelegate.swift". Alternatively, make a new file and stick it in there instead!
Am I missing something obvious or is this yet another Swift bug? I did try deleting all derived data and other forms of voodoo magic.
Thanks for the help!
It seems like the compiler removes the enum if there is only one case?
I can reproduce your issue, it disappears when I add a second case :
enum E {
case C,D
}
class Test: NSObject {
var v : E = .C
}
I noticed a couple things when trying this:
In the current non-beta version of Xcode, I see the error you're referring to (almost certainly a Swift bug). However, if I add an extra value to the enum (case C,D), it compiles just fine
I couldn't reproduce the crash in the latest Xcode beta (Version 6.3 (6D520o)), which leads me to believe that the bug has been fixed in Swift 1.2

UIColor Category Linker Errors

Earlier today I tried to add Unit tests to my xcode project for a static framework that I am creating. After adding the Unit Tests target to my project, I was able to successfully run the unit tests template and have the tests catch the default assertion. Then, after importing the file that I wanted to test into my new SenTestCase subclass, I tried to run the test but my UIColor category failed building with the test due to linker errors. The text of the linker errors is as follows:
Undefined symbols for architecture i386:
"_CGColorGetComponents", referenced from:
-[UIColor(ColorExtension) hexValue] in StaticFramework(StaticFramework)
"_CGColorGetNumberOfComponents", referenced from:
-[UIColor(ColorExtension) hexValue] in StaticFramework(StaticFramework)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Next, I found where these two references were in my project. Both live in my category under the following function:
- (NSString *)hexValue
{
UIColor *color = self;
const size_t totalComponents = CGColorGetNumberOfComponents(color.CGColor);
const CGFloat * components = CGColorGetComponents(color.CGColor);
return [NSString stringWithFormat:#"#%02X%02X%02X",
(int)(255 * components[MIN(0,totalComponents-2)]),
(int)(255 * components[MIN(1,totalComponents-2)]),
(int)(255 * components[MIN(2,totalComponents-2)])];
}
If I remember correctly, both of these are part of the NSColor class. With a little more inspection, I also noticed that in my Unit Test's framework's folder, both UIKit.framework & Foundation.framework are red. I have tried reimporting them and building but this does not fix that issue either.
Interestingly enough, my static framework will still build and run fine as long as the associated Test is not also run. And when I comment this function out (and every time I use it), the Unit Test builds without issues. Would I be correct in my assumption that the missing UIKit.framework & Foundation.framework could be causing the linker not finding the NSColor properties? Does anyone have any additional suggestions that could explain why these properties are causing these issues or what I could do to fix them?
Any help would be greatly appreciated. Thanks for the assistance.
The linker error indicates that you are using CoreGraphics functions but you are not linking the CoreGraphics framework.
Update your project/target so you link the CoreGraphics.framework and the linker issues will be resolved.

Resources