Creating a framework with mixed Swift & Objective-C code - ios

I have a project with mixed code (objective-c and Swift) that I need to package as a framework. It also uses some external frameworks.
My umbrella header has many imports to different headers of the frameworks I use, as well as to the objective-c source code in my project (so that it's accessible by the Swift code). I also have a swift file, e.g. MyFramework.swift, that has some code that I'd like to expose to users of the framework.
The framework compiles, however, when I try to use it in another Swift project, I cannot access the contents of MyFramework.swift. That is the case even though the file exists (with the Swift source code) in the framework product!
Yet, I am able to access the objective-c code from the public headers. So I tried to write the code in MyFramework.swift in objective-c instead (MyFramework.h & MyFramework.m), because I thought it might be a problem exposing code in both objective-c and swift (though from what I read - it shouldn't be). That did the trick in terms of accessing the objects inside this class, but then I got a linker error:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_MyObject", referenced from:
__TZFC12TestFW6MyObject20testfMS0_FCSo16UIViewControllerT_
in ViewController.o ld: symbol(s) not found for architecture x86_64
This actually happens for every public swift class I try to reference. I made sure these files exist in the "Compile Sources" list under Build Phases of the project settings, so that's not the problem.
I'm pretty clueless. Any ideas?
Thanks.

To solve your project there's 2 things to check.
Do you have the correct "valid architecture" in your project
(1st picture below), and
Do you have a BridgingHeader properly
created for working with Swift and Obj-C in the same project (2nd
picture below)?

Related

Adding unit tests for an existing objective c + swift project

I have an existing iOs project which I would like to add a unit test target to. The classes I'd like to test are both in objective c and swift.
I've managed to create a test target which allows me to test swift only code by adding the implementation swift files to the test target.
However, as soon as I import or use a class that imports objective c code, I run into Linker issues when building the test target:
...
Symbols not found for architecture x86_64
I've tried adding the objectivec mm files to my target which gets my passed the linker error, but I then get an unresolved identifier error for the class I'm importing.
I'm using xcode 9 and swift 3.
edit: I think this may have something to do with the fact the swift bridging header is not available in the test target, however I'm not sure how to add it.
Your test project is a separate target and should have all files it relies upon to be tested linked separately. So first of all click one of the .m files it's missing and check if the test project is also included in the targets. If this is the case there might be a problem with the bridging header your test project uses. Figure out which one it uses from the build settings of your target and see if it includes the same files as your main project.

Duplicate symbol(s) for architecture(s) [arm7, arm64]

I have imported a new version of a framework in my SDK. Anyway, I am not able to build on iPhone 6 running iOS 9.0.1 because of the following error that's driving me crazy:
duplicate symbol _IPDJobStatus in:
/Users/akiki/Desktop/iOS 9 Test/MPSDK/iPD.framework/iPD(IPDDevice.o)
/Users/akiki/Desktop/iOS 9 Test/MPSDK/iPD.framework/iPD(IPDAdministration.o)
ld: 5 duplicate symbols for architecture arm7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This is happening for the same symbol _IPDJobStatus being found twice in 5 files. The same is happening on iPhone 4S running iOS 9.1 with arm64 architecture. To import the framework, I deleted the old one from the project, imported the new one and check into the Link Binary with Library section wether the framework reference links to the correct updated file. Before asking I have tried to perform the following actions:
I searched for the duplicate symbol inside the project scope with no result.
I'm not importing a .m file by accident.
The Compile Sources of the Build Phases project settings doesn't include any duplicate file.
The framework headers references in Headers of the Build Phases project settings link to the proper files.
I tried to clean the project, empty the Derived Data folder, quit and relaunch Xcode.
I added the -ObjC linker flag (in this case the duplicate symbols goes from five to only one).
I switched the No Common Blocks compiler setting to NO, though it has the same error with or without it.
I created a new empty project and imported the framework there. In this case I was able to build, so the problem must resides in my SDK.
Could someone please give me some help?
You can check your project directory may be there available framework. If available then delete it.
I was able to solve the same problem with the following code.
Add this to the Library Search Paths in Build Settings and make sure you select recursive, delete other library paths which might be absolute paths.
$(PROJECT_DIR)
May be it will help you.
You can not make constant type variables of same name & type in two or more classes.
_IPDJobStatus is this constant type variable?
change it to some other name for different classes.
Here you can see the same issue
It means in you project multiple copy of same View Controller instance (i,e means duplicate).
Possible observation:
This IPDJobStatus variable contains in the class IPDDevice or IPDAdministration of the framework is duplicate. Please check this.
Note: You should not have/create a class which already have in any other framework either Xcode's default or 3rd party framework.
For example: UIkit framework have class name "UIApplication" (i.e UIApplication.h, and UIApplication.m). So, if you create you class name "UIApplication". this error will occur. Same case for also 3rd party framework.

Undefined symbols for architecture in watchKit

The error that Im running into is Undefined symbols for architecture arm64:. Below I have provided more in-depth screenshots. The source of the error according to Xcode is within the watchKit extension within the interfaceController. The Class is referenced from a dynamic library. If I actually CMD+Click the framework that Im importing Im taken to the framework in Swift thats fully ported over to Swift, it is originally written in Objective-C. The second image shows my import statement for the class, and the 3rd image shows how I have setup the import statements within the .h of the framework file.
On the right sidebar when those files are selected, under Target Membership, is your app (with the little pencil icon) checked as a Target Membership?
That should fix your problem.
It's look like dynamic library doesn't have arm64 architecture is it. In order to verify please use following command against the static library of your dynamic library.
lipo -info <libraryName>.a
Please make sure that library is added into extension target.
If your library is not static library, and it is framework like .framework, please follow following step.
1. Go to framework using cd command
cd /Users/<User>/<Path>/<Library_Name>.framework
2. Use ls command and list out all the files within framework file. You will see three files named as "Library_Name, Headers and Versions".
3. Use following command to display all architecture that library has.
lipo -info <Library_Name>
4. You can see list of all architecture that library was build for.

Adding static library to project >> Undefined symbols

I have created a static library which I added to another project in the same workspace in XCode. The library builds fine, both for Simulator and an actual device.
All errors refer to classes in the library, so it's not about another framework.
I get two undefined symbols errors that both refer to "_OBJC_CLASS_$_Campaign"
When I build for an actual device I get Undefined symbols for architecture armv7s
When I build for a simulator I get Undefined symbols for architecture i386
I tried creating a fat library: same issue.
I toggled "build for active architecture only" on and off: doesn't help.
I deleted and rebuilt the XCode workspace: no solution.
I'm very sure I added the correct .m files to the "compile sources" of the library, and I properly added the library to the other project through "Link binary with libraries". I also tried just dragging the .lib to the Frameworks folder.
I added the header file of the .lib to the project.
I would be glad with any suggestion!
The problem is likely caused by the fact that your static library import something from another library.
You need to figure out what symbols are missing exactly and add library that defines them. Build log output should be very helpful in this regard.
EDIT: Based on discussion in comments, problem is caused by the fat that there's no implementation for Campaign class. Without implementation, compiler doesn't generate class and this results in linking error. There are no compile-time errors because interface of the class is declared though.
You should add such implementation, either in a separate Campaign.m file, or in one of already existing files.

iOS: Pull To Refresh error

I'm trying to implement a "pull to refresh" functionality to my table views.
I found a couple of classes that should do the trick (iStopped's PullToRefreshView & Leah's PullToRefresh)
Both classes throws me an error about undefined symbols for i386...
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_PullToRefreshView", referenced from:
objc-class-ref in FeaturedTableView.o ld: symbol(s) not found for architecture i386 clang: error: linker command failed with exit
code 1 (use -v to see invocation)
Thing is.. I linked against QuartzCore.framework in the Build Phases..
And in the Build Settings, under "architectures" (and "valid architectures"), I see both "armv6" & "armv7".
I searched around the web for that error regarding PullToRefresh, and all I could find is that the framework is missing... but it isn't (I even removed it and re-added it).
I also came across this tutorial, which says I need to Refactor (edit -> refactor) my project (convert to Objective-C ARC), but I can't do that because when I choose my target, I get LOTS of errors (especially from the Facebook SDK).
Isn't there a simple way to add a pull to refresh functionality? :)
Any help would be much appreciated!
Thanks!
Ok, I've found the actual issue:
I have several Targets that share the most of the project's code.
When I was importing the PullToRefresh class, I de-selected all of the Targets, because I noticed that all the other shared files in the project had all the targets in their properties de-selected...
When I re-imported the class and selected all the Targets, everything works fine... I'm now actually using the EGOTableViewPullRefresh and it's working great.
So I guess de-selecting all targets doesn't mean that it's completely shared across all targets :) I wonder why all my view controllers and all don't have any targets checked and they are available to all targets...
But the issue has been resolved (^_^)
Thank you, #jrtc27 , for making me check the import procedure again.
(Without seeing your code) You need to import the PullToRefreshView class.
#import "PullToRefreshView.h"
Or you need to make sure that your table controller (which seems to be FeaturedTableView) is a PullRefreshTableViewController.
Example
#interface FeaturedTableView : PullRefreshTableViewController
{
/* your objects here */
}
#end

Resources