Category

A cure for the common code: Sharing code between iOS and macOS targets

A cure for the common code

I created an iOS app for my friend Jackie. Then I wanted to add a macOS app. I didn’t want to copy the common code and then have to maintain it in two places; I wanted it in one place that could be shared between the apps. Not surprisingly, this was not straightforward in XCode.

As usual, this is for me to remember what I did. You may find it useful too.

This is what I did.

Introduction

Table of Contents

I didn’t want a separate external framework since the common code is really only for these two apps. So, I created two frameworks inside the project. You will see this a lot if you ask the Google. But then you have two frameworks in two folders. I know, duh. So, I did a few things to make this easier. NB you don’t have to do the following to make this work. It’s just a lot less confusing this way.

Do this

Table of Contents

Create a project. I chose the Empty Cross-Platform template.

Add an iOS Single View app target. (Or any iOS app template)

Then, create a macOS Cocoa app target.

Now you have an iOS app and a Cocoa app.

What if you want a domain object, e.g. Product?, Employee?, Contact?
Where do you put it?

Glad you asked.

Create two framework targets, a Cocoa Touch Framework under iOS, and a Cocoa Framework under macOS.

It will look something like this. The names may be changed to protect the innocent.

Add a new group named SharedSource, Shared, or CommonCode – whatever you like – in the Project Navigator (this also creates a directory on disk).

Move the iOS target’s Info.plist and header file to this group. Remove the “ios” from the header filename. (rename FooIOS.h to Foo.h).

Inside the header, remove the UIKit import. Insert an import for Foundation.

Set the target membership of the header to all app targets and make it public.

Since you moved the Info.plist, XCode needs to find it.
For each app targets go to “Build Settings > Packaging > Info.plist File and make it point to SharedSource/Info.plist

In build settings, change the “Package name” of the shared targets to the name of the group you just made. So, in this example, since I created a group named SharedSource, both targets will have the product name SharedSource.

Optional: For additional checking, you can select “Allow app extension API only” on the General tab for each framework.

You can now delete the shared folders from the project navigator since we’re using the SharedSource directory.

Now create a public class/struct in SharedSource.

Create an instance of it in each app. You’ll need to import whatever you changed the “Package Name” to. (e.g. import SharedSource). Run the apps to see if you missed anything.

Testing the shared code

Table of Contents

Now you can add two test targets, for for iOS and another for macOS to test the shared code.
Go ahead and create tests for your shared domain object in each.

Summary

Table of Contents

If you want to share code between app targets within a single project, you can make it more maintainable by doing this tap dance.

If you got lost, there’s a Github repo.

I might even make an XCode template for this. Want one?

Resources

Table of Contents

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.