4. Februar 2019

CocoaPods and the new Xcode build system

If you use CocoaPods to develop libraries for your apps together with the new Xcode build system, there is a bug where Xcode doesn’t pick up the latest version of your framework when building. Apparently this is an issue with the Xcode build process - see radar 41126633 - it works if you switch back to the old build process via File » Workspace Settings » Use Legacy Build. This article documents a better workaround.

I hope this will become obsolete in a later Xcode version - as of Xcode 10.2 and CocoaPods 1.6.1 this is necessary when building Pods.

Reproducing the issue

  1. Create an example Pod (or download the example project here):

    pod lib create HelloPod
  2. Provide some example API, f.e. rename ReplaceMe.swift to ExampleAPI.swift in the Pod and declare a public greet function:

    public func greet() {
        print("hello!")
    }
  3. In the example app, use this API:

    import UIKit
    import HelloPod
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
            greet()
    
            return true
        }
    
    }
  4. Run the app, check the greeting on the console.

  5. Change the greeting text, Run again - you’ll see the greeting is not up to date. That’s the bug.

  6. Clean the project, run again, now its updated.

Why is this happening?

This is discussed in the CocoaPods issue tracker, see #8073, #8151

Long story short: Have a look in the build phases of the project. There is a build phase Embed Pods Frameworks that copies the built framework over to the project. This uses a feature called Input/Output files that’s supposed to only run the script if the affected files have changed:

Xcode Input Files

This seems to be broken in the new build system by this Xcode bug.

As a workaround, make sure you have the latest CocoaPods 1.6:

gem update cocoapods

Then you can add an installation option to your Podfile that disables the usage of input/output files:

use_frameworks!

install! 'cocoapods', :disable_input_output_paths => true

target 'HelloPod_Example' do
  # ...
end

Now when you run pod install again, the build phase will not use the input/output files anymore, the script will be always be run and your framework will always be up-to-date.

Discussion: CocoaPods Google group, Reddit