Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modularize a big iOS app using CocoaPods

Inspired by a Hubspot blogpost, I have split up my iOS project into one main project and several sub-projects that are added to the main project using CocoaPods.

I have one main project and several sub-projects (each in a separate git repository and podspec file). The advantage is that each sub-project can be compiled, run and tested on it's own. That approach works well, except for sharing global items like static strings, global protocols, base classes between the sub-projects (e.g. SomeProtocol.h, constants.h). I have defined the static strings, protocols and base classes in the main project and created a pod spec in the main project that includes the global items, which is added to the child project's pod file.

The child projects compile and run using this approach, but the main project doesn't compile, since each sub-project pod will include files like

#import <SomeProtocol.h>
#import <constants.h>

that (although part of the main project) cannot be found when the individual pod libraries are compiled.

Is there a best practice how to split big iOS projects into several smaller ones?

like image 953
Ronald Mannak Avatar asked Mar 01 '14 00:03

Ronald Mannak


2 Answers

Is there a best practice how to split big iOS projects into several smaller ones?

Absolutely! You have two options for this: libraries and frameworks. Typically each library or framework would be it's own project, and would live in a workspace shared with an application using these. Schemes would be used to build these projects as dependancies of the application.

This more or less describes what you would want to do: Static Libraries in Xcode

Note that your static library targets should have SKIP_INSTALL set to YES. Otherwise you will have problems when you archive your application.

Schemes seem to be a blind spot for a lot of developers, but they are very important for understanding your tools and scaling your workflow. So important that Apple did a WWDC session on schemes in 2011 and then repeated it, almost word for word, the next year

static strings, global protocols, base classes between the sub-projects

Static strings should be pretty easy - use NSLocalizedString, and then the values are loaded by the application using the library.

I'm not sure what you mean by "global protocols". "Sharing global items" though sounds not so good. That's something in general you want to avoid.

Base classes would go into their own library or framework, and the other things that use them would depend on them. If libraries B and C both used FooController as a base class, FooController would go into library A, which B and C would link against.

like image 65
quellish Avatar answered Sep 20 '22 13:09

quellish


Are you getting duplicate symbols or errors that those classes are being redefined? That's my guess as to whats going on. I'll lend my thoughts as if that is the case.

I work on a large project that uses the same approach though our project is a little different. Essentially we started with one app and then started building other apps that have some of the same functionality, so those common things got split out into their own project. Think stuff like networking code, custom alertviews, custom navigation bars, and so on.

From what you described it sounds like your global items like strings, constants, base classes and so forth belong in a project of their own which is sort of what your doing, but without it being in it's own project. Is it possible to break those objects out into another repo and let cocoapods resolve the dependencies? This is what we do with our project - anything that is used in more than one place is put into the common project and that gets included via cocoapods.

My guess of whats happening is that your including them (lets call them common) in your main (lets call this main) project without cocoapods, then subproject A has a dependency on 'common' so cocoapods brings common along with it when it gets pulled into main.

Something else helpful that you may not have learned yet is that you can bring all your pods in from your local disk instead of pulled in via Git. In your podfile it would look something like:

pod 'common', :path => '~/dev/common'
like image 40
Brandon Avatar answered Sep 20 '22 13:09

Brandon