Friday, January 8, 2021

Introducing support for Swift Package Manager and Apple Silicon

The latest version of our client SDKs for iOS, macOS, tvOS, and watchOS, version 4.3.0, is now distributed via Swift Package Manager and includes support for Apple Silicon Macs.

At the same time, with this version, we are dismissing CocoaPods as a package manager. The last version available on CocoaPods is and always will be version 4.2.1.

Read on for a quick How-To on switching from CocoaPods to SPM.

Deintegrating CocoaPods

If the only reason you were using CocoaPods in your project was our SDK, good news: from this release on you can deintegrate it and rely only on the integrated package manager of Xcode: Swift Package Manager. On the other hand, if you use CocoaPods for other package dependencies, just skip this section.

When CocoaPods installs a package in your project, it does a lot of changes under the hood. For this reason, simply removing the dependency from your podfile may not be enough. What you need is a full deintegration, which will restore the project to its original state.

To deintegrate CocoaPods simply issue the following command from your project's folder:

pod deintegrate

Done this, you can proceed to delete any remaining files and directories specific to CocoaPods, such as:
  • The <YourProject>.xcworkspace file.
  • The Pods directory.
  • The Podfile and Podfile.lock files.
Et voilĂ , your project is restored to its pristine state. Skip the following section and go to Adding the Lightstreamer SDK with SPM.

Removing the Lightstreamer SDK from CocoaPods dependencies

If you use CocoaPods for multiple package dependencies, where the Lightstreamer SKD is just one of many, you can just remove it from the Podfile and issue the following command from your project's folder:

pod install

CocoaPods will remove the Lightstreamer SDK dependency and leave intact all the others.

Adding the Lightstreamer SDK with SPM

The Swift Package Manager interface can be accessed directly inside Xcode, in the last tab of your project editor. Once there, click on the + button to add a new dependency:


The packages for our SDKs are accessible via GitHub repositories. Specifically:
  • For the iOS SDK: https://github.com/Lightstreamer/Lightstreamer_iOS_Client.git
  • For the macOS SDK: https://github.com/Lightstreamer/Lightstreamer_macOS_Client.git
  • For the tvOS SDK: https://github.com/Lightstreamer/Lightstreamer_tvOS_Client.git
  • For the watchOS SDK: https://github.com/Lightstreamer/Lightstreamer_watchOS_Client.git
Once you have entered the repository URL, a panel will ask you the rule to follow for package updates:


Choose whatever rule you see fit. Just keep in mind that we are not retrofitting old releases, so the first version available is and always will version 4.3.0.

Once all your dependencies are added, the SPM panel will look like this:


Code Changes

None. There are no code changes needed by switching from CocoaPods to SPM. Your code will compile and run exactly like it did before.

If your app includes a watchOS extension, you may encounter the following error when trying to validate an app archive:


This is due to Xcode adding a copy of the Lightstreamer iOS SDK inside the WatchKit extension. You can verify the problem by inspecting the app archive and noting that in the Watch directory there's a copy of the Lightstreamer iOS framework.

If this happens, as a workaround add a Run Script phase at the end of the build of your iOS app target, with the following command:

rm -rf "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Watch/Lightstreamer_iOS_Client.framework"

This command manually deletes the Lightstreamer iOS framework. With this, your app archive should validate with no issues.

We have no idea why this happens. Maybe Xcode support for binary targets in Swift packages is not yet bug-free. If you know more about this issue please let us know.

Under the Hood

To reach this point we had to complete a long and tortuous trek that passed by: rebuilding the SDKs as XCFrameworks, adding support for Mac Catalyst, Apple Silicon, and 64-bit watchOS binaries to our upstream dependencies (in particular we had to create a custom build of the J2ObjC project), packaging all this as a Swift package and finally testing everything from scratch.

Man, it was hard. But we think the result is worth the effort. Note, however, that this will be one of the last versions of our transpiled architecture, as we are working on a full rewrite of the SDKs with Swift, which will be distributed as source code sometime in the future.

Our transpiled architecture has served us (and you all) very well in the past 6 years, but it has become more and more difficult to keep it up to date with the ever-changing Apple ecosystem. It's time to let it sunset as the new Swift SDK takes the stage.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.