Fixer of explicitly unwrapped optionals

SwiftUI.List selection is not working as expected in Beta 5

Added on by Paul Wood.

So a List can have selected items in it in SwiftUI. However Zoe Smith found an issue with them if you need to have the list preselected and provided to the SwiftUI framework via a BindableObject. The following Script is mostly working, but after some really simple changes the selection no longer works.

At first Glance I thought everything was fine, A the item I selected because it was first, selected all fine. I thought that was that.

Screen+Shot+2019-08-18+at+8.48.36+PM.jpg

Zoe changed the Selected Item from A to C and no longer saw a selection on first load

Screen+Shot+2019-08-18+at+8.48.48+PM.jpg

Tap A though and you got both items visible

Screen+Shot+2019-08-18+at+8.51.39+PM.jpg

I tried to go above and beyond to model something that I consider to be most normal in an Application, and ObservableObject holding @Published arrays and sets to Reference Types. However nothing worked as expected in this setup, not even the editing mode!

Screen+Shot+2019-08-18+at+8.46.13+PM.jpg

So if you are using List selection in SwiftUI in the Beta, I hope this is a warning to what is currently possible and if this bothers you please file a Feedback to Apple about it, I already have, and Zoe will too!

SwiftUI.FetchRequest is lacking dynamic input

Added on by Paul Wood.

Given the new property Wrappers for core Data and the environment variable for managedObjectContext I would expect that the properties would be dynamic in some way to respond to @State, or @ObjectBinding changed that are related to the fetch request the view is managing. currently there is no way to pass something as simple as a NSManagedObjectID to a FetchRequest to populate a new view dynamically based on use section. Nor is it possible to change the attributes of a request (Sorting or Predicate) dynamically based on user input an extremely common use case for Core Data and NSFetchRequest in general.

For example given a List of Int I could have a state that changes them to ascending and descending order

The only way to do this at the moment is an if statement around two FetchRequest that are both built at the view’s startup. Those request would then need to be for the life of that View.

Next I can image a complex query that is built using a user interface with text fields that would build a NSPredicate built on state. Each input could be handled by a SwiftUI view, and have a binding to the output expected. As these outputs change the Fetch request also could change dynamically or only change when the user presses a button.

In short here is the possibility I wish I had:

I’m confident this work is technically possible without first party support using the FetchResults struct and new @Environment(\.managedObjectContext) API

Also my fleeting thought on Twitter and Plea to Luca for future reference :)

I think the ability to support this feature is contingent on the future direction of Property Wrappers out lined here on Swift Evolution

Below is a Gist of my research into the possibility with the current API, using a container view to update a Child view that actually have the list. Each revision compiles, looks correct from the programmers perspective but does NOT render an updated sort order using SwiftUI List view. I hope this misuse of the API (I think I must be a misuse) should be documented in some way before release of SwiftUI. The painful intellectual part is that the binding renders correctly as well as a debug statement that performs the fetchRequest. the fetched results printed from that statement ARE reordered correctly it just does not update the SwiftUI view. So I feel like I’m close but SwiftUI prevents me from displaying the new fetched results for some reason. This code is part of a research project on SwiftUI, Combine with back pressure and CoreData

Lastly I doubt I’ll be alone in trying to have dynamic results with this new API. The framework could give feedback that I am incorrectly using the FetchResults struct.

Some extra Documentation on NSPersistentCloudKitContainer is needed about simulators and devices

Added on by Paul Wood.

This page of Documentation should have a warning saying that a physical device is required to test the automatic syncing of NSPersistentCloudKitContainer

On the page, Mirroring a Core Data Store with CloudKit I can read in the section “Set Up Your Development Environment” A sentence reads “You can run and test Core Data with CloudKit apps using Simulator. You may also test with multiple physical devices logged into the same iCloud account on a good wireless internet connection.” But no explicit warning that the simulator will not have the same experience as a physical device because it does not receive push notifications.

On this page, Synchronizing a Local Store to the Cloud in the Section “Configure the Sample Code Project” a note about using physical devices should be included to see the automatic “live” syncing using push notifications

I had to learn about this via a blog post by Andrew C Bancroft.

I can’t wait to use this feature in iOS 13. Its a great addition to the frameworks and removes a lot of friction of working with CloudKit and CoreData

Combine needs back pressure documentation

Added on by Paul Wood.

For context to this post, Heres some of us talking about it on Twitter:

