Swift Embedded Framework That Depends on Swift Package - ios-app-extension

My iOS app follows the "Photos Extension" template:
- A standalone, "container" app
- A Photo Editing extension, which is deployed by embedding it within the app above.
As suggested by Apple, code that is shared by both the app and the extension is gathered in a "core" cocoa framework that is embedded in the app, and to which both the app and the extension are linked.
So my Xcode project contains three targets:
The Framework target,
The Photo Editing Extension target, which links to the Framework but does not embed it, and
The App target, that embeds the Extension binary and the Framework binary, and links to both.
So far, so good.
Furthermore, the framework, the app, and the extension depend on two libraries MyLibraryA and MyLibraryB I have on Github (and in turn, MyLibraryA depends on MyLibraryB).
I originally set the dependency on MyLibraryA and MyLibraryB using Carthage, and everything was working fine.
Then, I decided to migrate my libraries A and B to Swift Packages.
I removed all Carthage-related settings in project and targets, framework search paths, etc. to make sure the Swift Package versions of my libraries are referenced and not the cached Carthage builds. I also deleted the Carthage directories (checkouts and build).
The Problem
When I build the shared/embedded Framework target, there are no issues.
But when I try to build either the App or App Extension targets, I get an error pointing to the shared frameworks Swift header (MyFramewor-Swift.h):
// ...
#import CoreGraphics;
#import CoreImage;
#import Foundation;
#import PhotosUI;
#import UIKit;
#import MyLibraryA; <-- Module 'MyLibraryA' Not Found
// ...
And the resulting:
Could not build Objective-C module 'MyFramework'
I know frameworks that are distributed as binaries cannot depend on Swift packages, but this embedded framework is compiled locally from source code and then embedded.
Perhaps there are some changes I can make to my setup on Xcode to get it to work?
I tried changing Enable Modules (C and Objective-C) to No in the Build Settings for the Framework target, to no avail.

You can currently set Install Objective-C Compatibility Header to No in Build Settings for modules that require a Swift Package dependency.
This's probably due to "Swift Packages" being "Swift", but still looks like a bug to me.

Related

How to exclude standard but unused libswift*.dylib's from macOS app bundle and reduce bundle size

When I build my simple menubar cocoa application written in Swift 4 with Xcode 9, a lot of libswift*.dylib libraries are linked/downloaded/embedded into .app bundle,into Frameworks folder as seen below:
I am only using import Cocoa and import Foundation in my project, and some #objc functions as selector to timer functions. I really don't think my very simple menubar app would need some 3D rendering Metal library functions or any SwiftOnoneSupport, so I would like them to be removed from the .app bundle. (Same libraries are also included in the helper app for launch at login feature, which makes even the helper app over 10 MB)
I would have thought Xcode would just copy whatever is neccessary by default actually. Some similar questions were asked here and here but I don't think there is a fulfilling and up-to-date answer to both.
What I have tried so far
I set ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES to NO in Build Settings. It doesn't seem to have any effect.
I set LINK_WITH_STANDARD_LIBRARIES to NO in Build Settings. It ruined everything and couldn't make it build even though I tried to add some frameworks(Cocoa, Foundation) on my own under Linked Frameworks and Libraries section.
Simply put, it's not possible to exclude the standard libraries that Swift automatically includes with an app and expect it to work. Currently any application created with Swift bundles its own version of the Swift Dynamic Library. Swift doesn’t live on the OS, rather it lives within each app bundle. What this means is that any app that is using Swift 4.1 for example bundles in the Swift 4.1 Dynamic Library (containing the 4.1 ABI), and so forth.
One of the things on the Swift project roadmap is to eventually have ABI Stability. If Swift becomes ABI Stable, Swift will live within the OS and it’s ABI will be compatible with every version of Swift.
From iOS v12.2 ABI[About] Stability for iOS is on. That is why your target will not include Swift standard library[About] because it is a part of OS

Adding swift framework extracted from IPA

