9 Requirements for Setting up a new Xcode Project

Rick Owers
Remote iOS Dev
Published in
10 min readFeb 20, 2020
https://www.pexels.com/

As a developer, when a client or product owner tells you, “We want to rewrite our application from the ground up.” — try not to faint from excitement.

It isn’t every day that you get to start a new iOS application. In my career, I have had a handful of these opportunities, and looking back, I didn’t always prepare properly. Honestly, early in my career I didn’t know how to prepare.

If you know you are going to be starting a new Xcode project, there are some key aspects of that project you will want to establish from the start. These may be team processes or architectural decisions that will allow for a more unified codebase, consistent developer experience, and a more scalable solution.

1. Define Design Patterns

Every project should follow a defined set of design patterns. Maybe you will stay true to Apple’s MVC pattern. Maybe you want to separate out your ViewModels and use MVVM. You might also look into MVP or VIPER. Whatever way you go, it will be important to establish the pattern you want to utilize within your application.

Why is this so important?

How often have you heard other developers talk trash about previously written code? What happens is a project grows, it gets more developers developing on the codebase, and the maintainability of that codebase becomes harder to control. If you have not defined proper design patterns to follow, your project will become a hodgepodge of patterns. Certain ViewControllers will be instantiated with Storyboard, others will be in code, and others will use Nib files. You might also find navigation using Segues, a Coordinator protocol, or ViewController to ViewController presentation. Lastly, you might find UI font and color customizations appearing in Storyboard and others in code. All of these will cause confusion as to where to look for the proper implementation.

A scalable application is one that allows you to implement things once and repeat the pattern again at a faster, yet properly architected, pace. If developers are constantly re-inventing the wheel, your project will become less scalable and more confusing for future developers.

As you think about design patterns, you should go beyond just the typical MVC and MVVM thought. Meaning, don’t just think about the View Controller, Views and how the Data will be injected, but also think about other patterns:

  • Coordinator vs Navigator vs Router
  • Repository Pattern
  • Delegation
  • Singletons

That is just a few, but the general idea is to have a general sense of how you should setup your application.

Note: If you are developing a native iOS application as a counterpart to a native Android application, these top level design pattern decisions should be communicated across platforms. Consistency across your product platforms is just as important as consistency within your own project. The great thing about Android development is that Google does a higher degree of architectural prescription, and an iOS application can easily create parity. Checkout the Android’s Developer documentation on Guide to App Architecture.

2. Project Structure

After you have defined the design patterns, you can then create your Xcode project and begin to setup the project structure that fits properly to that design pattern.

While I suggest that you get this setup from the start, this is an area that will most likely become more defined as you develop your application; however, as with design patterns, having something setup from the start will allow for a more consistent project structure and better conversations between team members as you decide to make changes.

In my experience, the following are some great folders to consider having within your application:

  1. Startup — I like to put the AppDelegate and any other app initialization files within this folder. Application startup procedures are important and knowing where to look for those features of the application is helpful.
  2. Navigation — I like to separate out my project’s navigation to a separate component. This allows the navigation logic to be removed from Storyboards, Nibs, and ViewControllers and contained in a single location.
  3. Screens — Many developers will think about this folder differently, but I like to follow an MVVM pattern. Within that pattern, I like to define “screens” as the full screen engagement a user is experiencing which is made up of the viewController and viewModel for that screen. An example might be a LoginViewController.swift and a LoginViewModel.swift that exist within a folder titled Login. This folder then sits within this Screens top level folder.
  4. UI Components — These would be all the reusable components to use throughout the application. New developers have a hard time thinking about this layer of separation, but as you grow, you will realize the efficiency gains of creating truly reusable UI Components. If your app get more complex, this separation allows for a UI Framework to be created in the future by just pulling out this folder and dumping it into a Framework.
  5. Services — This folder would contain the Restful or GraphQL API client or local data caching client for interacting with your data sources. This can also be were a repository design pattern would exist.
  6. Data — This contains your data models that are needed throughout the application. The viewModels in the Screens folder and the application’s data models are different. One is very specific to the views and the other is to contain all the data related to a given model object.
  7. Extensions — You will have a number of extensions in your application. I try to title these files ObjectType+ExtensionReason.swift. An example might be for UIView. I might have a UIView+Style.swift or UIView+Constraints.swift . One will contain extensions for the style of the views while the other helps with quick constraints requirements.
  8. Helpers — This folder will contain helper classes that can be utilized throughout the application. This might be a DeviceType class that helps to determine what type of device you are using, or a class that makes interacting with UserDefaults even easier.
  9. Environment — This folder will contain environment based files to help with switching environments and their environment variables.
  10. Root Files — This folder helps to expose the projects root directory files that you might need to edit from time to time. An example might be the Readme.md file. If you don’t expose the Readme within the Xcode project folder system in the IDE, you will need to go to Finder or the terminal to open the file. Remove this step by adding easy access to these type of files within the IDE’s folder structure.

There is no true prescription for a folder structure. It is up to you and your team. The key point here is to have a direction established so that the code can be properly organized as it grows.

3. Base Files

