I'm trying to generate a swift framework which integrates 2 smaller frameworks developed in objective-c. The idea is to wrap them in order to be able to use them adding only the new framework in a Swift 5 project.
Can I generate it by only adding those 2 frameworks?
Maybe doing some Swift code which does some middle work?
I followed these steps:
1.- Created SDK project.
2.- Inserted both frameworks
3.- In the .h file, added imports to make them public.
4.- Added swift code configurating classes and function as public (most important step)
5.- When swift code was working, deleted in the .h file the imports in order to make both frameworks unaccesibles.
Hope this will help.
Related
Note: I know How to call Objective-C code from Swift, but I don't know below,
I want to use this EsptouchForIOS's Demo in my project. The demo is write in OC, it has a storyboard and controller. I want to know how to integrate the demo in my swift project, and use that storyboard and it's controller in my swift project.
I'll start writing from the very beginning. Suppose you have a project in Objective-C and now you want to continue your project's development in Swift. Follow the below guidelines: (This intends to your specific needs)
First choose to add a new file from File->New->File. In this process select your language as Swift. In the final step here, you will be prompted to Create Bridging Header. Select that:
Now build your project once (⌘+B). You may get an error like this:
Change your target's minimum deployment to the version that Swift supports. (Example in the below screenshot)
To use Objective-C resources in Swift files:
Now that you've got one ProjectName-Bridging-Header.h file in your project. If you want to use any Objective-C class in your Swift files, you just include the header file of that class in this bridging header file. Like in this project, you have ESP_NetUtil and ESPViewController class and their header files too. You want to expose them to Swift and use them later in Swift code. So import them in this bridging header file:
Build once again. Now you can go to your Swift file. And use the Objective-C classes as like you use any resource in swift. See:
N.B: You must expose all the class headers (that you're intending to use later in Swift) in that bridging header file
To use Swift resources in Objective-C files:
Now you may wonder, I've successfully used Objective-C resources in Swift. What about the opposite? Yes! You can do the opposite too. Find your Target->Build Settings->Swift Compiler - General->Objective-C Generated Interface Header Name. This is the header file you will be using inside your Objective-C classes for any Swift to Objective-C interoperability. To know more check here.
Now inside any of your Objective-C class, import that interface header and use Swift resources in Objective-C code:
You will get more understanding from the official apple documentation.
You can checkout the worked out version of your linked project here with Objective-C-Swift interoperability.
So according to your question, you have added an objective C bridge in your swift project using How to call Objective-C code from Swift.
Now, import all headers (.h) files of your objective-c source code (demo project) that you want to direct use in swift file.
For example, your demo project has EsptouchForIOS following header (file with extension .h) files in project source code.
ESPAppDelegate.h, ESPDataCode.h, ESPTouchDelegate.h
import a header file in your bridge, which you want to use in your swift code. Suppose in your swift code you want touch delegate ESPTouchDelegate then write,
#import "ESPTouchDelegate.h"
Here is snapshot of your demo integration in my Test Swift project with bridge
and import statements.
Now, there is function/method in an objective C file getValue
which is used/accessed in swift project/file.
Similarly, you can import as many files (source headers) as you want in bridge and use the same files (source code) in swift.
I have never tried to use objective-c from swift project. But I normally used swift classes from my objective-c project. I usually follow this instructions https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html from apple developer website.
Pretty new to creating frameworks with SPM dependencies. So I made a new framework project, added some of my classes/files as well as a SPM dependency (CocoaLumberjack logger). Framework compiles fine.
When I look for my framework product that I'm planning on embedding into some other project I see that it is in my Products folder. Alongside with it I see CocoaLumberjack module. Inside of my framework there is not much beside the exec file.
When I try to embed my framework into some other projects. Nothing compiles because it says that CocoaLumberjack module is missing.
Does anyone know how to fix this? Am I missing an important step or soemthing?
Well, there are numerous isses you could have faced during importing framework itself. It also depends if you use framework as binary or source code. I assume you were using source code approach as you are the creator of framework. You can however check all approaches here: in this SO question . Lets look at all the steps you need to implement in order to successfully use framework with SPM dependencies in your swift project.
create SPM properly and also link all additional SPM dependencies tutorial here. Make sure all your classes, structs etc. and their coresponding initializer has correct access level property. If you plan to use them outside of the package, use public initializers..
2)Once you created you SPM package, link it to framework. For the sake of this answer I created testFramework and linked one of my custom SPM package called VodApiPackage . This package also contains dependency to another BaseTvApiServicePackage.
I also added TestPrinter file containing simple function for creating error declared in my SPM package. This function servers only for checking that everything is working properly and will be user later. It is also declared public.
import Foundation
import VodApiPackage
public struct TestPrinter {
public init () {}
public func makeTest() {
let x = VodApiError.customErr(msg: "testMsg")
print(x.localizedDescription)
}
}
Open your project and make link to framework, you can also check this nice tutorial. The most important step from tutorial is step 5 and 6. Where you drag .xcproj into your project and link libraries and framework
make sure your library and SPM dependencies are correctly linked in your project. Check sample project below.
Build and test using your framework and its packages:
import UIKit
import testFramework
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
testmodel()
TestPrinter().makeTest()
}
}
This question is a continuation of a previous one I'm currently migrating this (https://github.com/emilwojtaszek/leveldb-swift) library from swift 2 to swift 3/4. Here is the link to my fork https://github.com/lu4/leveldb-swift/tree/MigrationFromSwift2ToSwift3 (please note that the target branch is MigrationFromSwift2ToSwift3)
I was able to resolve (with many thanks to #Ruslan Serebriakov) all of the issues with initial code base and check that the code is running.
However after trying to update LevelDB C code to latest master I got new type of error which I don't understand how to resolve:
Include of non-modular header inside framework module 'LevelDB.c': '/Path/to/Project/leveldb-swift-migration/vendor/leveldb/include/leveldb/export.h'
I've did some research on the internet but the issues described there seem non-related with one I've stumbled on. Here is an image of the issue
Any help is appreciated, thank you in advance!
I'm never 100% certain with mixed language frameworks. But an error like this happens in Swift projects when:
since you cannot use a Bridging Header in frameworks,
you #import a C header in the Foo-Framework.h to expose it so the Swift code, and
the header is not itself marked "Public" to the target.
"Non-modular" seems to indicate "not part of the published module interface". At least with Swift--C mixes, you can only combine both through making the C headers public; no way to import private header files there, which is weird.
Give it a shot: Since you are obviously importing the file in non-Swift code, try to locate the export.h header file in your Xcode project, open the File inspector (⌘⌥1), and ensure public visibility in the framework target:
This issue is because the SDK u are importing is not modular or u can say modulemap file is missing. So make sure modulemap file should be available inside the framework folder. Also make sure that all public headers are listed explicitly in the modulemap. This issue will be resolve 100% if module map file will be include in the third party framework.
I've made a framework that requires the sqlite3 framework. How do I add a Objective-C Bridging Header for my framework that imports sqlite3 into my Swift file?
I already have a bridging header file for my project, but not for my framework.
I found a Objective-C Bridging Header setting in the target Build Settings. It was hidden by default. Check All instead of Basic.
In recent Xcode versions this solution would give the error Using bridging headers with framework targets is unsupported.
The workaround I've been using is to make the C-header public in the file inspector and import it in MyFramework.h like this example:
#import <MyFramework/MyObjectiveC.h>
How to change the C-header to public
Open your C-header and view the inspector by clicking in the upper right corner. To view the file inspector, click the file icon in the upper right corner.
just import your sqlite3 framework in your objective-c bridging file. You then automatically can use it in Swift.
Apple Docs:
Interoperability is the ability to interface between Swift and Objective-C in either direction, letting you access and use pieces of code written in one language in a file of the other language. As you begin to integrate Swift into your app development workflow, it’s a good idea to understand how you can leverage interoperability to redefine, improve, and enhance the way you write Cocoa apps.
One important aspect of interoperability is that it lets you work with Objective-C APIs when writing Swift code. After you import an Objective-C framework, you can instantiate classes from it and interact with them using native Swift syntax.
EDIT: You even can import an Objective-C framework or Swift framework or a mixed-language framework just into your swift file with import yourFramework
Apple Docs:
Importing External Frameworks
You can import external frameworks that have a pure Objective-C
codebase, a pure Swift codebase, or a mixed-language codebase. The
process for importing an external framework is the same whether the
framework is written in a single language or contains files from both
languages. When you import an external framework, make sure the
Defines Module build setting for the framework you’re importing is set
to Yes.
You can import a framework into any Swift file within a different
target using the following syntax:
SWIFT
import FrameworkName
You can import a framework into any Objective-C .m file within a
different target using the following syntax:
#import FrameworkName;
I needed to create a framework (which requires a static library) for a project I'm working on. I used this tutorial to create the framework, then copied the static library into the project and it worked.
But, when I dragged the framework to an iOS project, it shows a ton of errors.
`Undefined symbols for architecture i386:"_OBJC_CLASS_$_SomeClassFromTheStaticLibrary",referenced from:_OBJC_CLASS_$_AnotherClass in MyFramework`
What I think is happening is that the iOS project wants to recompile the framework and it cannot, because it can't locate the static library. All errors disappear if I add the static library to the iOS project. This is what I want to avoid.
Basically I want to have the iOS project -> Framework -> Library instead of having the library in both the project and the framework.
I have tried adding the static library as a resource in the framework, but it didn't work.
I doubt this is possible. When you think about what is happening you will see the problem.
The framework is compiled and the static library is processed so that things like extra symbols are stripped out
The app is now compiled and linked against the framework which may or may not have had the symbols that the app is requiring
I did get this to work if ONLY the framework was using the static library (logical) but I can't find a way to share the code across the framework & the app.
If a symbol is hidden (either via Symbols Hidden by Default/GCC_SYMBOLS_PRIVATE_EXTERN being set to YES or __attribute__ ((visibility ("hidden"))) being applied to certain symbols), then that symbol will be available when statically linking the library, but not when dynamically linking the framework.
Ensure that the static library's symbols are not hidden, and you should be able to access them from your app.
I have followed this link to create custom framework. I have static library inside my framework and it works fine with that.
I have copied his steps in my blog for my understanding along with a script to make it universal.