Include Pod's Bridging-Header to Build Settings of Project's Target? - ios

I created an objective-c pod with two files:
Source/SomeViewController.h
Source/SomeViewController.m
I also created a bridging header in the pod:
Source/Bridging-Header.h
with the content:
#import "SomeViewController.h"
My podspec looks like this:
Pod::Spec.new do |s|
s.name = 'TestLib'
s.version = '0.0.1'
s.license = 'MIT'
s.ios.deployment_target = '7.0'
s.source_files = 'Source/*.{h,m}'
s.requires_arc = true
s.xcconfig = { 'SWIFT_OBJC_BRIDGING_HEADER' => 'Source/Bridging-Header.h' }
end
I created a demo project did pod init and inserted my pod. Then after pod install I get the following output:
Installing TestLib 0.0.1 (was 0.0.1)
Generating Pods project
Integrating client project
[!] The `TestLibProject [Debug]` target overrides the `SWIFT_OBJC_BRIDGING_HEADER` build setting defined in `Pods/Target Support Files/Pods-TestLibProject/Pods-TestLibProject.debug.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
[!] The `TestLibProject [Release]` target overrides the `SWIFT_OBJC_BRIDGING_HEADER` build setting defined in `Pods/Target Support Files/Pods-TestLibProject/Pods-TestLibProject.release.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
When I open my TestLibProject.xcworkspace file I see that the pod was installed correctly but the bridging header from the pod is not installed correctly. I my Swift project I tried to do:
let vc: SomeViewController
This gives an error because the bridging header from the pod ist not installed.
How do I have to configure the podspec in order to get the bridging header of the pod being installed correctly?

