Adding 3rd Party Code to Xcode Projects

Adding 3rd Party Code to Xcode Projects

My talk from iOSCon 2014. Covers adding code directly, managed by Git Submodules and CocoaPods.

The video for this talk is available at https://skillsmatter.com/skillscasts/5058-third-party-code

F28c4835c9e2277b6e04b86574532a2d?s=128

Abizer Nasir

May 15, 2014
Tweet

Transcript

  1. ADDING 3RD PARTY CODE TO YOUR PROJECT ABIZER NASIR |

    ABIZERN.ORG | @ABIZERN
  2. Adam Evans https://flic.kr/p/8qki95

  3. ADD THE FILES DIRECTLY

  4. ADD THE FILES DIRECTLY • Probably the easiest way. •

    Download the files, drag them to the project. • Behaves like any other part of the project. • Easy to change the code.
  5. DISADVANTAGES • ARC/MRR? • Code warnings, errors. • Changes to

    the original code can’t easily be folded in. • Lose history.
  6. ++ADD THE FILES DIRECTLY

  7. ++ADD THE FILES DIRECTLY • Use some kind of version

    control to download the source, or project. • Add the files directly as before • Behaves like any other part of the project. • Easy to change the code.
  8. DISADVANTAGES • ARC/MRR? • Code warnings, errors. • Changes to

    the original code can’t easily be folded in. • Lose history.
  9. SUMMARY • For small classes, or categories. This is an

    easy way to get external code into a project. • For anything larger, or which has dependencies, there is an alternative.
  10. STATIC LIBRARIES

  11. STATIC LIBRARIES • An archive of code that can be

    linked against, with headers for the public interface. • Not just code, but resources can be included in a bundle that the consuming application can copy into it’s own bundle. • May have their own dependencies.
  12. STATIC LIBRARIES • Some come as pre-built libs • OCMock

    • Some come with scripts that create the libs • Specta • Most come with decent instructions about integration • Some are just projects built for CocoaPods that don’t build libraries cleanly • Sad Panda
  13. WHY THEY ARE USEFUL • They build with their own

    ARC/MRR settings that don’t need to match the consuming application • They build with their own settings configuration, so errors/warnings, if any, are confined to the library build phase and not yours. • They build the correct architecture
  14. ADDING A LIBRARY TO YOUR PROJECT

  15. STEP 1 DRAG THE LIBRARY INTO THE PROJECT

  16. STEP 2 ADD THE LIBRARY TARGET AS A DEPENDENCY AND

    LINK AGAINST THE ARCHIVE
  17. STEP 3 WAVE THE RUBBER CHICKEN • Sometimes you’ll need

    to fix a few things: • Specify the public header path for the library so that you can use • #import <Library/Library.h> • Specify the search path for archived builds so that you can distribute your application to testers • Add `-ObjC` `-force_load “some_path”` to the Other Linker Flags.
  18. CREATE A LIBRARY BEING A GOOD CITIZEN

  19. STEP 1 USE THE CORRECT TEMPLATE

  20. STEP 2 ADD A COPY HEADERS BUILD PHASE

  21. STEP 3 WAVE THE RUBBER CHICKEN • Make sure the

    public headers go into the correct place when building • Make sure the search paths are set up correctly • Set up valid architectures, warnings, errors. • Help is at hand…
  22. CONFIGURATION FILES • https://github.com/jspahrsummers/ xcconfigs • Available when added to

    the project. • Sensible and opinionated configurations for different build targets. • Not just for libraries, use them for apps as well. • Set the top level to “why” and the secondary levels to “what”.
  23. None
  24. DOCUMENTATION • Decide whether you need -ObjC (YES if you

    have categories on pre- existing classes) or -force_load linker flags (YES if your library only has categories and no classes), and document them. • Provide installation instructions, whether using CocoaPods or adding the project to a project or workspace
  25. COCOAPODS

  26. DEPENDENCY MANAGEMENT, AND MORE • If you’ve ever used a

    Ruby gem the idea of this will be familiar to you. • 3rd party source files and resources are fetched from a specified location, built into a static library which is added to an Xcode workspace that contains your original project. • From now on, you need to use the workspace not the project.
  27. PODFILE - SPECIFIES DEPENDENCIES • Uses a Ruby DSL. •

    Add pods to the targets in your app by name, or location. • Run `pod install` • CocoaPods will determine and install any other dependencies for those pods • The Pods folder contains the source, headers, project to build the library and more (acknowledgements, bundling scripts)
  28. PODS FOLDER • This is where almost all of the

    Pod output is sent to. It contains the sources, the config files, the static library project, the acknowledgements file. • Usually added to source control, even though it is generated. It’s not always guaranteed to be regenerated in the same state. • Useful to have a known state of the source when going back in history.
  29. PODFILE.LOCK • Should be checked into version control, specifies the

    version of pods to checkout on `pod install` • Resets when the Podfile dependency changes or `pod update` is run. • This is what tries to keep all repositories in sync. • Anybody else checking out the code just needs to run `pod install` and should get the same version.
  30. CREATING A COCOAPOD • You don’t need a working project

    (although it would be nice. Thanks) • Create a stub podspec file by running `pod spec create <name>` • A large, well commented file is created which is easy to fill in. • run `pod lib lint` to validate the file • Alternatively, `pod lib create` to generate a folder structure. Write your source and then run `rake release` which takes care of tagging and versioning. • Submit a pull request to have it added to the repository.
  31. None
  32. COCOAPODS? WE DON’T NEED NO STEENKIN’ COCOAPODS! Treasure of the

    Sierra Madre, Warner Bros 1948.
  33. GIT SUBMODULES

  34. GIT SUBMODULES • A Git repository that is added as

    a subdirectory of another Git repository. • The contents of the subdirectory are not tracked by the containing repository, the the commit hash. • It is checked out at a particular commit. • The submodule communicates with it’s own upstream repository independently of the containing repository.
  35. STORAGE • The .gitmodules file has a reference to the

    URL of the submodule and the directory which contains it. Shared with all repositories. • The .git/config file has a reference to the URL of the submodule and directory which contains it. Local to the current repository • The .git/modules folder has the actual git repositories for the submodule • The commit hash is stored in the repository.
  36. ADDING A SUBMODULE • `git submodule add <submodule URL> <Local

    Path>` • You can go into the checked out folder and change checked out version. • Check the module into the repository. This only updates the commit hash, not the added code. • Tip: Always use your own fork of a repository as the main submodule.
  37. SHARING THE REPOSITORY - SHORT • short • `git clone

    —recursive <repo-url>` • shortish, if you have a bootstrap script • `git clone <repu-url>
 ./script/bootstrap`
  38. SHARING THE REPOSITORY - LONGER • Clone the repo •

    `git clone <repo-url>` • Apply global repository settings to local repository • `git submodule init` • Actually setup the submodules • `git submodule update`
  39. CREATING A SUBMODULE • There is nothing to do. It’s

    just a library. • Specify the exact submodules and dependencies if required with a bootstrap script. • https://github.com/jspahrsummers/objc-build-scripts
  40. A RECURSIVE BOOTSTRAP https://github.com/jspahrsummers/objc-build-scripts

  41. HANDY TIPS • Check your submodules with `git submodule status`

    • Keep your submodules up to date - bootstrap or `git submodule update` • ALWAYS push changes to your submodule before committing to the enclosing repository • Use your own clone as submodules.
  42. WHICH SHOULD YOU USE?

  43. LOVERS CocoaPods Git Submodules Written by crazy, clever, passionate people

    There are some interesting edge cases that both can handle: Private repositories, fixed point checkouts. Try code before you buy. Most of the effort is in the setup, rolling out to others is easier after that. Builds libraries, doesn’t just dump code in the project, there is some audit trail of who did what.
  44. FIGHTERS CocoaPods Git Submodules Fast to set up Slower to

    set up. Integration is on you. Not tied to a VCS, doesn’t even need a VCS Needs Git repositories Dependency manager A dumb content tracker Quick to learn er… External code is just put into the project. No history, no logs directly accessible Full repository. See history, access all the code, run tests Encourages a consumption model Full project is available. Changes can be made, pushed to others while a pull request is pending Acknowledgements, external bundles subspecs. Shut up, I’m just a content tracker. Adds a dependency to manage dependencies You have Git already, you can manage the rest.
  45. SO, WHICH SHOULD YOU USE? • Pick the method that

    best suits the working environment • Which are you best able to support? • Do you see the value in the ancillary services that CocoaPods provides? • Almost anything you can do in one you can do in another.
  46. DOES IT MATTER? • Arguing about this is like arguing

    about the supremacy of Android/ iOS (IMHO). • Choices like this are not always technical. They are related to the environment, product, the 3rd party code, even personality. • Compared to actually developing YOUR app, the time and complexity of using one or the other is minimal. • Pick one. Get really good at it. Be able to work with the other.
  47. THANK YOU FOR LISTENING!