This guide shows how to build a Braintree framework from Braintree iOS SDK sources. We will be able to install Braintree SDK to any iOS app just by dragging the Braintree.framework
into the project. This method works on iOS 8+ in Objective-C and Swift apps. This method can also be used with Carthage.
First, we need to create a project that will be used to build the Braintree framework.
- File > New > Project > Application > Single View Application.
- Set "BraintreeFrameworkBuilder" as "Product Name". No other name will work with this tutorial.
- Set Objective-C as language.
- File > New > Target > Framework & Library > Cocoa Touch Framework.
- Use "Braintree" as "Product Name". No other name will work.
- Use Objective-C as "Language".
- Remove the automatically generated
Braintree.h
file from the "Braintree" group in project navigator. Select "Move to trash" for it. - Clone braintree_ios repository to some separate directory:
git clone https://github.com/braintree/braintree_ios.git
Those files are temporary so you can clone it into the Downloads or Documents directory, for example.
- Drag the contents of braintree_ios/Braintree/ directory you just cloned into the Braintree group in Xcode. Important: drag not the "braintree_ios/Braintree/" directory, but all the files and folders from it. Your project navigator will look like this:
- Paste the following code into
Braintree.h
file after#import <UIKit/UIKit.h>
line.
FOUNDATION_EXPORT double BraintreeVersionNumber;
FOUNDATION_EXPORT const unsigned char BraintreeVersionString[];
The top of your Braintree.h
file will look like this:
- Add "MessageUI" and "MobileCoreServices" frameworks into "Braintree" target > "Build Phases" > "Link Binary With Libraries".
- Add
-ObjC
into "Braintree" target > "Build Phases" > "Other Linker Flags".
Set a lower iOS deployment target version if you want to use the Braintree framework in an app that supports earlier versions of iOS. I set it to version 8.0. Note that this Braintree framework will work only on iOS 8 and newer.
- Use lower iOS version in Project settings > Info > iOS Deployment Target.
Let’s try using BraintreeSDK in View Controller.
- Add
#import <Braintree/Braintree.h>
toViewController.m
file in your "BraintreeFrameworkBuilder" app of the same project. - Build the project. You will see
'Braintree/Braintree.h' file not found
error.
We need to make some header files in the Braintree framework public.
- Change "Target Membership" of Braintree.h to "public".
- Build again. You will see a new error:
'Braintree/Braintree-API.h' file not found
. FindBraintree-API.h
file and make it "public". I useCommand-Shift-o
shortcut in Xcode to find files quickly. - Now build again. You will see
File not found
error message for yet another file. Find the file and make it "public" - Repeat "Build > Find > Make public" steps until there are no more errors.
- In addition to
File not found
error you will also seeInclude of non-modular header inside framework module …
errors. Make those complaining files "public" as well.
- I went through 33 header files in total, the work took about 10 minutes.
- Select Braintree target > Build Phases.
- Click on "+" icon and select "New run script phase"
- Paste the following code into the script text area.
# ---- Copy UI ----
build_dest="${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}"
dest="${build_dest}/Braintree-UI-Localization.bundle"
mkdir -p "${dest}"
# ---- Copy drop In ----
cp -r ${SRCROOT}/Braintree/UI/Localization/*.lproj "${dest}/"
dest="${build_dest}/Braintree-Drop-In-Localization.bundle"
mkdir -p "${dest}"
cp -r ${SRCROOT}/Braintree/Drop-In/Localization/*.lproj "${dest}/"
- Create
scripts
directory in your project root. I do it from a Terminal.
cd <your BraintreeFrameworkBuilder project directory>
mkdir scripts
- Add two script files to
scripts
directory: build_framework.sh and common.sh.
cd scripts
curl -O https://raw.githubusercontent.com/exchangegroup/braintree-framework-builder/master/scripts/build_framework.sh
curl -O https://raw.githubusercontent.com/exchangegroup/braintree-framework-builder/master/scripts/common.sh
Your scripts directory will look like this in relation to your project directory:
- Add 'execute' permissions to those two scripts.
chmod 764 build_framework.sh
chmod 764 common.sh
- Run
build_framework.sh
script from the Terminal:
./build_framework.sh
It will build a universal framework into "mybuild/Braintree.framework". When build finishes
it opens a Finder containing Braintree.framework
file.
In addition to the executable code the framework contains two bundles with localization strings. That's where frameworks are handy - they can contain assets.
If you have problem building the framework, check PROJECT_NAME=BraintreeFrameworkBuilder
line in build_framework.sh
. This variable value needs to be the same as the name of your project.
Finally! You can use the Braintree.framework
file in any of your apps.
- In your app, select its target, "General" tab and look for "Embedded Binaries" section.
- Drag the
Braintree.framework
file you built in previous step into "Embedded Binaries".
Alternatively, if you are using Carthage you can add your braintree builder repository to your app's Cartfile. There is no need to do the previous step of building the Framework - Carthage will build it for you.
github "your braintree builder repository"
- Add
#import <Braintree/Braintree.h>
into your view controller. - Instantiate a Braintree object in your view controller:
[[Braintree alloc] init];
My view controller code looked like that:
#import "ViewController.h"
#import <Braintree/Braintree.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[Braintree alloc] init];
}
@end
- Run the app. If it runs it means that your Braintree SDK integration is done correctly.
To use Braintree SDK in a Swift app you will need to import its header in a bridging header.
- To create a bridging header, select File > New > Source > Objective-C File. Name it anything you want, it will be a temporary file.
- Click "Yes" in the next dialog that asks if you would like to configure a bridging header.
-
Xcode will create a header file with a name like
MyApp-Bridging-Header.h
. -
Import Braintree in your bridging header file:
#import <Braintree/Braintree.h>
- Instantiate a
Braintree
object in your view controller to check if it's working.
import UIKit
class ViewController: UIViewController {
var braintree: Braintree?
override func viewDidLoad() {
super.viewDidLoad()
braintree = Braintree()
}
}
- Run the app to check if it's working.
Check this demo app that shows how to use Braintree drop-in UI in a Swift iOS app.
You may get the following error when building the app. It may happen if other targets in your app (like a test target) is importing code form the app target.
framework not found Braintree for architecture x86_64
To fix the error:
- Select "Braintree.framework" in the project navigator.
- Enable its "Target Membership" in your other target(s).
We have built the Braintree.framework. This is what I think is good about it:
- We can now use Braintree in any Swift or Objective-C iOS app by just dragging the
Braintree.framework
file into "Embedded Binaries" section. - Your app will build quickly because Braintree source files have been already built into the framework.
These are the materials I used to make this guide.
-
Swift demo app with Braintree drop-in UI: https://github.com/exchangegroup/UsingBraintreeDropInUIInSwiftDemo
-
"Building Modern Frameworks" WWDC 2014 video: https://developer.apple.com/videos/wwdc/2014/#416
-
Xcode 6 iOS Creating a Cocoa Touch Framework: http://stackoverflow.com/a/26691080/297131
-
Creating a static library in iOS tutorial: http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial
-
Script for building iphoneos and iphonesimulator schemes and combining them into a universal framework: https://gist.github.com/cconway25/7ff167c6f98da33c5352