up:
the first one is in July, from the 22nd - 25th, in Western Virginia, and you can get early registration up through June 21st; you can also sign up for their August course, and that's August 26th - 29th in Denver, Colorado, and you can get early registration through July 26th. If you want a private course for teams of 5 developers or more, you can also sign up on their website at pragmaticstudio.com.]
CHUCK:
Hey everybody and welcome to Episode 15 of the iPhreaks Show! This week on our panel, we have Ben Scheirman.
BEN:
Hello from Houston!
CHUCK:
We have Rod Schmidt.
ROD:
Hello from Salt Lake!
CHUCK:
Andrew Madsen.
ANDREW:
Hello also from Salt Lake!
CHUCK:
And we have a new guest panelist, that is Jaim Zuber.
JAIM:
Hello from Minneapolis!
CHUCK:
Do you want to introduce yourself really quickly since you're new to the show?
JAIM:
Sure, happy to! Independent consultants, I've been doing iOS stuff for about 2-3 years; before that, I did some kind of .NET stuff. Way before that, I did a lot of C++ and C stuff in kind of the past life. But, yeah, I'm doing iOS right now, mobile stuff, and enjoying it!
CHUCK:
Sounds good! I'm Charles Max Wood from DevChat.tv. This week, we're going to talk about "CocoaPods".
BEN:
Yay!
CHUCK:
[Laughs]
ROD:
[Chuckles]
JAIM:
I'm cuckoo for CocoaPods.
CHUCK:
There we go.
JAIM: [Laughs]
BEN:
I'm a super fan of CocoaPods. I wonder if we have any haters in the audience, or on the panel.
ANDREW:
Yeah, I'm the hater.
BEN:
[Inaudible]
ANDREW:
Not really.
BEN:
Okay [laughs].
ANDREW:
I just don't use it.
BEN:
You say you're the dissenting opinion?
ANDREW:
I can do that, sure.
CHUCK:
I've had people basically say, "Well, it's just like having bundler - bundlers of utility in Ruby for iOS!" I was like, "Oh! That sounds nice." But that doesn't really tell me necessarily how it works.
BEN:
So can we start off by maybe describing what it takes to integrate somebody else's code into your project without something like CocoaPods?
ROD:
[Chuckles]
CHUCK:
Yes. Yes, let's frame the public.
BEN:
Anybody want to describe this for like, say, a moderately complex library?
ANDREW:
It depends on how complicated the library is. But at its simplest, you can just drag source code from their project into yours and add it to your project, and that's it. But I think, the thing that CocoaPods helps with this is dependence; it particularly helps with this dependency management. So sometimes, the library might rely on a system framework that you don't already use in your project so you have to go into your build settings and add that library in. And then, of course, updating the code to track updates that have ever provided it makes this a little bit of a pain if you just copied the source code files into your made copies and put them in your project folder.
BEN:
Yeah, so let's just start with that, like dragging source files into your project that we own. I don't know. It drive me crazy, just the notion that I had like no isolation between my code and their code from a configuration stand point. During our transition, this was especially painful because then you'd have to go and then add these flags to turn off ARC for older libraries that hadn't updated yet, or vice versa, if your [inaudible] hadn't updated yet. And then things like, I don't know, PreprocessorDefinitions or other types of configuration -- I don't know. Just things like dragging and dropping source files into your project is, it's like the least friction way if you just want like this one class you found on the internet to get into your project. But over the life of a project, you can hear having to repeatedly do this; it just seems like a horrible solution.
ANDREW:
I know I said I was the dissenter, but I actually agree with you.
BEN:
[Laughs] So the next of those other things like what if the library that you are bringing in requires the security framework or something and there's no hint that you need that? You just drag these new classes into your project into, hopefully, a sub-folder or something, and then you build and you get a ton of compilers because a bunch of symbols and references aren't part of your project. And then you have to say, you go back to the docs and you say, "Okay, this requires security framework and mobile configuration and whatever else." So now, I'm going to add those to the project and then you build and then it's like, "Oh, it also requires a little bit of XMLs, let me do that," and that requires some header search paths business when going in header search paths. If you're like me and sort of prefer my code and a third-party code to be physically separated on disk, like have maybe an app folder and lib folder for a third-party stuff, I would typically use a git submodule to pull in another project into the lib folder, then you have to manage header search paths for every single library independently so that you can even get code completion for the projects that you've dragged in. So, I don't know if I'm just introducing pain for myself, but that whole process was just made me want to tear my hair out. And then once you get it working, you're like, "Man! I don't want to go through that again," because like Xcode, you said, these problems were like it. If you had too many header search paths entries, occasionally, we'd choke on one of the paths; maybe the path on its base and/or it was just you had recourse of check on the path that was really deep. But there was times when the Xcode, which is like lose all of its code completion and syntax highlighting. It's gotten a lot better about that over the years, but it's still not perfect. I think having sort of that one common way that works is ideal.
CHUCK:
Don't make it sound like it's so much fun, Ben.
[Laughter]
ANDREW:
He's setting us up really well.
CHUCK:
[Chuckles]
BEN:
I've experienced enormous amount of pain in this area because I come from Ruby and, I want to say, .NET (it has a good system for this either), but it is pretty easy to drop a DOL into a project that you got from somewhere. It's a lot easier. So then the alternative is, sort of like the purest approach. If you are just take all these concerns to say, "No, no, no. I really want these things to be separate so I'm going to take the time create a static library for this other project that, maybe just as that as you read it, does an Xcode project." So I'll compile the static library and then I'll link it into my project, then you have other concerns. They're similar concerns, but it's just kind of like an X drew sort of headache that you have to tackle this work on yourself to create these static libraries. I think the static library approach is more like importing a DOL where there's strict separation; they're the [inaudible] for the things that aren't yours. Though each one what you had is kind of complex and adds configuration and everything. So if purchased CocoaPod takes is "Why don't we just do the static library thing, but CocoaPods will manage it all," and you will only have one to link in -- you really don't have to worry about it, so it generates a work space for you -- it takes to your project and adds a sister project for the pods that you want to import. And then the output of the pods project is the static library, which automatically links to your application. When you build then you take a look at the output, it generates; you'd have your .APP file and a lib pods that they could link in. To me, that's sort of the best of both worlds without having some sort of Ruby gem system or being able to link in dynamic libraries like .NET would; it seems like this is the best approach.
ROD:
Honestly, we still have frameworks. They're not as well, their uses, as they used to be, but their framework, they're kind of like DOLs. They don't have them on iOS, and I always wondered why.
Do anyone have any ideas?
BEN:
Does it have to do with the sandboxing, like permission support? I don't know...Since I can sort of join this community for iOS and have never really done any Mac programming, so I've never --
ROD:
You can put frameworks in the bundle so that would be a sandbox issue. [Crosstalk]
BEN:
And when you have multiple versions of some frameworks that as long as this is just a local reference it doesn't matter?
ROD:
Yeah, it handles versioning, too.
ANDREW:
Rod, typically on OS X, the framework, other than the system frameworks, usually you don't have to do this. But normally, frameworks are included in the AppBundle so each App has its own copy; if it's a custom framework, not with the system framework.
ROD:
And during build, you have to specifically say 'Copy' into the AppBundle.
ANDREW:
But, I think the reason for not having those on iOS is that they are whether at one time so it's some with security issue.
ROD:
Mostly.
ANDREW:
We use them, that Mixed In Key, and also on my own; we use frameworks quite extensively. They are our own frameworks, but we have code that is shared among all of our apps and packaged that up in frameworks. In fact, I just finished packaging up some code that's new into a framework last night. They work well for that sort of code separation.
CHUCK:
One thing that I'm wondering is, is there a way to write libraries such that they can kind of circumvent all the pain that CocoaPod solves without just putting them in CocoaPods?
ANDREW:
You can circumvent some of that so I will be able to [inaudible] for shadowing. One of my picks today will talk about some of this, some new stuff related to this, but static libraries, it's just like one header that gets around some of what CocoaPods solve. But some of it is other stuff like keeping projects up to date, CocoaPods can do that for you. If you just copy a static library into your project back to manually plan updates to the code, rebuilding a library pointing it in or somebody else is doing a library for you, you'd have to get updates from them.
BEN:
Right. And if they're providing an Xcode project that's not a stack library, you're providing that then you have your own project that has to mirror their configuration, and if they had files, you have to add files and so forth.
ANDREW:
CocoaPods really does solves problems that people had. There's not really another solution for.
CHUCK:
One thing that I noticed because I went and play with the CocoaPods website for a little bit was that sometimes, the libraries were kind of hard to find. So if I need something that does a certain thing, how do I go about figuring out which (are they pods?) which pod to use?
ANDREW:
[Chuckles] I think I've always just found the library first and like, "Oh hey, there's a pod for this!"
JAIM:
Yeah, go backwards versus be able to search the CocoaPod's website.
ANDREW:
I you find a good popular library on GitHub, chances are, it has a CocoaPod already made for it. If not, you can actually make your own and submit it to a CocoaPods repository if you want. I realeased a little open source library about a year ago and within a few days, somebody had added it to CocoaPods for me. [Crosstalk]
BEN:
There's like 3 places that I know where you can go search for them outside of just searching GitHub for libraries. If you'd go to cocoapods.org, there's a search field in the top and you can search for a specific pod name or an author. So if you're a super fan of maybe Mattt Thompson's gems or Sam Soffes gems...not gems, pods!
CHUCK:
[Laughs]
BEN:
Then you can search there. But since you already have -- CocoaPods is distributed through Ruby gems so if you type gem and install CocoaPods from a terminal on the Mac, it'll download and install the latest version. From that point on, you have a pod executable on your machine so can type pod search and a search term. If I do this right now, 'pod search networking' and I hit enter, it comes back with a list of pods that are related to networking. That's another place you can search. And then the last place that I found is on cocoacontrols.com. Not all the things on CocoaControls are pods, but they have a search field that lets you pick, "I want the controls, or pods, or both."
CHUCK:
Hah! So what is some of the pods that you guys use the most frequently?
BEN:
AFNetworking.
JAIM:
I use RestKit; RestKit pretty heavily. OCMock is in just what everything I do.
BEN:
Kiwi or Spectra.
ROD:
SVProgressHUD is one.
BEN:
Yeah, that's pretty much a standard for me, too.
ANDREW:
Here's what I think [inaudible] the center, I don't use CocoaPods. Well, I already said that, but it's really because there aren't any pods that I want, that I use frequently.
JAIM:
Is this for Mac or iOS?
ANDREW:
I mostly do Mac development, but even for iOS.
BEN:
I wonder if that's why I like the pods for Mac way less than the pods for iOS.
ANDREW:
Yeah. It's very rare that there's some third-party code that I want to use or need to use.
BEN:
If you have like a system that reusing third-party code is sort of cumbersome, then every little tiny extension. Let's say you have just like a really handy set of categories on NSArray for doing like Ruby style like map and reduce type operations -- and there's a bunch of pods out there that do this; one of them is called "BlocksKit", and I'm sure if I remember the names of the others, but let's say you just have something where it's literally one file with a bunch of additions to a class, it may not make sense to, if it's cumbersome to embed something like that in your project, then you wouldn't just won't take the effort to do it. That led to much larger frameworks like 320 and RestKits kind of one those where there's just a lot of stuff in it. So in order for you to sort of pick and choose what you want, you wouldn't want necessarily just bringing a gigantic library and then bring in like 15 other little tiny pieces. But with CocoaPods, if you start thinking of things that's little tiny atomic units of functionality and one pod can depend on other pods, then it does make sense to bring in things that you want to depend on. Like if you look at a mature Rails stuff and you go take a look at the gems, the depency trees are kind of impressive of what the community sort of built upon anywhere from XML parsing for database access or something, they all build on each other. That's something that the CocoaPods community is sort of still young at, like not a lot of pods sort of work together. But I think that's just a matter of time before that happens that we could have much smaller or more focused libraries that become the basis for other libraries.
JAIM:
Yeah, but I see what happens, it's kind of a thing where I'm not sure what's going to carry over for my kind of Ruby best practices, but again with the gems and kind of what Objective C does. You don't really know what carries over. I think the kind of apps that they do are somewhat different. A lot of iOS apps are smaller things where this kind of focus is maybe not as important as a larger web app. But it's to really see how things are kind of developed that way.
CHUCK:
So walk me through the steps of kind of getting a pod or a library into my application. So you go install CocoaPods, and you said you gem install CocoaPods, is that --
BEN:
Right. Gem install CocoaPods will give you the pod executable on your machine. And then somewhere in your project, you can be up to one-level above the Xcode project. Actually, I suppose you can put it anywhere. I added a long time ago the ability to set an Xcode project half in the pod file. So we basically create a pod file and it looks like a gem file so it's syntatically Ruby, but you might not noticed. In the pod file, you have to specify what platform you're on, that you're iOS, Mac, or both, and then what version you're targeting. That's going to control what the static library outputs. Typically, I'll put platform iOS, 6.0 if I want to target 6.0. And then if my Xcode project is in the same folder, or I think one folder deep, it will find it for you so you don't need to specify. But if it's in sort of a non-standard path, or maybe it's in stabling path or whatever, then you can specify the Xcode project and give it a string for where to find it. Underneath that, you just list out your pods that you want so the syntax is like POD and then in quotes, the name of the POD. This uses the exact same code for Ruby gems to determine version. So you can say, "I want AFNetworking 1.3.0," and you can use the tilde-greater-than to do sort of -
CHUCK:
Every time I call it the Twitter walk and I've also heard it called something isn't this family-friendly. [Laughter]
BEN:
We'll call it the squiggle version. If you do that, then you can say, basically when you POD install, I'm okay with the 1.3.1, but the last significant digit that I typed, I'm okay with incremental versions from there. So if you're following semver (Semantic Versioning), then basically, 1.3.0, if you use the tilde-greater-than, then that will allow PODs to install 1.3.1, 1.3.2, so you're getting bug fixes without having to worry about breaking changes, and it's such a pain on how you specify your versions and how tolerant you are of upgrades, that sort of thing. Now, what you shouldn't do is like AFNetworking is eventually going to come out with 2.0 pretty soon, and 2.0 is going to break a lot of things. So if you just have pod AFNetworking in your project and then you pod install to install something else that you'll add later on, it will install the latest version that it can, and maybe that means bringing an AFNetworking 2.0. So I think it's important to sort of call out the notion of sort of locking down your versions to the extent that you don't want to deal with upgrades. At some point, you do want to do the upgrades, then that's when you should change the version then run pod install again.
JAIM:
I guess it's important to do the upgrades of the version exclusively like, "Okay, we're ready to test this," and not just because you're doing a build and you're like breaking edges and break stuff, but you're not expecting.
BEN:
Right.
JAIM:
Or the people kind of put in there versions pretty especially in their pods.
BEN:
I find that no...[Laughs] Even myself when I'm just sort of playing around, I'll forget. If it's like a shipping app, a real app like in our ongoing apps and stuff, of course I have it in there, but what I'm just creating like a little side of project whenever I usually don't put it in there because I just want the latest. And when you're sort of active early development, it's okay to tolerate that sort of flux in the library. Like if it changes to 2.0 and you haven't them shift yet, it's probably worthwhile to take the time to fix it to get to the latest version. But once you shift and you're sort of in the maintenance mode, it's definitely important to be aware of your versions and what could potentially happen if they just decide to create 5.0 and they have totally different design and things break. This particular thing happen SVProgressHUD twice where they upgraded their public interface like breaking changes all througout my apps. I must have like a hundred different references to show how the nview and they got rid of the nview or something like that. I can't remember the exact syntax, but I had to go back and fix them all, and then I've updated again and they changed it slightly again, and it was just, man! Really frustrating.
CHUCK:
Was this something in minor version or --
BEN:
I want to say this would be for CocoaPods.
CHUCK:
Oh, okay.
BEN:
So I don't know if it actually had a real version. But hence the reason why versioning matters because I should be able to take the code and leave it the way it was as long as it's not causing any problems and lock myself to that version until I'm ready to say, "Okay, this update adds these features fixes these plugs or fixes this warning, now I'm going to take the time to upgrade it," so I will manually bump the version in the pod file. Again, if you do pod search with the pod name, it will tell you all the versions are available so that's really handy.
ROD:
What about -- you can do multiple targets, right, like say at a test target and your main app target?
BEN:
Right. [Crosstalk] Target test, and then app kiwi or expect the OCMock or whatever to that.
CHUCK:
Another question that I have is some of these are maintained by GitHub and stuff, and I know that bundler lets you specify like a GitHub repository as opposed to saying "Pull it from Ruby gems and get this particular version." Does CocoaPods allow you to do that?
BEN:
Yeah. You can specify a path to a GitHub repository by using the git-hash like :git-hashrocket and then the GitHub repository. If you do that, though, the pod spec has to be in the root of that repository. That's true for most libraries who's sort of aware with CocoaPods, but some of them might have it in a subfolder or some might not at all so you would have to specify that pod spec elsewhere. So some of my projects have a folder called "PodSpecs" and I'll just create my own pod spec for that library. It can point to GitHub repository if just the same; it doesn't have to be hosted on CocoaPods. So I just tell it, "Go here, fetch the code, here's the files I want you to build, etcetera," and then keep that local, and then I check it into my own repository. In my podfile, I'll make a reference to that pod, I'm going to say, "Pod like us some pod," and then pass in the podspec as the path to the podspec on disk. And then the third option, it's just copy the code actually into your repository like maybe get some module or just like right there in your own repository and you can specify a path to the code. That's really handy if you're like contributing to a library like let's say I want to do a bug fix for AFNetworking, I can clone AFNetworking to a folder on my machine like my dead folder, and then change my project reference to that pod instead of just without any parameters where it would go to CocoaPods which would point it to the tag in GitHub, then go to the path on disk, you can pull up from there, that way you can make changes, fix the bug, and then submit a pull request to the main repository. That sort of enables this open source for a club that is really, really common in the Ruby community.
CHUCK:
Yeah, it's really handy to be able to do that kind of thing; just open things up and make your changes, send a pull request, do all that good stuff.
BEN:
There's couple of other stuff. So once you've finished it to your podfile -- initially, I'll just create a podfile with a couple of ones I know I'm going to use, and one of those is reachability and SVProgressHUD and AFNetworking. So I just had a few common ones that I know I'm going to need, then your own pod install. That will find your Xcode project and it uses an Xcode gem to sort of interact with it. So a lot of the things you can do in Xcode like adding references or changing project configurations or whatever can be done with this gem so they use that gem to modify your Xcode project and set up the dependencies; they create a workspace for you and put your project in a pod project in that workspace. The only sort of, I won't call it cumbersome, but it's just sort of minor nuisances that you usually had your Xcode project open while this happens, and now you need to use the workspace so you have to close the window and then open backup with the workspace instead of the project. But for my point onward, you're just dealing with the workspace and you can pod install all you want and it will just type what it needs to.
ROD:
And how do you handle multiple platforms? Just another target?
BEN:
Well, since I don't really do multiple platforms, [laughs] I haven't tackled that --
[Laughs]
BEN:
But yeah, pod itself can support, like AFNetworking for instance, supports both Mac and iOS. If you're going to have multiple targets, one for iOS and one for Mac and a pods project, then I think you just have to be careful to have all of your common pods in those sort of top level, and then do target specific pods for the ones that should only be linked to an OS X project.
ROD:
But then you can only have one project in your workspace? Or you have two projects?
BEN:
You can have as many as you want, but it's only going to modify the main project that it finds. Like if there are 2 Xcode projects in there -- I'm not sure if I will just throw out and say which one do you want or if it will just take the first one -- but you can specify which project are you going to have CocoaPods integrate with. And then if you wanted to add to that workspace later on, I think you could; I think that would be fine. Do you typically have one project with multiple targets or like two projects in one workspace?
JAIM:
I alternately do multiple targets. I think we've had some OS X builds and iOS builds and we'll have one project. For the stuff that used to be cross platform, I'll be doing multiple target, two targets.
BEN:
Since that workflow would be really ideal for CocoaPods because you can just do the target specific pods.
ANDREW:
Same thing, I have couple of projects that has cross platform, a bit of cross platform. I used multiple targets in one project.
CHUCK:
So you just, when you're building for iOS, you just use the iOS targets; for the Mac apps, you just use the Mac targets?
ANDREW:
Yeah. So when I'm talking about it, it's a little more complicated because I actually have the shared code effected out into it, the framework on OS X and the static library on iOS. But the framework and the static library are built by the same project; it just has OS X target that builds the framework and then iOS target that compiles the static library.
CHUCK:
Sounds like fun!
BEN:
So then once these pods are sort of living in your repository -- and that sort of a choice that you can make of whether or not to ignore the pods folder or not when it downloads and integrates -- in the Ruby community, when you install a gem and it installs on your system and your project looks for them in the system path, every developer needs to run bundle install in order to get the latest gems. And when you install it on the server, you'll probably also run bundle install which led to "What if we just want to have all the gems ready and we don't want to do bundle install in the server?" or whatever, then that would lead you to vendoring gems, which is basically checking them in to your project. In the CocoaPods community, they looked at this and said, "We'd rather just check in the dependencies the exact versions you need," so then not everybody needs to know or care that you're using CocoaPods; all the code is already there. That's [inaudible] they took by default, but both sort of scenarios are supported. So I will typically check in my pods project or pods folder into my GitHub repository and push it. In that way, everything, all the dependencies and everything, are there in my project. If the project went away tomorrow, I will still have the code.
Then when a co-worker downloads it, they don't need to run pod install at all.
CHUCK:
Yeah, the big tradeoff with Ruby, at least, is that some of the gems compile C code so depending on the system you're on, you may not want to install the gem locally like you do with CocoaPods. But the CocoaPods, it makes sense because you kind of build everything at once when you compile your project. So it makes a lot of sense to just put it in there and then you can pass it around and it doesn't really matter because the build process is mostly architectured independent and it doesn't very aton between the different max anyway, so it's not going to kill you off to have to have something in one issue versus the other.
BEN:
Right.
ROD:
Another thing I noticed, that RubyMotion supports CocoaPods so you can --
CHUCK:
I was about to ask that [laughs].
ROD:
Yeah! You can use all the, even Objective C CocoaPods, you can use them in RubyMotion.
CHUCK:
Does it work any differently there? I guess what I'm wondering is...Well, I guess you do need a Mac to build your RubyMotion stuff.
ROD:
Yeah, you put your pods...I don't think you have a podfile and say you put them in your rakefile, and there's a gem called "motion-cocoapods" that integrates into that.
BEN:
That's kind of a bit of a mind been drape...you've got gems that are [inaudible] like it's a RubyMotion that you can use and that's usually a prefix of motion dash, and then you have CocoaPods which are actual Objective C [inaudible].
ROD:
Right.
CHUCK:
Yeah, but they still compile using LLVM and all the stuff that you're used to. I'm pretty sure
RubyMotion uses LLVM as well so it's a similar process; it's just compiling Ruby instead of Objective C -[Crosstalk]
JAIM:
It's like Thanksgiving, it all ends up in the same place, right? [Laughter]
BEN:
Didn't you guys watch Ghost Busters? You're not suppose to cross the streams... [Laughter]
CHUCK:
See? You're tempting me to say something that's not family-friendly...
BEN:
[Laughs] You just have many...Cut it out until last week --
CHUCK:
[Laughs]
JAIM:
Are you guys looking CocoaPods on like kind of client work? Because in that case, it definitely make sense to I'd always check it into whatever they have so that they're not reliant on kind of the pods. I'm not entirely comfortable saying, "Oh yeah, that sort of code is out the cloud somewhere," even if it's on GitHub which is fairly stable. Do you guys have any differences for keeping it in sort of control kind of for client work? Or have you done anything like that?
BEN:
Yeah, it goes on everything I do; personal, side project, client work, everything.
CHUCK:
Yeah, it's definitely something that I want to play with a little bit more while I'm still learning this stuff. But yeah, are there any other -- for example, when you're testing, do CocoaPods make it easier or harder to test?
BEN:
Easier because testing tools are typically distributed through CocoaPods also. Like I typically use Kiwi or Specta, but you can also pull in an OCMock or any of the others like OCHamcrest for matchers or whatever testing tool you want to you use, you can probably use that way; it's just makes it easier to get started. Before CocoaPods, Kiwi had a Wiki page that was probably 10 printed pages full of setup with screenshots of all the crap that you have to do in order to get Kiwi working because you have to link it in to your project, but only for a separate target because you don't necessarily want to ship your unit test. So you have a separate target just for your tests and you have to link Kiwi at that and you need to make sure all of the libraries that you're using in your main target are also checked for the test target. It's just kind of a pain.
CHUCK:
So do you do any kind of an integration testing from your code to their odds and back? Or do you just kind of mock them out?
BEN:
I suppose that depends on the nature of the pod. Something like AFNetworking, you have few choices: you could mock the AFNetworking interface and sort of call the success callbacks or failure call yourself. I think that's probably not a great idea because you're mocking an interface that you don't know. There's other gems out there like OHHTPStubs which can stub the underlying NSURLConnection behavior. So you can say, "Okay, I want you to get a request that looks like this; I want you to show me the first response," and then sort of trust that AFNetworking is going to work. That's more of an integration style in terms of your code integrating with the AFNetworking, but you're still stubbing the network. That's the approach I would generally take. A lot of times, testing an iOS is so much harder than it is in Ruby. So the test that end up being written the most are the ones that don't have many dependencies where you don't have a whole lot of mocking to do.
CHUCK:
Yeah, that makes sense. Are there any other parts of CocoaPods that we want to talk about?
BEN:
What about creating your own pods?
CHUCK:
Yeah, that's a good idea. Is it really that hard?
BEN:
Anybody else have CocoaPods? It's not hard at all, but there are some cases out there that people are kind of frustrated with how difficult it was just because their library was bigger or a lot more complicated for whatever reason. The pods that I've created are dead simple. It's just a couple of source files that I need to be compiled and give it a license. One of those is BSModalPickerView; it's sort of something that I use all the time. It's really simple. But basically, you give a button there that presents a PickerView from the bottom and sort of gives you a faded background that initially you can tap to cancel. That way, you can make a quick selection. It's almost like anytime you have a form that you needed a dropdown, I use that. So there's a podspec for that, and the way I created that was with podspec create. I think that takes [inaudible] for the GitHub project and the name of your pod so it gives you a sample podspec file. Like I said earlier, that should be in the root of your project when you push to GitHub so that people can use this directly with your project so that it'll prints just like you use the head of git and not necessarily a tag to version if they want. Anyway, the podspec goes in the root of your project and it gives you a description and version information and what files you want to compile. If you have any sort of resources like images that you need to embed in the pod's static library it gets created, then you can specify those as well. Once you're all done, you create a tag for this version. Typically, you'll start with 0.0.1 if you don't have a public version. Or, if you're creating a podspec for somebody else's library and they don't have versioning yet, then you will start out with 0.0.1, then you run podspec lint, which will verify everything you just did and make sure that the podspec is correct. I'm not sure the official approach to pushing a CocoaPod; I believe you'd just run podspec push and it works. But I have write access to that repo so I'm not sure if it works because I have write access to that repo or that's the intended way for everybody to do it.
JAIM:
Idea of other options for hosting other than like git on GitHub?
BEN:
We have 2 sort of common pods that are private to our company. They happen to be private GitHub repositories, but they could be wherever. Instead of hosting them directly through our CocoaPod and putting them the CocoaPods index, you can just use the git and tag versions, like you can say, "Go to this URL and pull up this tag," or a path on disk. It doesn't have to be GitHub, it could be like the bucket or some other GitHub repository or a path on disk somewhere.
CHUCK:
And then you just put the paths back in so that it handles it like array or your pod?
BEN:
If the podspec is already in the root of that GitHub repository, then you're already good. The only time I have to create my pods back is if the library doesn't have it in there. So I think when its actual mobile service had a bunch of client libraries in one repository sort of like iOS was a subfolder, and so I didn't work there. I had to create my own podspec for that that appointed to the right spot in their repository or where the code was.
CHUCK:
Another question I have then is, I'm assuming you can write pods that depend on other pods, do you just [inaudible] dependencies into the podspec?
BEN:
Yup, dependencies on other pods and frameworks. So if you're doing like a CoreData related pod, then you say I depend on CoreData and I depend on like MagicalRecord. And when you do pod install, it will install MagicalRecord, the pod put that code in there, and it will link your pods projects to the CoreData framewok.
CHUCK:
Nice. So if you've created a project that depends on, and you're pulling a pod that depends on CoreData but you haven't enabled the CoreData in your project, will it automatically fix that for you or give you a warning? Or do you just have to know that --
BEN:
That checkbox in Xcode is for 2 things: (1) to generate some really horrible template code; and (2) does like add CoreData framework to your project. The latter is handled for you by CocoaPods, but creating horrible template code, I can do without so I usually don't check that box anyway.
CHUCK:
So what it does is it goes in and basically puts in the includer or require or whatever that pulls it in.
BEN:
Right. So linking your project with that and then I think it puts CoreData .h in your prefix header so it's still available everywhere. But then it puts a bunch of CoreData setups like to set up the CoreData stack with all the defaults, it like dumps all that in your AppDelegate, and I don't like it there so I usually move it somewhere else.
CHUCK:
Okay. Alright, well, let's go ahead and get into the picks then. Andrew, do you want to start this off with picks?
ANDREW:
I only have one pick this week again, sort of quick pick. My pick is "Objective C Modules", which asre a feature of Client 3.4, an LLVM. Modules actually addressed some of what we've talked about CocoaPods addressing today, and this is the new feature in the compiler. Wherefore system frameworks, you don't actually include the header anymore, we use an app import directive to say that you need a certain module which corresponds to a system framework. And Xcode or the compiler takes care of including that for you and in the build so you don't have to go and manually anymore until the link with that framework and also it speeds up population because it avoids the whole huge include problem when you just import .h, you're actually including all of that code and the code in headers that includes in your tabulation unit. I just think that's going to be great in the future; it's not widely used yet, but without saying too much, if you've got access to the WWDC videos, go and watch them.
JAIM:
So that's upcoming? Xcode 5?
ANDREW:
Upcoming. Yup! It's in Clang or in LLVM now, it's not supported in Xcode yet.
CHUCK:
That's really interesting. We'll have to say what thay managed to do with it. Jaim, what are your picks?
JAIM:
I found a little library for kind of UITesting asynchronous stuff. So if you've got your ViewController and you [inaudible] some kind of background thread, it's called "UTAsync", and it's just a small little C library that if you have to actually test an asynchronous code, it allows you to do that. I've given that case where I inherit some code that maybe wasn't setup to be tested, but awaken kind of get around some of that. So I recommend that.
CHUCK:
Awesome. Rod, what are your picks?
ROD:
I'm going to pick a couple of Xcode plugins. One is called "CocoaPods Xcode Plugin", which is a plugin that sort of help you manage your CocoaPods right in Xcode. I haven't had a chance to look at it, but it sounds interesting. Then there's another one called, "VVDocumenter", which helps you do Javadoc like stuff for Objective C with templates right in your code. Those are my picks.
CHUCK:
Awesome. Ben, what are your picks?
BEN:
I've got 2 picks. The first one is "CocoaDocs.org", which allows you to search for any CocoaPod and it will give you the documentation for it. If you're using sort of Apple docs style documentation, then you can have one placed to go grab it all, which is super handy. And then the next pick is "cocoapods-xcode-plugin". I believe this is now requiring Xcode 5 so it should be out pretty soon. I tried this as well when Xcode 4 isn't seem to work, if I remember correctly. Anyway, it gives you a menu in Xcode that will say 'install pod file, init pod file, install your pods' that sort of thing. So if you like working directly with Xcode and don't want to jump to terminal just for that, then that might be something to check out. Those are my picks!
CHUCK:
Awesome! My picks are more related to the book I just read. I just read "Getting Things Done" for the second time. We're going to be interviewing David Allen this afternoon for the Freelancers' Show. Anyway, I'm going to pick the book because it is just awesome! I picked up a whole lot of stuff that I didn't get the first time so I'm really excited to kind of rework some of my productivity behaviors. And then the other thing that I'm picking is the software that I use to get stuff done and that is "Omnifocus", I'll put a link to that in the show notes as well. Omnifocus, it's a little bit expensive, but it is by far the best software I found for managing list, to-do's, it does synching between the iPad, the iPhone, and the Mac. The thing that I really like about it is that I can get it on my phone and my wife or I might need something that I need to do so I'll go and I'll put that in the Omnifocus on my phone. And then when I go through and review my to-do's later and work through my inbox, it'll actually get moved to the right place; it'll get synched back over. If I'm out and about in the car and I'm like, "What do I need to do?" while I'm out, I can just pull it out, I can look at the context for 'in the car' or things like that then I just know what I can do so I can go on and pick up the stuff that I need to get and get a whole bunch of stuff done. It's just really, really handy and it's a terrific way of managing all the stuff especially if you're self-employed and you're trying to manage marketing and clients and finding clients and subcontractors and all the other stuff that you have to do; paying taxes, and what have you. Anyway, it's super, super awesome tool and it's a great way to get things done. Anyway, those are my picks. Thanks for coming everybody! We'll wrap this up. We'll catch you all next week!