Make all objective-c files available in swift - ios

Recently all started using swift with my objective-c project. I used below post to make my objective-c files available in my swift files: https://stackoverflow.com/a/24005242/1939409
but it seems that for any class that I want to be available in swift files I should import it in my Bridging-Header. Is there any shorter and simple way to make all of my objective-c files available in the swift files too? I have hundreds files and from now I want to code my project with swift. I want to be able to use my old codes and also proceed with swift. It do not seems good to import all of them in the Bridging-Header.

If you have hundreds of existing headers that you potentially want to make available from Objective-C to Swift, you may want to look at dividing your project into multiple targets: all public headers in a framework will naturally be available to a Swift based dependent target as well. Of course you'll need to put together an umbrella header in that case that will list all public headers of that framework, but clearly declaring a public interface tends to be a worthwhile effort anyway for a project whose source code files range in the hundreds of source code files / headers.

Related

How to combine fat static libraries for use in an iOS application?

I got very confused when reading about static libraries and dynamic libraries and then finally about frameworks, Cocoa Touch Frameworks and Cocoa Touch Static Libraries.
The only thing I understood is that static libraries (frameworks?) are added at compile time, whereas dynamic libraries aren't; they're loaded dynamically during runtime.
Q:
I'd like to add several static libraries (they end with ".a", universal fat binaries, compiled for a bunch of iOS architectures such like armv7 and arm64) to my iOS application. Preferably, if possible, that'd be done by combining all of those libraries together (...to a framework?).
I also want to write a Swift wrapper around those C libraries. This wrapper shall finally be used in my application. However, the wrapper shall not be part of my app, I want a separate project (again, a framework?) for that (can the libraries and the wrapper be combined together?).
What I'm currently trying to do is to write the Swift wrapper.
So I've started with a Cocoa Touch Framework (because I thought that would be the best idea), added the C libraries and headers (actually via a podspec, I don't think that matters though as I could also add them manually), added a bridging header (although some other users reported frameworks don't work with bridging headers, mine does build successfully). Is this the correct way to go?
The first article I read was this one (called "Static and Dynamic Libraries and Frameworks in iOS").
Then, I read lots of articles on stackoverflow about how to compile static libraries, how libraries & frameworks are structured, that frameworks are really just a bundle of libraries and their headers (or so).
I also feel like things have changed over the years at Apple, like they changed the names and possibilities (the Cocoa Touch Framework (is that a dynamic framework?) seems to have been introduced on the release of iOS 8 etc.), which made it even more difficult for me to understand how things work.
Don't get me wrong, I'm just saying this because I want to make clear that I have indeed done some research (quite a lot I think), but I really need some help to get everything right. Basically, I'm just looking for the next step I should take in order to import all those libraries to my app.
There two parts to this:
Creating the framework Mach-O image
Sorting out the headers
The first part should be relatively straightforward. If you create a framework target and add a bunch of static libraries to it, the resulting framework will include all of those static libraries.
The only complication is Objective-C. If any of your static libraries contain Objective-C code, the linker may end up stripping that out. There’s a linker flag, -ObjC, that disables this.
Sorting out the headers is a bit more challenging. Frameworks have their own view of how headers should be organised, and this generally doesn’t line up well with UNIX traditions (which is what you seem to have). The critical question is how your client code uses these headers. If the client code does stuff like:
#include <lib_1/----1.h>
you have to preserve that layout on disk, and there’s no obvious way to do that when working with a framework. OTOH, if you have control over the client code, and can change it to just do this:
#include <MyFramework/MyFramework.h>
you could create an umbrella header in your framework, have it include all of your public headers, and away you go.
This answer was copied from the Apple Developer Forums.

How to add swift framework to Objective-C project

What I want to do is pretty simple : adding Charts framework (here on github) to an Objective-C project.
And I simply don't know how to do this. The readme says : drag charts.xcodeproj into your project, but where exactly ? On the same level ? Inside the project or inside a specific directory (like Products, Frameworks...) ?
Then, the readme says you should import the bridging header but an other documentations I read that this header is only needed when you include Objective-C code into a Swift project and not the other way around.
Then, among different posts or tutorials, some changes in project configuration seem to be needed but I don't know exactly which ones.
This is my first ios development on an already existing project, and I'm pretty sure this is not as complicated as it seems but everything is new to me right now and I'm pretty lost.

Publish my own CocoaPod Framework

I'm about to create a cocoaPod for a small iOS Framework for our customer. I have 2 questions about it.
1) I'm depending on another framework that is also available via cocoaPod. Could it happen that the original author removes the lib and therefor could kill my framework as well or is this secured?
2) I'm using Swift as the language of choice? Let's say one is importing an Obj-C Pod into a Swift project, he needs a bridging header. With the other way around, using a swift cocoapod with obj-c, does the user need to do anything to make this run?
Thanks
Yes, and hopefully the dependent framework doesn't remove his framework (its very rare they do it)
The bridging header is fine unless you use advanced generics (inheritance of a base generic class) as methods might not be available while converting to Objective-C.

Objective C classes within an iOS Swift-based dynamic framework

