Building a Cocoapod with Swift and dependency on Objective-C framework

Romain picture Romain · Mar 7, 2015 · Viewed 8k times · Source

I know there are already a few questions on this theme here on SO, but very few have accepted answers, and I don't think I have found the exact same problem as mine.

I'm building a Swift pod, and in my code I rely on the Google Maps iOS SDK, which is bundled as a .framework file. The project builds OK in Xcode, however I have troubles publishing the lib to Cocoapods.

I managed to have a Podspec file that almost validates using the pod lib lint command. However, now that I've added the Google-Maps-iOS-SDK pod as a dependency in the Podspec file, it fails with the following message:

$ pod lib lint

[!] The 'Pods' target has transitive dependencies that include static binaries: (/private/var/folders/n2/qyjfpk6n7zz_mngtwswlmsy00000gn/T/CocoaPods/Lint/Pods/Google-Maps-iOS-SDK/GoogleMaps.framework)

$

Is this expected? Why can't I add the Google Maps iOS SDK as a pod reference in my own Swift-based pod?

Here's the Podspec:

Pod::Spec.new do |s|
    s.name                  = '(name)'
    s.version               = '1.0.0'
    s.summary               = '(summary)'
    s.platforms             = { :ios => '8.0', :osx => '10.10' }
    s.ios.deployment_target = '8.0'
    s.osx.deployment_target = '10.10'
    s.license               = { :type => 'BSD', :file => 'LICENSE' }
    s.source_files          = 'Sources/*.{h,swift}', '*.framework'
    s.source                = { :git => "https://github.com/(Github repo).git", :tag => "1.0.0" }
    s.requires_arc          = true
    s.frameworks            = "Foundation", "CoreLocation"
    s.author                = { 'Romain L' => '(email)' }
    s.dependency 'Google-Maps-iOS-SDK'
end

If I don't include the Google Maps iOS SDK as a dependency, then pod lib lint fails in the Bridging Header, and complains it cannot find <GoogleMaps/GoogleMaps.h> (file not found).

I'm stuck, and I don't know if it's a bug from Cocoapods 0.36 (still in Beta) or if I'm doing something wrong.

Thanks for your help!

Answer

Romain picture Romain · Mar 9, 2015

I finally found another thread on SO dealing with similar problems: Linker errors in a Swift project with Google Maps for iOS added via CocoaPods.

It appears that the errors were due to a combination of bad Podspec file (on the Google Maps iOS SDK side), and bugs in Cocoapods 0.36 Beta.

It's actually possible to workaround the issues by using @fz.'s revised Podspec file for Google Maps: https://stackoverflow.com/a/28471830/145997. Another article that also was of great interest to understand how the vendored_frameworks setting works in Podspec is: http://codereaper.com/blog/2014/creating-a-pod-with-crashreporter/.

So, to correctly import the Google Maps iOS SDK in a Pod project, first use the following Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
# altered version of Google's Podspec
pod 'Google-Maps-iOS-SDK', :podspec => "https://raw.githubusercontent.com/Reflejo/GoogleMapsPodspec/master/Google-Maps-iOS-SDK.podspec.json"
use_frameworks! # don't forget this!

I'm now able to reference Google Maps classes from my Swift code simply by doing import GoogleMaps. And, to distribute the Pod, my final Podspec now resembles the following:

Pod::Spec.new do |s|
    s.name                  = 'MyPod'
    s.version               = '1.0.0'

    s.homepage              = "https://github.com/..."
    s.summary               = '(pod summary)'
    #s.screenshot            = ""

    s.author                = { 'Romain L' => '(email)' }
    s.license               = { :type => 'BSD', :file => 'LICENSE' }
    s.social_media_url      = "https://twitter.com/_RomainL"
    s.platforms             = { :ios => '8.0' }
    s.ios.deployment_target = '8.0'

    s.source_files          = 'MyCode/*.{h,swift}'
    s.module_name           = 'MyPod'
    s.source                = { :git => "https://github.com/....git", :tag => "1.0.0" }
    s.requires_arc          = true
    s.libraries             = "c++", "icucore", "z" # required for GoogleMaps.framework
    s.frameworks            = "AVFoundation", "CoreData", "CoreLocation", "CoreText", "Foundation", "GLKit", "ImageIO", "OpenGLES", "QuartzCore", "SystemConfiguration", "GoogleMaps" # required for GoogleMaps.framework
    s.vendored_frameworks   = "Dependencies/GoogleMaps.framework" # Put the Google-provided framework in that subfolder of your Pod project
    #s.dependency              'Google-Maps-iOS-SDK' # Careful! this will cause errors if enabled!
end

I am now able to start a new iOS app in Xcode and use the following Podfile to link against my own pod, itself referencing the Google Maps iOS SDK:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'MyPod'
use_frameworks! # do not forget this!

Not that easy, but feasible after all! Hoping Google will soon patch its Podspec file for Swift developments, though.