Every year, Apple promotes its Worldwide Developers Conference, which this year gathered 6000 atendees from more than 70 countries. Sice I am attending, I am using this blog to publish my completely disorganized, not revised, and not-for-public-consumption notes.

DataFlow through SwiftUI

@State not only makes a property managed (in the sense of ensuring updates of all the views that depend on the property when it changes) by SwiftUI; it also makes the property writable. This is relevant because it is a property of a struct (views are now structs) and they are, by default, immutable. Every time a variable is marked as @State it becomes a source of truth (which should be unique for each piece of data).

Important: Views are a function of state, not a sequence of events

A @Binding defines a dependency between a property and a source of truth. Passing a binding to a function requires prepending it with the $ character. Sort of like a reference semantics. If the function updates the variable marked as @Binding, the source of truth is updated as well. @Bindings can be associated to other @Bindings.

One of the main takeaway messages of SwiftUI is that controllers are not really necessary anymore. In ÙIKit, a controller is responsible for keeping views and data in sync and up-to-date. In SwifUI, this task is entirely delegated to the framework.

SwiftUI manages external state changes by treating external sources of change, such as notifications and timers, as publishers. On the main thread, the app should use the .receive(on) operator. This operator takes a second parameter, a handler for the event. This operator is associated to the view.

@EnvironmentObject is a way to encapsulate the model and all of its properties while having binding-like behavior in terms of view update. If one needs to pass around the model through the view hierarchy, it may be more convenient than keeping a set of @States and @Bindings. If an @EnvironmentObject is employed, it can be passed to the view in its initializer.

@BindableObjects are references to external sources of data, for example, data stored in a database. They are developer-managed (by the publisher mechanism). Data referring to @BindableObjectshould be marked as @ObjectBinding.

Introducing Combine and Advances to Foundations

Use DataProtocol instead of [UInt8].

The compression API is now part of Swift. It supports multiple compression algorithms and usage requires just one line of code.

RelativeDataFormatter and ListFormatter as ways to format dates and lists in a locale-specific way. The former refers to differences in the way in which dates are represented in different places. The latter refers to the separators and conjunctions to be used to combine a list of items , e.g., “and”, “y” and “と” or “、” vs “,”.

Operation queue now support barriers to ensure synchronization between tasks. In this manner, one can be sure that there are no pending tasks in the operation queue prior to the execution of an operation. Operation queue also provides functionality for progress reporting.

Combine: A new framework for declarative asynchronous programming. Three main concepts: publishers, subscribers, and operators. Unifies the multiple existing approaches for asynchronous programming into a single set of shared, declarative abstractions.

A single value asynchronously: Future. Multiple values asynchronously: Publisher.

Zip works similary to functional languages, but it combines data from multiple upstream sources into a single downstream tuple. It handles synchronization in the sense that all the fields of the tuple must be filled in in order for it to procede.

Combine Latest converts several inputs into a single value. Requires input from any of the upstream sources to proceed. If only one produces a new values, takes the older ones from the other sources and combines it with the lastest.

Combine in Practice

In Combine, every Publisher describes how they can fail. If the error type is Never, that means that the operation cannot fail or that errors are handled earlier in the stream. Multiple operators for handling errors, such as assertNoFailure, retry, catch, among others. catch can select a recovery publisher to replace the upstream publisher in case an error happens.

The meaning of Just is not clear to me in this case. It is necessary in the catch operator because the latter must return a subscriber and Just seems to work as a publisher wrapper for data.

There are also scheduling operators that pertain to ordering, timing (timing)), and pace (throttle) of data delivery.

Three rules for subscribers:

  1. A subscriber will receive at most a single subscription
  2. Followed by one or more values
  3. Eneded by at most one completion and the latter will mean that either the publisher has finished or failed.

A cancellation terminates a subscription early. Any subscriber that can be cancelled must conform to Cancellable.

Subjects work as both Publisher and Subscriber. Useful for broadcasts. Subjects may be PassThrough or LastValue. The latter keep a record of the last published events that allows subscribers to catch up on previous events.

The @Published annotation can be used to add a publisher to a property.

Integrating SwiftUI

This talk is about integrating SwiftUI with existing apps that already use UIKit and organize their data models without accounting for SwiftUI.

A Hosting Controller is a basic block in integrating SwiftUI. There are UIHostingController, NSHostingController (for AppKit), and WKHostingController. A Hosting Controller brings a SwiftUI view into an existing app built with AppKit or UIKit. There are also HostingViews, embedded a SwiftUI view into the hierarchy of UIKit or AppKit views of an app.

@IBSegueActions are new to Xcode 11. Avoid the need to use prepare:for:segue.

There are protocols for UIKit, AppKit, and WatchKit to wrap existing views into SwiftUI views. These are the Representable protocols, e.g., UIKitRepresentable. They include methods for makeing a view/controller, updateing it, and dismantleing it. The latter is optional. For example, makeUIView, updateUIView, dismantleUIView.

From what I could understand, a view either comes from UIKit(or AppKit or WatchKit) or from SwiftUI, but not both. They can interact, but the two technologies (event-based and declarative) cannot be mixed in the same view, although they can be part of the same view hierarchy.

BindableObject has a single property, didChange, through which changes to an existing data model can publish changes to SwiftUI GUIs.

Improving Battery Life and Performance

MetricKit a new framework for collecting metrics about stuff such as battery level and performance counters.

For battery, some of the available metrics are related to processing, location, display, network, multimedia, camera, accessories. Processing pertains to CPU and GPU** time. Help find issues such as unexpected rendering and CPU spinners. *Location** metrics quantify accuracy buckets, cumulative usage, background usage. Amoong *Display metrics, there is one called Average Pixel Luminance. Different pixels colors consume energy differently and lighter colors consume more. Networking comprise upload and download bytes, connectivity.

CPU metrics include, for example, Hanging metrics, that is, the amount of time that an app spends unresponsive to user requests. They also include disk and application launch metrics. There are also memory metrics, like peak memory, and average suspended memory.

XCTest can be used to collect a number of metrics during the execution of a test. This is straightforward to use; it is a matter of passing objects that represent the metrics to be collected to the measure function in the test function. When using this, it is useful to not attach the debugger to the process and to turn off every possible analyzer or sanitizer, in order to avoid overhead that may mess up the measurement process. It is possible to set baselines for these metrics that determine what would be acceptable values for them. Not meeting the baselines means that the test will fail.

MetricKit can even collect metrics around critical code sections. This functionality leverages mxSignPost.

Types from which we wish to collect performance and battery metrics must conform to the MXMetricManagerSubscriberprotocol.

Xcode Metrics Organizer (under Window > Organizer) is a data analytics service for MetricsKit. Involves sending collected metrics to Apple. Using this does not require any modification to the app. Provides a neat way, for example, to see which components are consuming more battery during the execution of an app, in terms of the % of user battery consumed per day. It also helps to detect how much of the battery is being consumed in the foreground and how much in the background. This functionality is mainly under the Metrics and Energy tabs.