CocoaPods Plugins

CocoaPods Plugins

Talk about useful CocoaPods plugins and building your own, using cocoapods-packager as an example. Given at CocoaHeads Berlin, July 2014.

9d2ea021919ff81e02d48530aae191bd?s=128

Boris Bügling

July 16, 2014
Tweet

Transcript

  1. COCOAPODS PLUGINS COCOAHEADS BERLIN, JULY 2014 BORIS BÜGLING - @NEONACHO

  2. YO

  3. AGENDA ▸ CocoaPods itself ▸ Useful plugins ▸ How to

    build your own plugin
  4. COCOAPODS

  5. THE DE-FACTO DEPENDENCY MANAGER

  6. None
  7. ▸ Core ▸ cocoapods-downloader ▸ Xcodeproj ▸ CLAide ▸ CocoaPods

  8. CORE spec = Pod::Specification.from_file('CPDColors.podspec') puts spec.name puts spec.version $ ./core.rb

    CPDColors 0.1.0
  9. COCOAPODS-DOWNLOADER def download_head! hg! %|clone #{url} #{@target_path.shellescape}| [...] end def

    download_revision! hg! %|clone "#{url}" --rev '#{options[:revision]}' #{@target_path [...] end def download_tag! hg! %|clone "#{url}" --updaterev '#{options[:tag]}' #{@target_path [...] end
  10. XCODEPROJ wrkspace = Xcodeproj::Workspace.new_from_xcworkspace( 'CPDColors/Example/Demo.xcworkspace') puts wrkspace.schemes $ ./xcodeproj.rb {"Demo"=>"/Users/boris/Projects/CPDColors/Example/Demo.xcodeproj",

    "Pods"=>"/Users/boris/Projects/CPDColors/Example/Pods/Pods.xcodeproj"}
  11. CLAIDE argv = CLAide::ARGV.new(['tea', '--no-milk', '--sweetner=honey']) argv.shift_argument # => 'tea'

    argv.shift_argument # => nil argv.flag?('milk') # => false argv.flag?('milk') # => nil argv.option('sweetner') # => 'honey' argv.option('sweetner') # => nil
  12. COCOAPODS $ pod install Analyzing dependencies Pre-downloading: `DBCamera` from `https://github.com/[...]`

    Downloading dependencies Installing ARASCIISwizzle (1.1.0) Installing Bolts (1.1.0) [...] Generating Pods project Integrating client project
  13. COCOAPODS PLUGINS ▸ Add subcommands to pod, the tool ▸

    Each plugin is a Gem ▸ Same access as built-in commands
  14. USEFUL PLUGINS

  15. $ pod trunk push

  16. $ pod plugins list

  17. ▸ Uses https://github.com/CocoaPods/cocoapods.org/blob/master/ plugins.json

  18. $ pod try BBUSegmentedViewController

  19. $ pod lib docstats

  20. $ pod lib testing

  21. $ pod package ContentfulDeliveryAPI.podspec

  22. $ pod roulette

  23. HOW TO BUILD YOUR OWN PLUGIN

  24. WHAT? ▸ Package a Pod as a static framework ▸

    Including dependencies ▸ All supported platforms ▸ Generate a corresponding podspec
  25. $ pod package AFNetworking.podspec

  26. LET'S GET STARTED

  27. $ pod plugins create cocoapods-packager

  28. TEMPLATE ▸ Just a Git repo, similar to the pod

    template ▸ Reads as much from the environment as possible ▸ Result is installable, shippable
  29. DEFINE THE COMMAND module Pod class Command class Package <

    Command self.summary = 'Package a podspec into a static library.' self.arguments = [['NAME', :required]] [...] end end end
  30. PARSE THE SPEC def spec_with_path(path) if !path.nil? && Pathname.new(path).exist? @path

    = path Specification.from_file(path) end end
  31. RUN def run if @spec builder = SpecBuilder.new(@spec) newspec =

    builder.spec_metadata @spec.available_platforms.each do |platform| build_in_sandbox(platform) newspec += builder.spec_platform(platform) end newspec += builder.spec_close File.open(@spec.name + '.podspec', 'w') { |file| file.write(newspec) } else help! 'Unable to find a podspec with path or name.' end end
  32. FRAGMENT OF SPECGENERATOR s.#{platform.name}.platform = :#{platform.symbolic_name}, '#{platform.deployment_target}' s.#{platform.name}.preserve_paths = '#{fwk_base}'

    s.#{platform.name}.public_header_files = '#{fwk_base}/Versions/A/Headers/*.h' s.#{platform.name}.vendored_frameworks = '#{fwk_base}'
  33. BUILD FOR A SPECIFIC PLATFORM def build_in_sandbox(platform) config.sandbox_root = 'Pods'

    config.integrate_targets = false config.skip_repo_update = true sandbox = install_pod(platform.name) UI.puts 'Building framework' xcodebuild versions_path, headers_path = create_framework_tree(platform.name.to_s) `cp #{sandbox.public_headers.root}/#{@spec.name}/*.h #{headers_path}` Pathname.new(config.sandbox_root).rmtree Pathname.new('Podfile.lock').delete end
  34. INSTALL FROM GENERATED PODFILE def install_pod(platform_name) podfile = podfile_from_spec(platform_name, @spec.deployment_target(platform_name))

    sandbox = Sandbox.new(config.sandbox_root) installer = Installer.new(sandbox, podfile) installer.install! sandbox end
  35. GENERATE THAT PODFILE def podfile_from_spec(platform_name, deployment_target) name = @spec.name path

    = @path podfile = Pod::Podfile.new do platform(platform_name, deployment_target) if path pod name, :podspec => path else pod name, :path => '.' end end podfile end
  36. $ rake install

  37. $ pod package AFNetworking.podspec

  38. ▸ Push your repo to GH ▸ Release as Ruby

    Gem ▸ Send a PR to the cocoapods.org repo
  39. $ git push $ rake release $ gem install cocoapods-packager

  40. !

  41. FUTURE ▸ cocoapods-testing ▸ cocoapods-coverage ▸ cocoapods-playgrounds ▸ ...

  42. THANK YOU!

  43. LINKS ▸ http://www.objc.io/issue-6/cocoapods-under-the-hood.html ▸ http://guides.cocoapods.org ▸ https://github.com/CocoaPods/Rainforest

  44. HTTP://VU0.ORG/CP-PLUGINS @NEONACHO

  45. IT'S A ZERO!