Recent articles

Jump to a random post

Handling deeplinks in iOS 14 with onOpenURL

Published on: July 6, 2020

Starting with iOS 14, we can write apps that are fully built using SwiftUI, dropping the need to have AppDelegate and SceneDelegate files entirely. For as long as I remember, I've handled deeplinks in my AppDelegate and for the past year in the SceneDelegate. So when Apple introduced developers to this new @main annotated App struct style of building apps, I'm sure we all had the same question on our mind. How does the new App struct work with deeplinks and other tasks that are normally performed in the AppDelegate? Luckily, Apple engineers made sure that handling deeplinks in our...

Read more...

Implementing an infinite scrolling list with SwiftUI and Combine

Published on: June 29, 2020

Tons of apps that we build feature lists. Sometimes we build lists of settings, lists of todo items, lists of our favorite pictures, lists of tweets, and many other things. Some of these lists could scroll almost endlessly. Think of a Twitter timeline, a Facebook feed or a list of posts on Reddit. You might argue that knowing how to build a list that scrolls infinitely and fetches new content whenever a user reaches the end of the list is an essential skill of any iOS developer. That's why as one of my first posts that covers SwiftUI I wanted...

Read more...

Using multi-colored icons in iOS 14 with SF Symbols 2

Published on: June 28, 2020

Apple introduced SF Symbols in iOS 13. SF Symbols allow developers to easily integrate icons in their apps. The SF Symbols icons integrate really well with the default system font, and provide a consistent look throughout the system. In iOS 14, Apple added over 750 new icons to the SF Symbols library for developers to use in their apps. Additionally, Apple has expanded SF Symbols to include multi-colored icons. For a full overview of the available SF Symbols that are available, including the newly added and multicolor symbols, download the SF Symbols 2 app from Apple's SF Symbols page. To...

Read more...

How to change a UICollectionViewListCell’s separator inset

Published on: June 25, 2020

In WWDC2020's session Lists in UICollectionView a slide is shown where a UICollectionViewListCell's separator inset is updated by assigning a new leading anchor to separatorLayoutGuide.leadingAnchor. Unfortunately, this doesn't work in when you try to do it. To set the separator inset for a UICollectionViewListCell you can update the leading anchor constraint by overriding updateConstraints in a UICollectionViewListCell subclass. Setting the anchor in init will cause the system to override your custom anchor leaving you with the default inset. override func updateConstraints() { super.updateConstraints() separatorLayoutGuide.leadingAnchor.constraint(equalTo: someOtherView.leadingAnchor, constant: 10).isActive = true } You can set the leadingAnchor constraint just like you would...

Read more...

What’s new with UICollectionView in iOS 14

Published on: June 25, 2020

Last year, the team that works on UICollectionView shipped massive improvements like compositional layout and diffable data sources. This year, the team went all out and shipped even more amazing improvements to UICollectionView, making UITableView obsolete through the new UICollectionViewCompositionalLayout.list and UICollectionLayoutListConfiguration. This new list layout allows you to create collection views that look and function identical to UITableView. When paired with UICollectionViewListCell your collection view can support features that used to only be available to UITableView. For instance, you can now add swipe actions to a cell and set its accessories to add certain affordances on a cell like...

Read more...

How to add a custom accessory to a UICollectionViewListCell?

Published on: June 24, 2020

Apple provides several accessory types that you can use to apply certain affordances to a UICollectionViewListCell. However, sometimes these options don't suit your needs and you're looking for something more customizable. To add a custom accessory to a list cell instead of a standard one, you use the .custom accessory type. The initializer for this accessory takes a UICellAccessory.CustomViewConfiguration that describes how your accessory should look and where it's positioned. Let's dive right in with an example: // create the accessory configuration let customAccessory = UICellAccessory.CustomViewConfiguration( customView: UIImageView(image: UIImage(systemName: "paperplane")), placement: .leading(displayed: .always)) // add the accessory to the cell...

Read more...

How to add accessories to a UICollectionViewListCell?

Published on: June 24, 2020

In iOS 14 Apple added the ability for developers to create collection views that look and feel like table views, except they are far, far more powerful. To do this, Apple introduced a new UICollectionViewCell subclass called UICollectionViewListCell. This new cell class allows us to implement several tableviewcell-like principles, including accessories. Adding accessories to a cell is done by assigning an array of UICellAccessory items to a UICollectionViewListCell's accessories property. For example, to make a UICollectionViewListCell show a disclosure indicator that makes it clear to a user that they will see more content if they tapp a cell, you would...

Read more...

How to add custom swipe actions to a UICollectionViewListCell?

Published on: June 24, 2020

In iOS 14 Apple added the ability for developers to create collection views that look and feel like table views, except they are far, far more powerful. To do this, Apple introduced a new UICollectionViewCell subclass called UICollectionViewListCell. This new cell class allows us to implement several tableviewcell-like principles, including swipe actions. You can add both leading and trailing swipe actions to a cell by assigning a UISwipeActionsConfigurationProvider instance to the collection view's UICollectionLayoutListConfiguration object's leadingSwipeActionsConfigurationProvider and trailingSwipeActionsConfigurationProvider properties. This swipe actions provider is expected to return an instance of UISwipeActionsConfiguration. A UISwipeActionsConfiguration is created using an array of one...

Read more...

Configure collection view cells with UICollectionView.CellRegistration

Published on: June 24, 2020

In iOS 14 you can use the new UICollectionView.CellRegistration class to register and configure your UICollectionViewCell instances. So no more let cellIdentifier = "MyCell", no more collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) and best of all, you no longer need to cast the cell returned by dequeueReusableCell(withReuseIdentifier:for:) to your custom cell class. Adopting UICollectionView.CellRegistration in your project is surprisingly straightforward. For demo purposes I created the following UICollectionViewCell subclass: class MyCollectionViewCell: UICollectionViewCell { let label = UILabel() required init?(coder: NSCoder) { fatalError("nope!") } override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor, constant: 8).isActive = true label.leadingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.leadingAnchor, constant:...

Read more...

What’s the difference between @StateObject and @ObservedObject?

Published on: June 23, 2020

Views in SwiftUI are thrown away and recreated regularly. When this happens, the entire view struct is initialized all over again. Because of this, any values that you create in a SwiftUI view are reset to their default values unless you've marked these values using @State. This means that if you declare a view that creates its own @ObservedObject instance, that instance is replaced every time SwiftUI decides that it needs to discard and redraw that view. If you want to see what I mean, try running the following SwiftUI view: class DataSource: ObservableObject { @Published var counter = 0...

Read more...