How do I import a Swift class from a framework?
I have Xcode Workspace
I create a Cocoa touch framework with using Swift
I create a Swift class named TestClass in that Cocoa touch framework
I create a Tabbed Base iOS application
I import my framework in that tabbed iOS application using import FrameWorkTest
The application project compiler can't find TestClass.
How can I import TestClass for use in the main application?
It says that TestClass is not defined. I also want to add an extension in FrameWork an then use it.
https://github.com/ArtemKyslicyn/-SwiftImportFrameworkTest
I'm using this Tutorial
http://www.swift-studies.com/blog/2014/6/30/creating-a-pure-swift-framework-for-both-ios-and-mac
I'm on Xcode version 6.0 seed
Thanks
Make the class in framework public. Also any variables must be public if you want them to use outside the framework.
public class MyClass... {
...
}
Here's one solution I found:
Create new iOS project
Press on project
Press + to add target
In the resulting window, choose cocoa touch framework
Press on project and press add dependency and add framework
Success!
I used the solution here: https://github.com/ArtemKyslicyn/-SwiftImportFrameworkTest in the project named AddingFrameWork
#Artem Kislitsvn: I did see your github repository,
In which you have TestClass.Swift file outside the targets 'test' and 'FrameWorkTest'. Which is out of the scope of the namespaces.
In Swift the namespaces are specified per targets. In your case 'test' and 'FrameWorkTest' are two targets. If you keep your file out of the targets, then your class(.swift file will not visible to at any time).
The solution is very simple. You just move your TestClass.Swift file inside any of the target groups (Drag and drop through Project explorer).
Following this your project works...!
To import a Swift class from a framework:
Go to your Project -> Build phases -> Select test target -> Link Binary With Libraries -> + Button -> Add other (on the dialog) -> Select your framework and congrats!
I leave the explanation in images below:
Related
Hi i have created a framework with a swift file having a public class. When i try to use this public class in the app project that i have linked this framework to , the xcode shows that there are no such class.
public class TestFrame {
public func hello() {
print("Hello World")
}
}
This is the class from my framework.
First i build the framework for my device, then link that file to the embedded binaries in my app project. Then i include a import statement of the framework name and then try to use this class(which is not possible at this stage).The Only file that i am able to access through framework is the .h(header file) of the framework. So what i need to do to get this class accessed in my app project.
The problem is that you built the framework for the device (arm) and now you are trying to link it to the simulator platform (i386).
You can either build two frameworks (one for the device, one for simulator), build a 'fat' framework including both architectures or you drag the framework project to your workspace so it is always built with for the selected target platform.
For anyone with the same problem:
Try building your framework for Generic iOS Device and then import it again.
For me it was because I moved the framework files from another project, grouped inside a folder and it lost the target. So I had to add a target to the classes before I was able to see them in the main project.
For me it was because I used the same name of the framework for a class name. 🤦
I have my own Xcode project which contains some controllers. I want to make its SDK, for use it in another application. In parent application it works as child. Parent app will share some data with my controller and my controller works on it and gives back some result. So kindly guide for me. Examples are - Payment Gateway SDK's. I am looking for the same.
I can see you add tag for swift. In Swift, static libraries are not supported, so you must exclusively use a framework (aka dynamic library) when linking an app to a library. Framework is similar to sdk.
Here are the steps:
1)Create the Framework using New > Project under IOS > Framework & Library, select Cocoa Touch Framework
2)To avoid the "ld: warning: directory not found for option..." goto Library Search Paths in Build Settings for your target and delete the paths.
3)You can't mix Objective-C with Swift so don't even consider adding the Swift-Header bridge file in your code.
4)There are some cases in swift where you need to import code from unexposed Frameworks. I've successfully used the module-map inside the framework to deal with these case.
5)I also select CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES in the Build Settings to solve 'include of non-modular header inside framework module'. That seems to work
6)I make sure that the header file that gets generated is marked as Public (not Project). Click on the file and you'll see the selection in the inspector under 'Target Membership'
Link
Also you can follow this tutorial. Since you have already created project.
Create a framework target, make all source code files a member of the new target, add the new target as target to the podfile. For everything else the tutorial should work. It should help you in understanding the steps.
Build framework
My goal in this was to create an iOS framework that incorporates both Swift and Objective-C that I could use in my development projects. The nature of this framework is that the framework itself is undergoing development. So, it was important that each time I build a project using this framework (I'll call projects using the framework "using" projects for lack of a better term), I wanted to make sure the framework itself was re-built. I wanted this to be a framework because I have a few using apps across which I want to use the same framework code. I have struggled with this for a good hunk of today, and wasted a lot of time on something that should have been, in my thoughts at least, easier. So, I'll share my process.
The first thing to observe (which was certainly not my first observation!) is that you cannot do this using a static library under iOS. Xcode will not let you use Swift in a static framework Try it. Xcode will deny your wishes!
Here's the process I ended up with. The two main issues I had to deal with were: (i) making Xcode link to the framework in the using project without errors, and (ii) getting access to the headers of the framework in the using project. In Apple's enlightened view these two issues are separate. Note the sarcasm. ;).
1) Create a Cocoa Touch Framework using Xcode. I believe this works with Xcode6 and Xcode7. Use:
File > New > Project > iOS > Framework & Library > Cocoa Touch
Framework
I happen to be using Xcode7. (Do not make a Cocoa Touch Static Library-- like I said above, Xcode will not let you incorporate Swift into static libraries).
2) With your Swift classes, make sure the members and functions are public. I've not experimented with this, but it seems that the public attribute is necessary for the members and functions to be visible to users of the framework.
3) Add what ever Swift classes (and Objective-C) you want to your framework.
4) Close that framework project. (The same project can't be open twice in Xcode, and you need to incorporate the framework into your using project next).
5) Open your using project in Xcode. For me this was an existing universal app project. You may be creating a new using project. In any event, drag the .xcodeproj file of your framework project, in the Finder, into your using project.
6) Inside of your using project, open your framework project. And drag the framework file into Embed Frameworks in Build Phases (the Embed Frameworks section wasn't present in Build Phases when I first started my experiments and I don't know yet what magic caused it to appear!).
These steps so far should enable you to build and link without actually yet integrating the usage of your library code.
(I was using https://github.com/RadiusNetworks/swift-framework-example for some of my testing).
7) Now for the coup de grace: Under Build Settings, search for Framework Search Paths. And add in:
${TARGET_BUILD_DIR}/YourFrameworkName.framework
(It seems you do not have to have this marked as recursive).
8) In your Swift code files using the framework, you need to add an import at the top of each file:
import YourFrameworkName
You should now be able build and link using your new library!
9) One more gotcha: Make sure your Deployment Target for your framework matches your destination project. E.g., if your using project builds for iOS7, make sure your framework builds for iOS7 or earlier.
10) Second gotcha (10/23/15): I just learned that it is necessary for my framework to have "App-Swift.h" (the name I use for this) as the Objective-C Generated Interface Header name in Build Settings. When I took this (Objective-C Generated Interface Header) out (trying to fix another issue), I get serveral interesting issues coming up in App-Swift.h. These issues look something like:
"Cannot find interface declaration for NSObject"?
11) Third gotcha (10/29/15): When I tried to upload my first app to iTunes Connect that makes use of this Framework, I got an uploading error. The error read:
ERROR ITMS-90206: "Invalid Bundle. The bundle at
'Your.app/Frameworks/YourFramework.framework' contains disallowed file
'Frameworks'."
Various SO and other posts have run into this kind of error, and the trick for me was, for the Framework target, in Build Settings, to set "Embedded Content Contains Swift Code" to NO. (My app Build Settings had this flag set to NO already).
An example project with most of these steps completed is on https://github.com/crspybits/CocoaTouchFramework.git
Swift consumer -> Swift dynamic framework
Xcode version 10.2.1
Create Swift framework
Create a framework project or create a framework target
File -> New -> Project... -> Cocoa Touch Framework
//or
Project editor -> Add a Target -> Cocoa Touch Framework
Two files will be generated:
Info.plist - Build Settings -> Info.plist File
<product_name>.h - Build Phases -> Headers. It is umbrella header file [About]
Add files .swift
Select `.swift` file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files
Build library - ⌘ Command + B or Product -> Build
Note: Be sure that you build the framework for the same process architecture as the client code.
Find generated output[Build location]
Products group -> <product_name>.framework -> Show in Finder
The framework includes
Info.plist
Modules[About] folder with:
module.modulemap
<product_name>.swiftmodule
.swiftdoc
.swiftmodule
Headers folder with:
files from Headers section. There are public interfaces/definitions
<product_name>-Swift.h - Xcode-generated header file[About]
Swift consumer with Swift framework
Drag and drop[About] the binary into the Xcode project
Embed dynamic binary(or not embed || link a static binary)[Link vs Embed] [Library not loaded]
//Xcode 11
Project editor -> select a target -> General -> Frameworks, Libraries, and Embedded Content -> path to `<product_name>.framework` -> Embed
//pre Xcode 11
Project editor -> select a target -> General -> Embedded Binaries -> path to `<product_name>.framework`
Add Framework Search paths(FRAMEWORK_SEARCH_PATHS)[Module not found] [Recursive path]
Project editor -> select a target -> Build Settings -> Search Paths -> Framework Search paths -> add path to the parent of `<product_name>.framework` file
Import module to the Swift client code[module_name]
import module_name
More examples here
I have built an iOS Swift framework with Xcode.
After writing the code I have build the project and took the .framework file inside the Products folder to test it.
To test the framework have open a new application and drag and drop the .framework file previously built and I added it into the embedded binaries list of my application project.
To import it into my ViewController.swift class I wrote:
import frameworkName
No problem until here, this means that the project sees the framework.
When I try to use a public class inside the framework with:
var x : className?
I get the following error:
'className' is unavailable: cannot find Swift declaration for this class
What does it mean? What is the problem?
When you're referencing a framework in the products directory from your workspace, ensure that the location is "Built Products" and the filename is just the framework name, without any additional path components.
If you're referencing a framework that isn't in your workspace, I would recommend using Carthage instead of copying it directly into your repository. This will make versioning much easier, and will ensure that it is built correctly for both simulator and device.
To actual a self defined framework, u really have to do a lot of things.
Firstly, make sure ur framework is used on right device. It's to say framework can only be used on corresponding device(either one of Simulator, Device and Mac). In other words, if framework A built on simulator, project import framework A can only pass compile and successfully built on simulator.
P.S. if universal version desired, -lipo command is what u need to further explore.
Secondly, during implementing ur framework , make sure all the classes, methods and variables u want use outside start with Public.
Thirdly, check ur project setting Embedded Binaries and linked Frameworks and Libraries do contain ur framework.
I wrote a class in Swift. I want to use this code in two separate iOS app projects that I wrote. Both the shared code and the apps are written in Swift. What is the best way of doing that?
I tried to create both a framework and a library in Swift and then add it as a sub-project to my app. In both cases I could not make the app see the module. I tried to add the shared module to "Target Dependencies" and "Link Binary With Libraries" of the main app's target. No luck - the app still can not see the classes of the shared module.
Using Xcode6 Beta6 at the moment.
Solution
As Konstantin Koval and Heliem pointed out, all I needed is to use public in my class and method declarations, in the shared module. Now all works, both if I use workspace and if I add the module as a subproject.
Update
I just found an excellent easy solution for reusing code between projects in Swift. It is called Carthage (https://github.com/Carthage/Carthage). This is not a plug as I am not affiliated with it in any way, I just really like it. It works in iOS 8+.
Create a new project (iOS Cocoa Touch Framework) for your reusable code
Move your classes to that Framework project
Mark your methods and classes, that should be visible to others as public
Create Workspace.
You can create a workspace on step 1. When you create new Framework project, Xcode will ask you if you want to create new workspace and add that project to workspace. This is the best approach
Add both your project and Framework to the workspace
Select you project target -> General tab. Add Framework and Libraries (add your library here)
When you want to use code from your Library in swift file, import it using import 'LibTargetName'
You can take a more programatic approach by using SWM (Swift Modules): https://github.com/jankuca/swm
It is very similar to npm (node.js package manager) or bower (client-side module manager); you declare your dependencies in a swiftmodule.json file like below. It does not have a central module registry like the two mentioned JS solutions, it only accepts git URLs.
{
"name": "ProjectName",
"dependencies": {
"Dependency": "git://github.com/…/….git"
}
}
…run swm install and have the Dependency module (compiled into a *.swiftmodule binary) ready for import in the .modules/ directory.
import Dependency
And if you prefer to skip Xcode for app development, you can also build your whole app using swm build (more info in the project's readme).
The project is still in early stages but it makes itself useful a lot for me at least. It provides the most clean (and clear) way of creating importable modules.
Here is a video which is very straightforward: http://eonil-observatory.tumblr.com/post/117205738262/a-proper-way-to-add-a-subproject-to-another-xcode
The video is for OS X instead of iOS. But you will get it and figure out the process for iOS.
Let's assume that AppA needs to reused code from SharedProject.
The following process works for me in Xcode 7 Beta:
Create SharedProject. Project type must be Framework instead of Application. You write common code in this project and mark the code as public.
Open AppA in Xcode, open the folder which contains SharedProject in Finder. Drag the .xcodeproj file of SharedProject from Finder and drop it into the root folder of AppA in Xcode Project Navigator.
AppA --> Build Phases --> Link Binary with Libraries. Add SharedProject.
import SharedProject and reuse code from SharedProject!
Edit:
Nowadays I suggest you use Carthage. It's better than the home made solution above.