This lack of documentation will quickly lead to performance issues being the default for many new to the concept of Reactive programming. An overview of back-pressure in Combine should be written and linked to from this page covering Combine in General:

Demand isn’t even mentioned on this page of Documentation about Subject.

Demand and how it works could be better explained on this page on Subscribers are the source of truth for demand:

The returned value for demand should be documented on these pages:

CurrentValueSubject and PassthroughSubject are implemented with demand unlimited. I assume this is because they must conform to both a publisher as well as a subscriber. This really should be explained in their documentation to prevent people from using them to implement back pressure and sharing the results to other subscribers using .share()

Need some inspiration on how to start documenting the overall subject? Please look at my personal mental model on back pressure here. With many more links of inspiration, for example RxJava’s documentation, are in the post.

Displaying Different Data Types in the same list with SwiftUI

Added on by Paul Wood.

SwiftUI is new, and the Swift language is very powerful. But the newness of the framework and the extensibility of the language has lead me into some deep rabbit holes. I’m not alone in this and I think @ishabazz went down a rabbit hole I had been down previously when I saw this thread on Twitter. I didn’t feel like I knew exactly why I’ve hit this issue before and how I could avoid it consistently in the future.

Let’s start simple to lay the SwiftUI groundwork and then work our way to the problem

We have a list of strings that conform to Identifiable and our SwiftUI can render it easily. The types are homogenious, of the same type, but oftentimes our data comes to us of diverse types or heterogeneous. We should plan for this eventuality ahead of time. For example product teams often want to add a new feature to the top or bottom of a list that is retrieved from at a different API endpoint. So let’s look at what some Swift programmers will want to do with SwiftUI. Start with a protocol! In our case Nameable. Lets define the attributes of a similar model we would like to display and the two models conform to that Nameable protocol. We should be able to render that!

The code seems all well in good in a gist, It’s understandable that we want to have two types that both conform to a common protocol, which (we hope) provides an interface for SwiftUI to render their content into.

But as we press the play button in the playground we find that this won’t compile. Even though we can reason about it, the compiler does not.

Here we can see that we have two compiler warnings complaining about the same issue in different ways

Here we can see that we have two compiler warnings complaining about the same issue in different ways

Now it’s time to take a break from reading my code and get to our required reading for understanding this problem. Rob Napier has a great talk on Generic Swift. You can follow him on twitter and subscribe to his blog. I really recommend you do both if you’ve found this subject interesting enough to read to this point.

Our issue comes down to a trick we’ve used with NSArray for years, defining an NSArray of NSObjects that conform to an Objective -C Protocol and only using the interface defined by that protocol when we access the items in that array. I used this a lot in the past and it made my intent clear that the array was only for using the parts of an NSObject that are in that protocol. However in Swift we have different types than Obj-C and we enforce those types with vigors. In our case we have an Array Type, that must be filled with concrete objects. Swift protocols are not concrete and therefore we have the first error.

The next error restates the issue from the perspective of the array being passed to the List must have elements that conform to Hashable. While we think to ourselves that yeah they both do, we are missing the issue again with how an Array works. An Array in swift must be of filled with concrete objects of the same type. Protocols are not concrete and therefore we cannot create this array.

We are using the above interface for a List and we can see that SelectionValue must be Hashable, but again it is of one type SelectionValue. So one concrete type must be the contents of the array that we pass into this initializer.

Even though they both look alike, have the same properties, and probably consist of the exact same raw assembly code the Swift compiler will not allow you to mix and match them when put into a Swift Array. Under the hood Swift is making two different interfaces, one for Name and one for Surname of different types.

If you want to know why I’ll direct you back to Rob Napier’s talk on Generics. Its great and he gets into the issue of Swift protocols within Arrays, and it is to do with Generics. The Swift Array uses generics to implements algorithms that manipulate a data structure of the same type. In short if you want to put something in an Array don’t try to be tricky with Protocols with associated Types and generics. Instead you need to keep it simple.

In my case I went back to the tried and true of just writing some more code than I thought I should to get my point across. And I started not with a Protocol but instead a concrete type. I created a third struct that would display the names and give us a Heterogenous collection.

This looks pretty tedious, two types with the exact same interface, just by a different name requiring a third type just to wrap them to be displayed in a List. As those types scale we need another initializer for the Holder. We should realize that this could be error prone.

