How to create UICollectionView using Swift without storyboards

There’s a lot of tutorials about how to create a UICollectionView using storyboards or just nib files. I don’t like Interface Builder and prefer to do everything in code. Most of the time it’s easier, it creates less bugs, so in this tutorial we will create UICollectionView programmatically.

UICollectionView is highly customizable class for presenting your content in almost any layout you want. If you want Apple to tell you basics about it, visit WWDC 2012 videos “Introducing Collection Views” and “Advanced Collection Views and Building Custom Layouts”. It implements in a similar way to UITableView — using UICollectionViewDataSource and UICollectionViewDelegate protocols. Let’s take a look at how to do it using Swift.

Let the show begin

At the time of writing this post, Xcode 6 is in beta so I can’t post screenshots of it, but don’t worry, you don’t need them because we’ll do almost everything in code.

Create an Xcode project. Unfortunately, Xcode 6 doesn’t allow us to choose an empty project with only an App Delegate, so we’ll choose one close to it. Select Single View Application and click Next. Name your project as you want (I named it Gridtest), select iPhone in Devices list, but actually this will work just fine on iPad too (not two :)). Uncheck Use Core Data. And do not forget to select Swift in Language list!

Ok, so here’s our project. The next step is optional, but it may be useful to know. Let’s…

Say goodbye to storyboard

I want to do everything in code, so let’s delete the storyboard that was provided to us by Xcode.

  • Open up Project Navigator (⌘1).
  • Select your project here, then in menu at the right of this project button under the Targets section select your project name. It’s Gridtest in my case.
  • Clear Main Interface field.
  • Delete Main.storyboard from your project.

Alright. There’s no storyboards now, but because of this now we need to initialize a window programmatically, just like in Objective-C. Select AppDelegate.swift in Project Navigator and update application(_:didFinishLaunchingWithOptions:) method with this code:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.backgroundColor = UIColor.redColor()
window!.rootViewController = ViewController()

return true

This little piece of code (as the name tells us) gets called right after application finish its initialization process. Here we initialize our window property, set it’s background color to be red, set an instance of ViewController class to be window’s root view controller and show it to user. Window is where everything is displayed in an iOS application.

Run the app and you will see that the screen is filled with red. Good. Window is here, so we can move on. An instance of ViewController class is a root view controller of our window, but it’s transparent. Let’s fill it with UICollectionView!

Collection View

UICollectionView is a nice thing, but it’s pretty easy to get confused when you work with it for the first time. Lots of links in Google tell different information, but it’s cool that you have clicked on a link to Randexdev 🙂

Apple provides us with UICollectionViewFlowLayout — grid-like layout for cells in our collection view. To create nice layouts people subclass this class or UICollectionViewLayout. We don’t need to subclass anything, but if you want it’s up to you. To fully implement UICollectionView with UICollectionViewFlowLayout, we need to adopt three protocols (not 2, like in UITableView): UICollectionViewDataSource, UICollectionViewDelegate, and UICollectionViewDelegateFlowLayout.

Select ViewController.swift in Project Navigator. Update the class declaration with this:

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

Well, wut?! We need to adopt three protocols, why there’s only two? This is because UICollectionViewDelegateFlowLayout inherits from UICollectionViewDelegate, so by writing only UICollectionViewDelegateFlowLayout we adopt both of them. By the way, if you’d need to implement UIScrollViewDelegate methods in your project, by writing UICollectionViewDelegateFlowLayout you automatically adopt UIScrollViewDelegate too.

Don’t worry if you get an error here, we’ll fix that soon. Right after class declaration create a new variable:

var collectionView: UICollectionView!

This creates our first and last variable we need. As you can see, this is an instance of UICollectionView class, and this is an explicitly unwrapped optional (because there’s and exclamation mark after the class name). Explicitly unwrapped optionals are dangerous, because if you try to use one before it gets initialized, your app will crash. We could remove the exclamation mark, making this variable just a simple non-optional, but then we’d need to initialize it in the class’ init methods. I want to simplify this tutorial, so I won’t do it. Let’s initialize our collection view in viewDidLoad() method.

Update the code of viewDidLoad() method with this:

override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 90, height: 120)

collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = UIColor.whiteColor()

At first, we create an instance of UICollectionViewFlowLayout because you can’t initialize UICollectionView without a layout — you’ll simply get an exception. Then we set sectionInset just to make our grid more beautiful. 20 instead of 10 for top inset because of the status bar. Then we set our cell size. If it’s not set, cells will be with a default size of 50×50. After this we finally initialize our collectionView, tell him that we will be his dataSource and delegate. Then we register a class that will represent a cell in our collection view. Important: this is necessary to register your cell class because without this you’ll get an exception, because collection view need to know what kind of cells it works with. In our case we didn’t create any custom cells, so we just register a UICollectionViewCell class as a class for our cells.

And at last we need to implement dataSource methods. Write them somewhere in ViewController class. I’ve used to do it at the bottom.

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 14

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
cell.backgroundColor = UIColor.orangeColor()
return cell

CollectionView(_:numberOfItemsInSection:) must return number of items to be displayed on screen. It is similar to UITableView‘s numberOfRowsInSection(_:). In collectonView(_:cellForItemAtIndexPath:) you need to create a cell and return it. The thing is, dequeueReusableCellWithReuseIdentifier(_:forIndexPath:) dequeues existing cell if available or creates a new one based on a class you’ve registered. That’s why you should’ve register a class previously. At last, cells of UICollectionViewCell class doesn’t contain anything at all, so we just set a backgroundColor to them.

Run the app and you’ll see that everything is working fine. You should see a grid with several columns and 14 orange rectangles in it on a white background. Congratulations!

Where to go from here?

Check out the UICollectionView documentation, experiment, explore new things and optional methods in protocols we’ve adopted. UICollectionView is very flexible and powerful instrument to show your content to user, so you better take a closer look.

If you have a question, suggestion, or if I did something wrong here, please let me now in comments below.

35 replies to “How to create UICollectionView using Swift without storyboards”

  1. Thanks Randexdev!

    It’s very helpful!

    Just wonder can you do an extension of this tutorial, such as putting pictures to the cell and some interaction with the cell?

    Thanks again,

      1. Thanks,
        I was trying to learn more about doing Collectionview with swift, and there are not much resources out there. I’m starting to get an idea how to do it too.

  2. There are so many Swift examples online that overcomplicate things and don’t explain important steps. Your article could not be have been better written – clear, simple, and straight to the point. Thanks!

  3. thanks for this page. I started getting errors relating to the UICollectionViewDataSource protocol after upgrading to Xcode 6 build 7 and was able to fix them after checking your code. I had to remove a few ‘!’s…

  4. I added the required functions for the UICollectionViewDataSource protocol but still getting “does not conform” error. Is anyone getting that with xCode 6 GM Seed?

    1. I don’t have that error in Xcode 6 GM Seed.
      There are only two required methods in this protocol and we added both in this tutorial. Double check function names:

      func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int


      func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
  5. Nice tutorial! Thank you! Just to mention that you define the cell as a constant (let) and then try to modify it by changing its background. cell is a var in this case.

  6. My bad… Not true what I said about the ‘let’ declaration. With a constant you can change objects attributes but not the object reference itself. Sorry.

  7. Awesome tutorial. I had to change my ‘main interface’ under the Project settings from ‘main’ to ‘launch screen’ and it worked perfect.

  8. Hey thanks, I am newbie and this is very helpful. Starting to get hang of things to work on UIViewController!! Much appreciated post.

  9. Thanks for the nice tutorial, I followed every step but I am not able to see collection view added to my view.
    The only difference is I am trying to add a collection view in custom keyboard extension.
    Do I need to do anything different in case of custom keyboard extension?

    1. Ah spoke to soon. Solution is to move it from viewDidLoad() to viewDidAppear() as the view in custom Keyboard extension hasn’t been instantiated yet 🙂

  10. This is great and great, but I got an error when doing it in a storyboard about being unable to dequeue something something reuse something something. All I had to do to fix it was move the collectionView.registerClass(…) command two lines up, so it came before setting the dataSource and the delegate on the collectionView.

    If you made that change here too, others wouldn’t encounter that error.

Leave a Reply

Your email address will not be published. Required fields are marked *