Collectives on Stack Overflow. Learn more. How to make a simple collection view with Swift Ask Question. Asked 6 years, 9 months ago. Modified 1 year, 1 month ago. Viewed k times. The answer below is my attempt to learn to do this.
Suragch Suragch k gold badges silver badges bronze badges. Add a comment. Sorted by: Reset to default. Highest score default Date modified newest first Date created oldest first. This project has been tested with Xcode 10 and Swift 4. Create a new project It can be just a Single View App.
Open ViewController. You could also add the UICollectionViewFlowLayout protocol to change the size of the views programmatically, but it isn't necessary. We are just putting simple strings in our grid, but you could certainly do images later. You can Control-drag. Right click Collection View in the Document Outline. Then click and drag the plus arrow up to the View Controller.
Finished Here is what it looks like after adding constraints to center the Label in the cell and pinning the Collection View to the walls of the parent. Making Improvements The example above works but it is rather ugly. Cell spacing Changing the minimum spacing between cells to a smaller value makes it look better. Cell shape If you want rounded corners, a border, and the like, you can play around with the cell layer.
Changing the color when tapped It makes for a better user experience when the cells respond visually to taps. Alex Zavatone 3, 35 35 silver badges 53 53 bronze badges. Im using a custom layout — Gerald. If you didn't hook up the outlet by control-dragging from the label in the storyboard to the IBOutlet for myLabel in code, you would get a crash like this. I wish Apple's documentation was as easy to read as this explanation — elmarko.
Show 24 more comments. For swift 4. Abhishek Mishra Abhishek Mishra 1, 15 15 silver badges 32 32 bronze badges. Saranjith Saranjith DummyCollectionCell cell. Ryan 9, 10 10 gold badges 44 44 silver badges 55 55 bronze badges.
Aditya Sharma Aditya Sharma 4 4 silver badges 18 18 bronze badges. Dilraj Singh Dilraj Singh 10 10 silver badges 12 12 bronze badges. The Overflow Blog. Underscoring or dunder-scoring the importance of native type methods in You don't even have to set the reuse identifier from IB, because we have to register our reusable views inside the source code, so just set the cell class and connect your outlets.
Providing the size for the flow layout delegate is also pretty straightforward, however sometimes I don't really get the naming conventions by Apple. Once you have to switch a kind, and the other time there are exact methods for specific kinds. Starting from iOS9 section headers and footers can be pinned to the top or bottom of the visible bounds of the collection view. What about complex cases, like using multiple kinds of cells in the same collection view? Things can get pretty messy with index paths, so that's why I re-invented something better based on a technique how to build advanced user interfaces with collection views showcased by Apple back at WWDC Now you know the basics, so why don't we get straight to the point?
I'll show you my best practice of building great user interfaces by using my MVVM architecture based CollectionView micro framework. By the way this framework is a great fit if you are planning to construct input forms or complex lists. I'll explain the components real quick and after that you'll learn how to use them to build up the Apple music-ish layout that I was talking about in the beginning.
The first problem with collection views is the size calculation. Thats good, but still you have to mess with index paths, trait collections, frames and many more in order to have a simple 2, 4, n column layout that adapts on every device. This is the reason why I've created a really basic grid system for size calculation.
With my grid class you can just set the number of columns and get back the size for x amount of columns, "just like" in web based css grid systems. Registering and reusing cells should and can be automated in a type safe manner. You just want to use the cell, and you shouldn't care about reuse identifiers and cell registration at all.
I've made a couple helper methods in order to make the progress more pleasant. Reuse identifiers are derived from the name of the cell classes, so you dont't have to worry about anymore. This is a practice that most of the developers use.
Filling up "template" cell with real data should be the task of a view model. This is where MVVM comes into play. I've made a generic base view model class, that you should subclass. I'm trying to emphasize that you don't want to mess with index paths, you just want to put your data together and that's it.
In the past I've struggled more than enough with "unnecessary index path math", so I've made the section object as a simple container to wrap headers, footers and all the items inside of the section. The result? Generic data source class that can be used with multiple cells without any row or section index calculations.
So in order to make all the things I've mentioned above work, I needed to implement the collection view delegate, data source, and flow layout delegate methods. That's how my source class was born. Everything is implemented here, and I'm using sections, view models the grid system to build up collection views. But hey, enough from this theory, let's see it in practice.
How to make a any list or grid layout hassle free? Well, as a first step just add my CollectionView framework as a dependency. Don't worry you won't regret it, plus it supports Xcode 11 already, so you can use the Swift Package Manager, straight from the file menu to integrate this package. This step is identical with the regular setup, except that your cell have to be a subclass of my Cell class.
Add your own cell and do everything as you would do normally. Just pick a model object. It can be anything, but my approach is to make a new struct or class with a Model suffix. This way I know that models are referencing the collection view models inside my reusable components folder.
Congratulations you're done with your first collection view. What if we make a cell that contains a collection view and we use the same method like above? A collection view containing a collectionview U I Collectio n View ception!!! It's completely possible, and really easy to do, the data that feeds the view model will be a collection view source object, and you're done.
Effortless, magical and super nice to implement, also included in the example app. Multiple sections? No problem, circular images? That's also a piece of cake, if you had read my previous tutorial about cirular collection view cells , you'll know how to do it, but please check out the source code from gitlab and see it for youself in action. User events can be handled very easy, becuse view models can have delegates or callback blocks, it only depends on you which one you prefer.
Click on it, and in the window with the various capabilities that appears, double click on the App Sandbox. A new section will appear in front of you. Here you can choose which resources and folders app will have access to. The above changes are written in the PhotosApp. Time to set its constraints. Set 20px to Top, Leading and Trailing , and 8px to Bottom as shown next:. Similarly to other Cocoa controls we met in previous macOS tutorials, the collection view is contained into a clip view, which in turn is contained into a scroll view.
With the collection view selected, open the Inspectors pane and go to the Attributes inspector. By default, the Flow layout is selected, and right below there are several text fields where you can specify the details of it. You can also set the scroll direction by choosing Vertical or Horizontal in the respective popup button. The default option is Vertical, which means that if there are enough elements to make the collection view scrollable, scrolling will be up and down to the vertical axis.
The layout-related text fields you see here can also be found if you expand the Collection View object in the Document Outline and you select the Collection View Flow Layout element. By doing so, in the Attributes inspector you can set the scrolling direction. Layout details can be set in the Sizes inspector. Back to the collection view object itself and in the Attributes inspector. To do so, just check the Use Alternating Colors check box and set the primary and secondary colors right below.
Note that if the color you apply has no effect, then you should check if the container controls clip view and scroll view are not drawing their own background colors. There are three check boxes there:. As I said right before, the default layout is set to Flow automatically.
Actually, even in that case you can skip setting your custom layout here as you can do it programmatically as well. The only other option besides Flow that remains is the Grid layout style. By using it, items of the collection view will be displayed as a grid. Use the provided text fields in the Attributes inspector to specify the layout details.
Even though any Flow layout settings made in the Attributes inspector have effect in the collection view, settings made for the Grid layout do not! Then, open the Connections inspector and locate the collectionView outlet. Click and drag until the mouse is above the collection view, then release.
The connection will be made. In the templates window that will appear, choose the Cocoa Class template and click Next. Finally, click on the Create button to let Xcode create the two files. Follow the next steps:. This image view should be connected to an IBOutlet property so we can access it programmatically and set an image to it. An image view IBOutlet property is among them. Click on the Connections inspector to find all outlets provided automatically.
For now, click on the circle on the right side of the image view property, and drag to the image view object inside the view to make the connection. An additional action is required for that: To add a collection view item object. To do so:. Once you have it, click on it and open the Identity inspector in the Inspectors pane. In the Class field type PhotoItem. What we just managed is to indicate that this XIB file represents a collection view item, we related it to the PhotoItem class, and we assigned to it a unique identifier so we can refer to it later on programmatically.
Switch to the PhotoItem. Background colors in Cocoa views are drawn in their layers, but views have no layers by default. We can round the corners a bit as well. Add the following line to the viewDidLoad method:. Next, we need to determine when the view is selected or not, and to change the background color accordingly. The above code does what exactly I described right before. So, open the ViewController. Our starting point will be the definition of a new method in the ViewController class:.
The first thing we have to do is to set the ViewController class as the delegate and datasource of the collection view:. With it we define the border type of the scroll view that contains the collection view. So, instead of writing multiple times:. Why not to create a property in the ViewController class with it and then simply access it?
Go to the beginning of the ViewController class in the section with the declarations of the various properties. Add this:. The basic properties for the collection view are set, and the item to use has also been registered. Of course, that distance can be increased if the window becomes big enough so items are laid out to cover the available space horizontally. The last two properties define the spacing among items both horizontally and vertically.
However, they do not define any padding between items and the collection view sides. To change that, we can set the sectionInset property:. With the above line, items will be 20px away from each side of the collection view. Also, sections will have the same distance among them. It can be used to specify the size of the items in the collection view:.
Finally, once the flow layout configuration is finished, we have to assign it to the collection view:. This method must be invoked somewhere. Go to the configureCollectionView and right after all existing statements add this:. Even though flow layout is usually the must-go solution in collection views, let me show you fast how you can use the grid layout instead.
What we just did right before regarding the flow layout is pretty much what we also do to set up a grid layout. We already met a couple of them:. However, in grid layout it is. Here you have the option to set a minimum and maximum size for the presented items.
For simplicity here, we assign the same size to both:. However, I would recommend to keep it commented out at first and wait until we finish with the app preparation. Once the app works properly with the flow layout, then switch to grid and play around with it to find out its pros and cons. As said in the beginning of this post, the photos array is going to be providing the data displayed on the collection view. Each item in this array is another array that will be containing PhotoItem objects see the PhotoInfo.
Such an object has two properties only, one for the URL of the source file of a photo, and one for the thumbnail image a NSImage object of the photo. Each inner array in the photos collection represents photos loaded from a specific folder on the computer. In collection view, the number of inner arrays specify the number of sections that the collection view should show. This is the number of PhotoItem objects in each inner array of the photos collection:.
In it we must either create or reuse a collection view item that will display the actual photo for any given index path of the collection view:. The makeItem withIdentifier:for: method above is the one that does the job.
It accepts the item identifier and the index path as arguments, and either initializes a new PhotoItem object, or it reuses a previously created one. Note: All the above should look easy and familiar to you if you have prior experience on table views. With the following delegate method the ViewController class is being notified when an item is clicked:. In the above code, lastPathComponent property will give the actual file name along with the extension.
Note: The optional unwrapping taking place in the second guard statement could have been written in the first guard. With the next delegate method we are actually specifying the size of each item in the collection view. The collection view is now fully configured, so we can move forward to other aspects of the app that have to do with the collection view and perform actions on it.
The reason for that is that the body of the createThumbnails method is missing, even though that method has been defined in the ViewController class. In fact, all that code is already implemented in the starter project. During the past two years, in iOS 13 and 14, Apple have made a number of significant changes to UICollectionView and the various types that surround it.
Not only have new APIs been introduced, but the fundamental concepts and conventions used to build collection views have shifted to embrace a series of modern programming trends — such as declarative UI development, composition, and strong type safety. Quickly build native user interfaces visually, and publish them instantly, without having to submit updates to the App Store. Judo experiences fit seamlessly into your existing app, and is perfect for features like onboarding and marketing offers.
Build faster, release on your timeline, and save coding for the hard stuff. One of the most commonly faced problems when working with collection views on operating systems prior to iOS 13 comes from the fact that all updates need to be manually coordinated by the programmer using APIs like performBatchUpdates , which in turn very often results in crashes and errors when those updates end up out of sync with the underlying data model being used. By default, a diffable data source will also automatically determine what kind of animations that should be used when applying a given snapshot, which is something that can be tweaked by passing additional arguments to the apply method that we called above.
The concept of cell registrations is new in iOS 14, and enables us to encapsulate the registration of a given UICollectionViewCell subclass — as well as our cell configuration code — within a dedicated object. The benefit of that is both that we no longer have to remember to always register the correct cell type for a given reuse identifier, and that we again get complete type safety within our cell configuration code — no more cell type casting required.
With the above in place, we can now go back to our makeDataSource method from before and modify our cellProvider closure to simply return the result of dequeuing a cell using our new registration implementation — like this:.