Podspecs build frameworks, and frameworks cannot include bridging headers. If you want to import non-modular code into a Swift framework, you'll need to use a custom module map, instead, e.g. at MyLib/module.modulemap:
framework module MyLib {
umbrella header "MyLib.h"
// Load an SDK header, e.g. CommonCrypto.h
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
export *
module * { export * }
}
Once there, you can specify the custom module map both in your Xcode project (either as the MODULEMAP_FILE setting in an .xcconfig file, or as the Module Map File of your target's Build Settings.
Now, the final piece of the puzzle: the podspec. You need to set the module_map:
Pod::Spec.new do |s|
# …
s.module_map = 'MyLib/module.modulemap'
end
The above is how SQLite.swift distributes itself, both as a general framework and as a pod.
Edit: Seems like I missed the point of the original question, as was clarified in this thread. The OP wanted to use a pod framework's bridging header to automatically load itself into the installing project's Swift code. This isn't possible. Even if Swift frameworks did support bridging headers, they would only be able to load Objective-C/C code (i.e. private framework code) into the framework's Swift code.

Related

cocoa podspec subspec swift compatibility header file not found

Pod lib could not find mymodule-swift.h header.
One of my objc.m file imports following code.
#import <devillogin/devillogin-Swift.h>
Xcode build is success. Everything is ok.
But when I'm trying to distribute with pod, following error printed.
pod lib lint mymodule.podspec
fatal error: 'devillogin/devillogin-Swift.h' file not found
My mylib.podpec is as following
Pod::Spec.new do |s|
...
s.subspec 'DevilLogin' do |devilLogin|
devilLogin.source_files = 'devillogin/devillogin/source/**/*.*'
devilLogin.public_header_files = 'Pod/Headers/*.h'
devilLogin.dependency 'devil/DevilCore'
devilLogin.dependency 'KakaoSDK'
end
end
Is there any syntax in podspec for mylib-swift.h ?
I'm answering to myself.
I found that the issue only occur when it is in the subspec.
No problem with root podspec.
Consequently I couldn't find way to let my pod-subspec import "XXX-swift" header.
But I found workaround.
I referenced firebase frameworks which use many pod-subspecs.
https://github.com/firebase/firebase-ios-sdk
Just watched root pod spect and 1 subspec.
It distributes sub-specs as root pod spec which is success with 'XXX-swift.h' header
And each subspecs depend on it above.
There is Firebase.podspec and FirebaseDynamicLinks.podspec.
FirebaseDynamicLinks is standalone independent frameworks.
But it is actually subspec.
Firebase podspec defines subspec like followings.
This is workaround
s.subspec 'DynamicLinks' do |ss|
ss.dependency 'Firebase/CoreOnly'
ss.ios.dependency 'FirebaseDynamicLinks', '~> 7.9.0'
end
It defines DynamicLinks as subspec and define dependency on independent FirebaseDynamicLinks.
Done

How to import Alamofire/AFNetworking in my custom cocoapod

How do I include Alamofire (a web request pod like AFNetworking) in my cocoapod source files? I have a service in my cocoapod that needs to make web requests using Alamofire, my cocoapod doesn't seem to have a podfile that I can see, so I don't know how to add the dependency to my cocoapod.
I am creating a cocoapod using pod lib create The build fails whenever I go to import Alamofire in any of my files. In a normal project, I'd just add Alamofire to my podfile, but this is a cocoapod, so I can't figure out where to add the dependency, or how to get it to build successfully.
I followed the guide here but it doesn't say anything about importing another pod into my cocoapod's files.
My directory structure looks like this:
MyLib.podspec
Example/
MyLib example project
Pod/
Source files for my cocoapod
If your pod depends on other pods you can define that in your pod's .podspec file. You can add dependencies there.
Have a look at RealmSwift's podspec file as an example. The RealmSwift pod has a dependency to the Realm pod. This is defined in RealmSwift.podspec:
Pod::Spec.new do |s|
s.name = 'RealmSwift'
s.version = `sh build.sh get-version`
s.summary = 'Realm is a modern data framework & database for iOS & OS X.'
s.description = <<-DESC
The Realm database, for Swift. (If you want to use Realm from Objective-C, see the “Realm” pod.)
Realm is a mobile database: a replacement for Core Data & SQLite. You can use it on iOS & OS X. Realm is not an ORM on top SQLite: instead it uses its own persistence engine, built for simplicity (& speed). Learn more and get help at https://realm.io
DESC
s.homepage = "https://realm.io"
s.source = { :git => 'https://github.com/realm/realm-cocoa.git', :tag => "v#{s.version}" }
s.author = { 'Realm' => 'help#realm.io' }
s.requires_arc = true
s.social_media_url = 'https://twitter.com/realm'
s.documentation_url = "https://realm.io/docs/swift/#{s.version}"
s.license = { :type => 'Apache 2.0', :file => 'LICENSE' }
# ↓↓↓ THIS IS WHERE YOU DEFINE THE DEPENDENCY TO ANOTHER POD ↓↓↓
s.dependency 'Realm', "= #{s.version}"
# ↑↑↑ THIS IS WHERE YOU DEFINE THE DEPENDENCY TO ANOTHER POD ↑↑↑
s.source_files = 'RealmSwift/*.swift'
s.prepare_command = 'sh build.sh cocoapods-setup without-core'
s.preserve_paths = %w(build.sh)
s.pod_target_xcconfig = { 'SWIFT_WHOLE_MODULE_OPTIMIZATION' => 'YES',
'APPLICATION_EXTENSION_API_ONLY' => 'YES' }
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
s.watchos.deployment_target = '2.0' if s.respond_to?(:watchos)
end
You should check out the AlamofireImage project. It uses Carthage to add the Alamofire submodule to the project. The Alamofire project is then added as a dependency to the AlamofireImage project.
The AlamofireImage.podspec also demonstrates how to add Alamofire as a dependency for CocoaPods. If you follow the AlamofireImage project structure exactly, you'll be up and running in no time. Here are some useful commands to get you going:
Cartfile
github "Alamofire/Alamofire" ~> 3.0
Checkout through Carthage
brew update
brew doctor
brew install carthage
// or
brew upgrade carthage
carthage update --no-build --use-submodules
Hopefully that helps!
If you have created a pod and in your .podspec file you are trying to add a dependency (like Alamofire, RealmSwift..) after that you should go to the Example/.. folder and do a pod install to make the dependencies required from the .podspec of your custom pod visible to the .swift files in your custom pod/framework.
A typical example of a pod project folder hierarchy would be:
- MyLib/
- _Pods.xcodeproj
- Example/ // <-- do a pod install under this folder in order to get the dependencies declared in your .podspec
- Podfile
- MyLib.xcodeproj
- MyLib.xcworkspace
- MyLib/
- Classes/ // <-- folder with pod specific logic that also uses Alamofire
- Assets/
- MyLib.podspec // <-- your podspec with dependencies (Alamofire..)

Swift compiler error: Header not found

I started a "Cocoa Touch Static Project" with a Cocoa Pods dependance.
Podfile:
platform :ios, '8.4'
inhibit_all_warnings!
target 'project' do
pod 'libPusher', '~> 1.6'
end
target 'project' do
end
A workspace has been created by the command "pod install".
Then I created un swift project on this workspace and I created a Bridge header between this swift project and my Objective-C library project.
My swift project configuration:
//:configuration = Debug
SWIFT_OBJC_BRIDGING_HEADER = demo/demo-Bridging-Header.h
//:configuration = Release
SWIFT_OBJC_BRIDGING_HEADER = demo/demo-Bridging-Header.h
When I compile my swift project, I obtain this error:
demo-Bridging-Header.h:5:9: In file included from /Users/XYZ/Projets/iOS/project/library/demo/demo/demo-Bridging-Header.h:5:
project.h:10:9: 'Pusher/PTPusherDelegate.h' file not found
Failed to import bridging header '/Users/XYZ/Projets/iOS/project/project/demo/demo/demo-Bridging-Header.h'
Do you know why the swift compiler doesn't found header file and how can I fix it?
• Did you run pod install ?
Installing SocketRocket (0.3.1-beta2)
Installing libPusher (1.6)
• Did you open demo.xcworkspace (close Xcode project, open Xcode workspace)
If so, were is the correct demo-Bridging-Header.h content:
#import "Pusher.h"
#import "Pusher/PTPusherDelegate.h"

Using dependency in swift module (framework)

I am trying to create a swift module (Cocoa Touch Framework) with reusable code inside the environment set up by cocoa pods which includes third party libraries written in Objective-C (namely here Restkit).
Unfortunately I am not able to use Restkit in the module I create.
Here's what I did to create the module:
File -> New target: Cocoa Touch Framework, Language: Swift, Project: MyProject, Embed in Application: MyProject
In the "Info" tab of the project settings in the "Configurations" section I define the Pods.debug and Pods.release xcconfig file for my newly created target.
In the header file, which Xcode automatically created for me, networkModule.h, I add the following line:
#import <RestKit/RestKit.h>
Result: When trying to compile I get the error "include of non-modular header inside framework module 'networkModule'"
I have set the flag for "Allow Non-modular Includes in Framework Modules" to YES in the build settings for the Project Target and the Module/Framework target.
I went to the Cocoa pod project and have tried setting the visibility of the RestKit.h Header file to "Public" in the target membership (which of course is not a good solution to mess with the cocoa pods environment)
I am not able to compile. I still get the same error.
Is it possible in the first place to create a Cocoa Touch Framework with dependencies to a cocoa pod managed framework?
Btw. My first idea of creating a private cocoa pod didn't work out as well, as it doesn't seem to be supported, although I am using the prerelease of cocoa pods 0.36 with support for swift.
You should be able to make your won private Pod. You just need to make a podspec for it. Here is an example of one.
Pod::Spec.new do |s|
s.name = "Commons"
s.version = "1.0.0"
s.summary = "Common code for my iOS projects."
s.license = {:type => 'Commercial', :text => "Copyright (c) Dan Leonard(Or Your Name?). All rights reserved." }
s.source = { :git => "https://github.com/PATHTOPOD", :tag =>
s.version.to_s }
s.homepage = "https://github.com/PATHTOPOD"
s.requires_arc = true
s.ios.deployment_target = '9.0'
s.subspec 'Core' do |ss|
ss.source_files = '*.swift'
end
s.subspec 'Menu' do |ss|
ss.source_files = 'Menu/*.swift'
ss.resources = ['Menu/*.storyboard', 'Menu/*.xcassets']
ss.dependency 'Alamofire'
end
end
Then Inside your project you just have to do pod init open your podfile that was just created and add this
source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'YOURPROJECT.xcodeproj'
platform :ios, '9.0'
use_frameworks!
pod 'Commons', git: 'https://github.com/PATHTOPODPROJECT'
#pod 'Commons', :path => '/Users/YourUser/Path/To/Project/commons'
pod 'KeychainSwift'
pod 'SQLite.swift', git: 'https://github.com/stephencelis/SQLite.swift.git'
Now in this example Podfile Commons is stated twice the second is commented out. If you uncomment it and comment out the first then do pod install in your projects folder from the terminal. This will make a DevelopmentPod which is a pod that is local. This way you can make changes to the pod locally within Xcode. No switching and pod installing every time you make a change.
You will import the pod just like any other by putting
import Commons not #import <Commons/Commons.h> That is how you do it in Objective C not Swift
Once you have a working version commit it to git hub and point your project to the the github version.
Hope this helps.

Cocoapods importing a framework to source code

In my cocoapod for iOS, I have a essentially items:
Open-source classes (.m & .h files)
MyFramework.framework (.framework directory, header files, and .bundle for resources)
One of the open-source classes calls import <MyFramework.MyFramework.h> so it can use the components of MyFramework in its implementation. But because of this, I'm having trouble getting the podspec to pass the spec lint test (pod spec lint MyCocoapod.podspec). When I run the spec lint validation, it says:
ERROR | [iOS] [xcodebuild] .../MyFile.h:54:9: fatal error: 'MyFramework/MyFramework.h' file not found
While investigating, I noticed that the podspec does pass the spec lint validation if I remove that open-source class in the podspec's source_files section, s.source_files = 'MyFiles.{h,m}'. Any idea why my class can't import my custom framework during the spec lint validation?
The relevant code in the podspec looks like this:
s.preserve_paths = 'myframework/MyFramework.framework'
s.frameworks = 'Foundation', 'MyFramework'
s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(SRCROOT)/myframework/' }
s.public_header_files = 'MyFramework.framework/Headers/*.h', 'SourceCode/*.h'
s.source_files = 'SourceCode/*.{h,m}' # Crashes here - Source_file imports MyFramework.h. If I take this out, it passes spec lint validation
EDIT This process is now entirely handled by the vendored_frameworks option. This handles preserving the paths, the framework search paths, and linking to the project.
To include a framework you can use:
s.vendored_frameworks = 'path/to/SomeFramework.framework'
To include bundle files do:
s.resources ='path/to/SomeBundle.bundle'

Resources