I'm trying to run an IOS app created by another dev that is using a cocoapod from a private repository I have no access to. I managed to extract the .framework bundle from the IPA and add it to the xcode project but it is not being recognized (I get "No such module").
Is it possible to do what I'm trying to achieve?
So far, what I've tried:
build it in release as I guess the framework in the IPA is in release
add the .framework as embedded binary
add the .framework as Linked Framework and Libraries
copy the .framework to ~/System/Library/Framework
update the Frameworks Search Path including $(SRCROOT), recursive, hardcoded paths, etc.
change the .framework location to "Relative to Build Products"
Thanks!
It wasn't that much easy to get the frameworks used in project from ipa file.
Whenver the application runs for first time, also when you archive your application, all the linked .frameworks will get converted to .dylib that is dynamic libraries.
What is static library - a unit of code linked at compile time, which does not change.
What is dynamic library - a unit of code and/or assets linked at runtime that may change.
Framework - A framework is a hierarchical directory that encapsulates a dynamic library, header files, and resources, such as storyboards, image files, and localized strings, into a single package. Apps using frameworks need to embed the framework in the app's bundle.
Dynamic Library
A dynamic lib file is just resides inside the framework folder.
Following is a description from apple documentation
Dynamic libraries outside
of a framework bundle, which typically have the file extension .dylib,
are not supported on iOS, watchOS, or tvOS, except for the system
Swift libraries provided by Xcode.
Ref: Documentation
So you cannot simply copy a .dylib to xcode bundle and just use it. There is some sort of security too.
Another approch
It is possible to decompile the source code from .ipa files. You will get idea from below links.
SO Question regarding decompiling of ipa file
Decompilation Possibility
It seems that when an app is archived for distribution, the Headers and Modules folders are removed from the .framework bundle.
The Header folder contains the .h headers for Objective-C and the Modules folder contains the .swiftmodule equivalent files for Swift.
Without these files you have no public API to consume for the framework binary, so unfortunately this renders the frameworks unusable without reverse engineering.

Adding CommonCrypto to custom Swift framework

I’m building a Swift framework which seems relatively simple. Then I needed to import CommonCrypto.
In the framework’s .h file I added the line
#import <CommonCrypto/CommonCrypto.h>
and included Security.framework in Link Binary with Libraries for the framework’s target.
When I build I get the following build error:
Include of non-modular header inside framework module ‘MyKit'
I’ve tried changing the Allow Non-modular Includes In Framework Modules to YES and NO and tried every combination for both the framework target and the project with no luck.
The MyKit.h’s Target Membership is set to Public and is ticked for MyKit too.
In Xcode 10.0 you'll be able to import CommonCrypto. As a work around I suggest inverting that dependency with a protocol and importing CommonCrypto in your framework client.

Linking libz.dylib and libsqlite3.dylib in Xamarin iOS Project

I created a Xamarin iOS binding project that requires the following frameworks:
SystemConfiguration.framework
CoreTelephony.framework
libz.dylib
libsqlite3.dylib
I added the following line in my iOS binding project to the linkwith.cs file:
Frameworks = "SystemConfiguration CoreTelephony"
This seems to work correctly and tells that project to include these frameworks when binding. From what I have read, it sounds like the remaining 2 libraries need to be added as linker flags in the project referring to the DLL generated from my iOS binding project. So I created a test app, imported the DLL, and now need to add the linker flags but my project cannot find the right libraries.
My linker flags in Xamarin Studio are as follows:
-gcc_flags "-lz -lsqlite3.0"
When I build my Xamarin test app I get a few errors regarding the frameworks that cannot be found. Are there additional flags that need to be linked or do I need to do some additional configuration in my iOS binding project?
I found a great resource: http://ipixels.net/blog/specify-extra-gcc-flags-for-native-library-binding-in-xamarin-ios/
I needed to add LinkerFlags = "-lz -lsqlite3.0" to my .linkwith.cs file. I then rebuilt the library to generate a new DLL and added this to my test app. The test app builds correctly then.
If you are creating your bindings for a cocoapod using sharpie:
sharpie pod init ios nameOfCocoaPod
sharpie pod bind
you get a nameOfCocoaPod.framework file and .cs-binding files.
The nameOfCocoaPod.framework file should be added to your binding project under Native References. To change e.g. Frameworks or LinkerFlags, right-click and open properties.

Share an Xcode project as a static library for other people to use in emulator. How do you use an AppDelegate from a .a static library file in Xcode?

I want to share my Xcode project as a static library for other people to use in the xcode emulator (giving them as little raw source code as possible). How do you use an AppDelegate from a .a library file in Xcode or UIBuilder?
I copied the main Window.xib file to a new project and included all of the other source files in a static .a library that I thought I would be able to invoke somehow. What do I have to do to launch my main product that is compiled into the .a library from a brand new Xcode project that is including that library?
You'll have to link to the static library. Include it in your new Xcode project, and then in the target for the application, go to the General tab and set the library as linked. You'll probably want to copy it into your new project's bundle (in the Frameworks directory), using a Copy Files build phase. You'll also need to reference the header files for the static library for avoid warnings.
This is a much better solution found in someone else's question:
iOS Question. Can I distribute the Xcode simulator versions of my app?

Resources