Closed source is best
source
Cocoaheads Montreal - 11/2016
Slide 2
Slide 2 text
Hi, I'm Romain
· @Palleas on Github, Twitter...
· iOS developer at Mirego
· I love Continuous Integration (it's a disease)
Slide 3
Slide 3 text
Context
· Currently working on a project for a super secret
client I can't tell you about but OMG it's cool
· Working on reusable components for other
teams in the company
· Unable to give them access to the sources (for
now)
Slide 4
Slide 4 text
Creating the framework
Slide 5
Slide 5 text
Creating the framework
let emojis = ["!", """, "#", "$"]
public func nicify(_ string: String) -> String {
let emoji = emojis[Int(arc4random_uniform(UInt32(emojis.count)))]
return "\(string) \(emoji)"
}
Slide 6
Slide 6 text
Building the framework (⌘ + B)
Slide 7
Slide 7 text
Using the framework in a "sandbox"
Slide 8
Slide 8 text
Using the framework in a "sandbox"
Slide 9
Slide 9 text
Using the framework in a "sandbox"
Slide 10
Slide 10 text
Thank You!
Questions ?
Slide 11
Slide 11 text
(Kidding)
Slide 12
Slide 12 text
Running the app on a device (iPhone 7+)
Framework is not working on device !
Slide 13
Slide 13 text
That's not how you release
a framework
Slide 14
Slide 14 text
Solutions ?
· Cocoapods-packager
· Carthage
· Sweat, tears and command line
Slide 15
Slide 15 text
Cocoapods-packager
· Does not seem to play well with Swi!
· Not actively maintained by the community
https://github.com/CocoaPods/cocoapods-
packager
Slide 16
Slide 16 text
Carthage
· Carthage is cool
· Carthage is slow
· Carthage mostly-only works with Github
https://github.com/Carthage/Carthage
Slide 17
Slide 17 text
Sweat, tears and command line
· Customize the whole process
· Learn a lot about frameworks
· Still rely on cocoapods
Slide 18
Slide 18 text
Disclaimer
I have never done anything like
that before
Slide 19
Slide 19 text
The goal
· Build a framework
· Put it on a server somewhere
· Make it available via Cocoapods over HTTPS
Slide 20
Slide 20 text
And CI the shit out of it
Slide 21
Slide 21 text
Let's go back to the
framework we built
Slide 22
Slide 22 text
Digging into the framework
Slide 23
Slide 23 text
Switching to the command line with lipo
Lipo is a command line tool to interact with The
lipo command creates or operates on universal
files.
Slide 24
Slide 24 text
Switching to the command line with lipo
lipo -info BeingNiceIsNice.framework/BeingNiceIsNice
Architectures are: i386 x86_64
Architectures are:
* i386
* x86_64
We need to build for the
devices and the
simulator...
Slide 27
Slide 27 text
... and merge the products
into one framework
Slide 28
Slide 28 text
Building the framework (simulator)
xcodebuild -scheme BeingNiceIsNice
-arch i386
-arch x86_64
-sdk iphonesimulator
only_active_arch=no
Slide 29
Slide 29 text
Building the framework (iphone)
xcodebuild -scheme BeingNiceIsNice
-arch armv7
-arch armv7s
-arch armv64
-sdk iphoneos
only_active_arch=no
Slide 30
Slide 30 text
Merging the frameworks?
Lipo is a command line tool to interact with
universal files. So let's interact.
lipo -create -output "BeingNiceIsNice.framework/BeingNiceIsNice" \
"build/Release-iphoneos/BeingNiceIsNice.framework/BeingNiceIsNice" \
"build/Release-iphonesimulator/BeingNiceIsNice.framework/BeingNiceIsNice"
Slide 31
Slide 31 text
Add the missing slices
· Copy the *.swiftmodule file from the
simulator framework to the new one
cp -r "BeingNiceIsNice.framework/Modules/BeingNiceIsNice.swiftmodule/"
"BeingNiceIsNice.framework/Modules/BeingNiceIsNice.swiftmodule"
What did we do?
· Built the framework for the simulator
architectures
· Built the framework for the devices
architectures
· Merged two frameworks into a single one
Slide 34
Slide 34 text
Now for the fun part:
Fastlane
Slide 35
Slide 35 text
Fastlane
· Fastlane is the easiest way to automate building
and releasing apps (seriously)
· Written in ruby
· 500+ contributors
· Great documentation
· Great community
Slide 36
Slide 36 text
Fastfile
platform :ios do
# ...
desc "Deploy a new version to the App Store"
lane :release do
# release the framework
end
end
Slide 37
Slide 37 text
Packaging with fastlane
· Bump the version number
· Build the project
· Zip the framework
· Make it available via cocoapods
Slide 38
Slide 38 text
Bump the version number
new_version = version_bump_podspec('BeingNiceIsNice.podspec')
set_info_plist_value(
path: 'BeingNiceIsNice/Info.plist',
key: "CFBundleShortVersionString", value: new_version
)
Slide 39
Slide 39 text
Build the project
sh('build-script-from-earlier.sh')
Slide 40
Slide 40 text
Zip the framework
zip(
path: "BeingNiceIsNice.framework",
output_path: "BeingNiceIsNice-#{new_version}.zip"
)
Make it available via cocoapods
Pod::Spec.new do |s|
s.name = "BeingNiceIsNice"
s.version = "0.4.6"
# ...
s.source = { :http => "http://some-server.com/BeingNiceIsNice-#{s.version}.zip" }
s.vendored_frameworks = "BeingNiceIsNice.framework"
end
Slide 44
Slide 44 text
Make it available via cocoapods
pod_push(
path: "BeingNiceIsNice.podspec",
repo: 'secret-podspecs'
)
Slide 45
Slide 45 text
Using the framework
source 'secret-podspecs' # ⚠
target 'BeingNiceIsHard' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
pod 'BeingNiceIsNice'
end
Slide 46
Slide 46 text
Bonus
· Run the test with scan
· Generate the documentation: jazzy
· ...