Creating ReactiveSwiftRealm — Part 1

If you’ve already read my previous post you know this was happening. I’m sharing the whole process on how I created the ReactiveSwiftRealm package, including Carthage and Cocoapods support. On this first post I’ll explain how to setup the project to be Carthage/Cocoapods and Submodules ready.

Creating the Xcode Project

First I’ll create the Xcode Project where the package will live.

  • Select File -> New -> Project
  • Choose “Cocoa Touch Library” inside Framework & Library option from the iOS tab
  • Click “Next” and fill the options. Check the “Include Unit Tests” option (because we want to test our package)
  • Select where to save the project
  • Uncheck the “Create Git repository on My Mac” as we’re going to manually setup it
  • Click Create and Xcode will open the project
  • Now go to File -> Save As Workspace and save it in the same directory as the Xcode project using the same name. We’re using a workspace in order tu support dependencies as submodules. They must be in the workspace so Xcode compiles them.
  • Close the Xcode project using File -> Close Project
  • Open the Workspace file from finder or with File -> Open
  • Click on the scheme on the top left of Xcode and select “Manage Schemes”. We should mark our scheme as “shared” so it can be built with Carthage

Time to git

Now we have to setup our git repo. Before we start please navigate to the directory where you saved the project in terminal and then:

  • Run git init to initialize an empty repository.
  • Create a .gitignore file so git doesn’t keep track of dependency files we don’t want to track.

You can use this example standard for Swift projects:

OS X Finder
.DS_Store

Build generated
build/
DerivedData

Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata

Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint

Obj-C/Swift specific
*.hmap
*.ipa

Swift Package Manager
.build/

Carthage
Carthage/Build
  • Run git add .
  • And git commit -m “Project setup”

Carthage and Dependencies

  • First create a file in the project named Cartfile and add our runtime dependencies to it. We’ll add Realm and ReactiveSwift:
github "realm/realm-cocoa"
github "ReactiveCocoa/ReactiveSwift" ~> 1.0

At this point we could add private dependencies (like test frameworks for example) but we don’t need any in this case.

Now we’re going to create an script to make our contributors (and us) a simple way to set tup the project and the dependencies.

  • Create a bin/setup script using terminal (in our project folder)
mkdir bin
touch bin/setup
chmod +x bin/setup
  • Open bin/setup and paste:
!/usr/bin/env sh

if ! command -v carthage > /dev/null; then
printf 'Carthage is not installed.\n'
printf 'See https://github.com/Carthage/Carthage for install instructions.\n'
exit 1
fi

carthage update --platform iOS --use-submodules --no-use-binaries

In this script we check if Carthage is installed and then we run it’s update command to install de dependencies. We use — use-submodules so our dependencies are added as submodules. This allows our possible users to consume the framework outside Carthage if the want. We use — no-user-binaries so our dependencies are built on our system.

With bin/setup ready, let’s run it so that Carthage downloads our dependencies.

  • In terminal run: bin/setup

Now we have Carthage setup ready, save it as a commit.

Adding Dependencies to the Workspace

Now we have our dependencies as submodules, we need to add them to our workspace.

Open Carthage/Checkouts and add each dependency’s .xcodeproj to the root of the workspace. You can just drag them from Finder into the navigator of the Xcode project.

It should look like this:

Link dependencies

  • With our project selected in the navigator (ReactiveSwiftRealm) and ReactiveSwiftRealm selected as Target go to the “Build Phases” tab and expand the “Link binary with Libraries” section.
  • Click the “+” icon and select: ReactiveSwift.framework, Realm.framework, RealmSwift.framework, Result.framework. All from the iOS target (some could include macOS target framworks, double check you include the iOS ones)
  • Click “Add”

Now we’ve finished the Carthage setup, save it with another commit.

Cocoapods

Adding CocoaPods support is really easy. We’ve to create a .podspec file at the root of our project and fill in our project info.

  • Create a file named ReactiveSwiftRealm.podspec
  • Copy and paste the sample below into the file
  • Change it to fit your project details. There are a lot more options available but we don’t need them for this project.
Pod::Spec.new do |spec|
spec.name = "ReactiveSwiftRealm"
spec.version = "1.0.0"
spec.summary = "Add reactive swift functionality to Realm"
spec.homepage = "https://github.com/bitomule/ReactiveSwiftRealm"
spec.license = { type: 'MIT', file: 'LICENSE' }
spec.authors = { "David Collado" => 'bitomule@gmail.com' }
spec.social_media_url = "http://twitter.com/bitomule"

spec.platform = :ios, "9.1"
spec.requires_arc = true
spec.source = { git: "https://github.com/bitomule/ReactiveSwiftRealm.git", tag: "#{spec.version}", submodules: true }
spec.source_files = "ReactiveSwiftRealm/**/*.{h,swift}"

spec.dependency "RealmSwift", "~> 2.2.0"
spec.dependency "ReactiveSwift", "~> 1.0.0"
end

As we want our package to support CocoaPods we’ve to add our dependencies also in Cocoapods.

Once the file is done and saved we can run the pod lib lint command to test that everything is configured properly.

You should get something like:

That’s because we don’t have the repo published yet so pod lint can’t find it. Let’s fix that but we’ll change pod version as 1.0.0 for an empty project seems a bit high.

  • Change spec.version = “1.0.0” to spec.version = “0.0.1”
  • Create the GitHub repo
  • Save commit
  • Add remote repo
  • Push (You may have to use git merge origin/master — allow-unrelated-histories to merge GitHub default files into your local repo)
  • Tag as 0.0.1
  • Push tags

Now try to run pod lib lint again and now you should get:

So here we are, we’re finally ready to start coding, but that would be in the next part. See you there!