Every project will have some base level files that are needed before development can continue.

  1. Readme.md — This is usually created automatically by Github or manually within your project. Either way, this file is incredibly important to outline the basic requirements to run your project. Try not to over bloat the Readme.md file. This ends up causing more confusion than help.
  2. .gitignore — The .gitignore file is important to ensure you don’t push certain files to your remote repository. Without a properly formatted .gitignore file, PRs can become incredibly difficult and confusing to review. There are plenty of .gitignore file templates out there. Github can create one based on your language or you can look for examples from the community.
  3. cartfile or podfile — You will inevitably be using some sort of dependency management process, so creating the blank file ahead of time and structuring it within your project file system will help to ensure other developers know where to find it and update it in the future.
  4. pull_request_template.md — A PR template can be very valuable to keep PRs properly formatted across each developer on the team. Again, consistency in your development process will help with your overall efficiency as a team. Checkout Github’s help page on how to create one: Creating a Pull Request Template for your Repository.

4. Environments

Setting up a clean way to swap between your environments will pay dividends in the long run. You should consider Xcode Configurations, Schemes, Build Settings, and .xccofig files. No matter how you set things up, it should be scalable as your team and environment grows.

The issues I have seen in the past are where environment variables are getting set in multiple locations. Some are based on build settings and user defined variables, others are in code based on a DEBUG macro, and others are scheme based environment variables. If not documented properly, this really makes the environment setup difficult to understand.

I hope to write a post in the future about this subject, but in the mean time I’d like to push you to a blog post by Thoughtbot: Let’s Set Up Your iOS Environments. This post has really helped me think about my environment setup.

5. Linting

I use Swiftlint in my project setup to ensure our developers are following similar coding norms. This tool is not intended to enforce your larger architectural decisions, but it will ensure proper spacing, variable name lengths, method parameter and overall method lengths, among many more. It is a great tool to set a baseline on how your team will conform to some basic Swift semantics.

As you can see, these initial project setup tasks have a common theme: consistency.

6. Branching Strategy

The most popular branching strategy that I’ve seen used is Gitflow. I’ve had debates on what it really means to follow Gitflow, but those are extremely minor nuances to the process than the larger idea of how it helps with our team’s versioning and feature development iteration. The most important thing here is to make sure that your team knows how to branch, develop, PR, release, and hotfix your application’s code. Keeping a clean codebase is very important as you develop your application. I really love this github.io page that visually showcases how Gitflow works.

A properly setup branching strategy will also be directly tied to some of your automation tasks, so defining and adhering to your strategy from the start can really help with other processes as well.

7. Dependency Management

I like to start projects with a clean dependency management file as I stated above. I also like to try to keep my project to a single dependency management process if possible. Both Carthage and CocoaPods are great options, but you also can utilize submodules and Apple’s Swift Package Manager. Either way you go, you’ll need to think of how this will effect your development process as well as your automation processes.

8. Automation

Automating as many tasks as you can within your development process will save you tons of time down the road. In the past, with projects that are not setup optimally, cutting a release for the App Store would take me quite a while with multiple button taps and processes to run through. What if you can boil that down to a single command via the terminal?

Fastlane is a great automation tool that I have used in my projects to help automate a number of different processes. I love Fastlane’s homepage that showcases how many hours they have saved developers overtime.

Whether you use Fastlane or you just use the tools available to you on your CICD platform, the key here is to think about all the places you can automate your processes. Here are a few that I have seen to be beneficial:

  1. JIRA tasks — creating workflows in JIRA that connect to Github and move tickets to new statuses based on Github status can save a developer from entering into JIRA constantly (remove an administrative task from a developers’ workflow will make them extremely happy).
  2. Build Incriminator — Don’t worry about build version numbers. Find automation tasks that can help increment your builds and even versions to alleviate that process from your workflow.
  3. Unit Testing — Unit Tests should be automated on your CICD platform to ensure that all unit tests pass on any PR or Push to a given branch in the repository.
  4. Linting — Automated your linting processes will ensure no one can check in bad code that breaks your linting processes.
  5. Slack Messages — Post slack messages when builds are successful or fail so that team members can get alerted of when things need their attention.
  6. Release Process — 1 button release processes to the App Store are the best processes you can setup. This will save you immense amount of time in the long run.
  7. Provisioning — Fastlane offers some great Cert and Provisioning processes that can help automate this terribly frustrating process that developers have to maintain within the Apple ecosystem.

There are any number of automation tasks that you can achieve. Some will make sense with your team while others will not. The main point is that any time you save with an automated tasks will be more time you can spend coding.

9. Testing Expectations

Having your testing targets setup from the start with proper code coverage metrics being tracked will help ensure your team keeps testing a main priority.

I have gradually gained more insight and understanding over the years why testing is so important. Many new developers don’t see the benefits and instead see it as a cumbersome processes, but I can honestly tell you that writing unit test will benefit your team greatly by keeping a higher level of code quality in the project and highlighting where bugs can become present.

I hope to also write a post in the future about Unit Testing and showcasing how easy it can be to gain a base level of coverage without much effort.

Final Thoughts

All of these tasks can allow you to create a great technical base to your project as you start a new application. As you can see above, none of these tasks take into consideration any creative assets. This means, these can be part of your initial technical setup sprints as you being your new project.

Not every project gets the opportunity of really preparing and architecting a new application. If you are given this opportunity, don’t take it for granted. The more effort placed here as a team will make your development life so much easy moving forward.

Suggestions to the Community?

What other tasks do you always perform when setting up a new project? Comment below and keep the conversation going!

--

--

Rick Owers
Remote iOS Dev

Writer focusing on my career and life experiences: developer, engineering manager, family man, beach lover and dreamer of financial independence.