Situation:
I've got an iOS dyanmic framework written in Swift. I've also got a bunch of classes written in Objective C that I would to use within my Swift classes (some are public, some are private). However, I would like the Objective C classes to not be exposed to projects using my framework.
What I have tried:
Umbrella Header
From what I understand, I should import using #import header.h in my umbrella header file, which is usually FrameworkName.h, and then make sure all the Objective C header files that I wish to include in my Swift classes are to marked as "Public", under Build Phases -> Headers.
Doing this, however, automatically exposes the project using my framework to all the private Objective C classes that the framework uses.
Module Mapping (with separate module)
Because of this, I've looked into using module mapping, which is documented here. I've looked at posts by other users such as this and this, as well as this Github repo.
I successfully got the following working:
//SharedClasses/module.modulemap
module SharedClasses {
}
//SharedClasses/module.private.modulemap
module SharedClasses.Private {
header "header.h"
export *
}
The problem is that in my project (that has this framework imported), this:
import Framework
import Framework.SharedClasses
is allowed, and subsequently the "hidden" Objective C classes are exposed. Perhaps this is just how modules work? Is there a way to make them truly private?
Module Mapping (with framework private module)
Also, I've tried creating a module.private.modulemap file at the root of my framework with the following contents:
explicit module Framework.Private {
header "header.h"
export *
}
and then linking it my target's build settings under MODULEMAP_PRIVATE_FILE. However, when I do import Framework.Private in my framework's Swift classes a compiler error is thrown:
"No such module 'Framework.Private'
I don't understand why this error is occurring.
Module Mapping (with private header)
I noticed that in the Clang docs, a private specifier is mentioned:
A header with the private specifier may not be included from outside the module itself.
My understanding is that since all the Swift classes in my framework are already part of the module Framework, if I create a module.modulemap file with the following:
framework module Framework {
umbrella header "Framework.h"
private header "header.h"
export *
module * { export * }
}
then everything should be working! The Objective C headers are only accessible within the module (i.e. the framework's Swift classes), and aren't exposed to any project using the framework. Cool, but it doesn't work...the compiler just doesn't recognise the Objective C classes. No other errors are thrown, but you can't use the headers, so it's like you didn't include the headers in the first place.
WHY? And what is the private specifier for then?
Soo, reiterating my original question:
Is there any way to import Objective C headers for use in Swift classes, within an iOS dynamic framework, while keeping them private and not accessible from any project using said framework?
Thanks for reading, and sorry for the long post. It's been a long day (and night)...
The quick answer is you can't :) Even if you declare "private" modulemap, it can be always imported by your framework users. Please note, that usually, it is not a concern, especially with open source. You just say "this is an internal module, don't use it".
But (there is always but) - you can have behavior, that effectively works the same - allows you to use your Objective-C classes withing same framework target, without making them public. It works in closed source setup - I have a dynamic framework shipped to external parties, that has a purpose of revealing as less about its construction as possible.
The case a bit too complex to paste everything here. I'm adding a link to my article about the topic. That's a general idea:
Mimic your Objective-C classes with Swift protocols (manual work needed)
In your swift code use these protocols
Expose internally these Swift protocols to Objective-C (manual work needed)
Adopt these protocols by ObjC classes
Create in Swift and expose in ObjC a factory, that will create instances of these protocols
Create in the factory methods, that will allow you to register concrete types, and expose them to ObjC
Register ObjC types from Objective-C code in the Swift factory
Use the factory to instantiate ObjC classes, without actually exposing ObjC to Swift (hurray ;) )
Creating Swift framework with private Objective-C members. The Good, the Bad, and the Ugly
Github example project
You can find some method from this link.
Just create Folder (e.g.PrivateA) with module.modulemap where include all object headers you need to use in your Swift class.
e.g.
module $(ModuleName)Private {
header "header.h"
export *
}
in Swift,
you can use: import $(ModuleName)Private
so, default module exclude these headers when using import $(ModuleName).
From my experiment, test project can also import $(ModuleName)Private, but not found any useful code.
Try this way anyway.

How to create & configure a (mix & match) framework as module?

I've read the "Using Swift with Cocoa & Objective-C" a few times, and I've tried every possible combination of project type (framework, static lib & Swift first, Obj-C first, the lot) but I simply can not get modules to work. I've spent more than 2 hours on this, and it shouldn't be that difficult. Chosing a module name and setting Defines Module to 'yes' doesn't do it.
My goal: to create a module that makes the Apple System Logging service available in Swift code. I've got an objective-c wrapper library lying around that I thought I'd make available as a module to import into my Swift framework, but so far the only luck I've had is it exposing only one of the many classes publically in Swift code. The rest simply aren't available. It's also exposed the 'asl.h' C functions, which is cool, but I have no idea how that happened. I tried creating several sparce frameworks/static libs with the sole goal of making 'asl.h' functions available in Swift. If someone knows how to do that (for any C headers that are part of iOS) without the need to create an Objective-C framework as a module to import into Swift, I'd love to hear about it. Or even just as a framework to make any c headers available in Swift that would be awesome.
So! I create a workspace with an app project in it, and then I create a framework project at the same root level in the workspace as the app project. On the framwork target I set the Product Module Name and Defines Module to 'Yes'. I update my My App's Scheme build target to include the framwork above the app target. I ensure the Link Binary With Libraries build phase contains the framework. Build the app target after adding an 'import MyFramework' line in a Swift file and boom. Failure.
Obviously I've tried clean builds, deleting Derived Data for all projects, hopping one leg and trashing everything and starting again. Someone, anyone, had success with modules yet?

Resources