But generics can help us in this case to remove the tedious initializers. So long as an object conforms to Nameable, we can create initializers of NameHolder for all of them. Now the swift compiler is our tedious code writing templating engine.

The take away from Rob’s talk that I’m using is that generics are for algorithms. And in this case my algorithm is simple, take the known attributes “name” and put it into the holder. If I add a third type that I want to put into the list, MiddleName for example, I don’t need to write a new initializer, unless I want to, which is also perfectly fine.

So there is my deep dive into a very simple problem, a problem that I was able to solve one way with Obj-C because of its protocols. But needed to use a different way, with Swift and SwiftUI. I think its much simpler, leverages the type system in a new way to me and should lead to clear code in your projects as well.

Apple's Combine and reactive programming with Back pressure

Added on by Paul Wood.

When Apple released Combine in June 2019 those of use using RxSwift already felt justified if not vindicated that we had been making the right architectural decisions. This new framework, built into the foundation of the platform is going to increase the number of developers using reactive methods to solve problems exponentially and help the developer community as a whole solve problems in a consistent manner with less code.

I don’t want to give a rundown of what Combine and Reactive programming are. Nor do I want to compare and contrast Combine with RxSwift, which was my chosen flavor of Reactive Programming on Apple’s platforms before Combine. Please check out Casey Liss’s article for an overview of Combine. And if you are more an auditory learner check out Casey and John Sundell on the Swift by Sundell podcast.

I wanted to deep dive into something Combine has and RxSwift does not, Back pressure. This is a feature of Combine that allows a communication flow both up and down a reactive chain. That data flow is best considered, Elements move down the stream and Demand is returned up the stream to signify if more work can be done.

Everything is mental models when learning a new concept. After playing with the new API’s a little mental model for the different moving parts of Combine that deal with back pressure came to me, Marbles in a Funnel

At this point if you haven’t been to RxMarbles.com you are doing yourself a disservice, go check that site out first. Marbles are a great mental model for elements of a stream. They flow and roll place to place but they are also one unit and concrete unlike a stream of water. Mental models using liquids don’t stick for me when thinking about back pressure because there is not a single “unit” of water. A more humorous mental model for elements combining the two could be a lazy river or rafting ride with lots of people in inner-tubes flowing through turbulent water features.

Marble, Element - an element published by a Publisher

Marble, Element - an element published by a Publisher

Funnel, Publisher - represents work that can be done but a publisher, such as reading a line from a CSV file

Funnel, Publisher - represents work that can be done but a publisher, such as reading a line from a CSV file

Tube, Buffer - a tube that stacks up elements

Tube, Buffer - a tube that stacks up elements

Gate, Subscriber - the number of elements that a subscriber can handle. How many marbles would come out each time I opened it? The value returned by the subscriber for Demand can be thought of as the width of this gate creating back pressure so the marbles stay in the buffer

Gate, Subscriber - the number of elements that a subscriber can handle. How many marbles would come out each time I opened it? The value returned by the subscriber for Demand can be thought of as the width of this gate creating back pressure so the marbles stay in the buffer

Bringing it all together

I wrote up an example project that I hope will help others experiment with back pressure with a real world use case. You can find it on Github as PaulWoodiii/Combine-Backpressure-Research-CSV.

In the example project the “marbles” are rows in a Comma Separated Value file. each new row is sent down a reactive chain to a subscriber that does some work. As part of the published values a simple mapping from an array of Strings to a value type “NameType” helps us see how data can be transformed from a raw text file to a usable data structure that can be rendered in a User interface, or saved to a database.

I’ve added a simulation of back pressure by creating my own Subscriber based on Sink called SlowSink that sleeps the thread for some time. This creates back pressure and using breakpoints a developer can see when work is done. I’ve shared a few breakpoints in the project file to get readers started.

I hope this helps other developers get started learning how back pressure in reactive steams can be used, debugged and tested. However I know it is not complete and would recommend anyone who wants to really dive into the deep end to read documentation on back pressure written for RxJava.

I can assume that Apple has been working on Combine for client side development for ease of use when it comes to developing asynchronous code. RxSwift got along very well without back pressure for client side development though. My suspicion is that the inclusion of back pressure hints that Apple is aware of its utility for server side development. With back pressure developers can read massive files, while keeping a low memory footprint.

SwiftUI: Lets get started

Added on by Paul Wood.

When one of the top developers and teachers of how to implement UICollectionViews ask a question on Twitter and you know the answer it feels nice!