Swift
Understanding how DispatchQueue.sync can cause deadlocks
Published on: September 21, 2020As a developer, you'll come across the term "deadlock" sooner or later. When you do, it's usually pretty clear that a deadlock is bad (the name alone implies this) and if you've experienced one in your code, you'll know that your application crashes with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) when a deadlock occurs. A few weeks ago, I wrote about dispatching code synchronously and asyncronously. Several people pointed out that that post does not mention deadlocks. Instead of making that post longer and more complicated, I decided to make this week's post all about deadlocks and understanding what they are. If you're...
Read more...Dispatching async or sync? The differences explained
Published on: August 31, 2020When writing iOS apps, we regularly run into code that is asynchronous. Sometimes you know you're writing something that will run asynchronously and other times you're passing a completion handler to code that may or may not run asynchronously on a different dispatch queue. If you're familiar with using DispatchQueue.main, you have probably written code like this: DispatchQueue.main.async { // do something } And while writing this, you may have encountered a second method on DispatchQueue.main called sync. In this week's post I will explain the difference between sync and async, and you will learn when you might want to...
Read more...Understanding Swift’s OptionSet
Published on: August 18, 2020Every once in a while I look at a feature in Swift and I fall down a rabbit hole to explore it so I can eventually write about it. The OptionSet protocol is one of these Swift features. If you've ever written an animation and passed it a list of options like this, you have already used OptionSet: UIView.animate( withDuration: 0.6, delay: 0, options: [.allowUserInteraction, .curveEaseIn], animations: { myView.layer.opacity = 0 }, completion: { _ in }) You may not have realized that you weren't passing an array to the options parameter, and that's not surprising. After all, the options...
Read more...Using Codable with Core Data and NSManagedObject
Published on: August 3, 2020If you've ever wanted to decode a bunch of JSON data into NSManagedObject instances you've probably noticed that this isn't a straightforward exercise. With plain structs, you can conform your struct to Codable and you convert the struct from and to JSON data automatically. For an NSManagedObject subclass it's not that easy. If your Core Data data model is configured to automatically generate your entity class definitions for you (which is the default), you may have tried to write the following code to conform your managed object to Decodable: extension MyManagedObject: Decodable { } If you do this, the compiler...
Read more...Setting up a Core Data store for unit tests
Published on: July 27, 2020Unit testing is an important skill in the toolbox of any engineer. Knowing how to write a reliable, robust test suite helps you write reliable and robust code. If you've followed my introduction to unit testing part one and part two, or if you're experienced with unit testing you know that your tests should run isolated from any other tests. You also know that you should make sure that your test relies on as few external dependencies as possible. When you want to test your Core Data code, it might not be immediately obvious how you can test your Core...
Read more...How to change a UICollectionViewListCell’s separator inset
Published on: June 25, 2020In 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...How to add a custom accessory to a UICollectionViewListCell?
Published on: June 24, 2020Apple 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, 2020In 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, 2020In 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, 2020In 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...