www.swiftbysundell.com Open in urlscan Pro
2606:4700:20::681a:2ec  Public Scan

Submitted URL: http://www.swiftbysundell.com//
Effective URL: https://www.swiftbysundell.com//
Submission: On September 30 via api from US — Scanned from US

Form analysis 0 forms found in the DOM

Text Content

Articles, podcasts and news about Swift development, by John Sundell.

 * Articles
 * Basics
 * Podcast
 * Discover
 * Subscribe
 * About
 * Search

 * RSS feed
 * Categories


 * SWIFTUI


 * CONCURRENCY


 * GENERICS


 * UNIT TESTING


RECENTLY PUBLISHED

Show compact list


 * SWIFTUI VIEWS VERSUS MODIFIERS
   
    * swiftui
   
   Published on 27 Feb 2023
   Discover page available: SwiftUI
   
   One of the most interesting aspects of SwiftUI, at least from an
   architectural perspective, is how it essentially treats views as data. After
   all, a SwiftUI view isn’t a direct representation of the pixels that are
   being rendered on the screen, but rather a description of how a given piece
   of UI should work, look, and behave.
   
   That very data-driven approach gives us a ton of flexibility when it comes to
   how we structure our view code — to the point where one might even start to
   question what the difference actually is between defining a piece of UI as a
   view type, versus implementing that same code as a modifier instead.
   
   Take the following FeaturedLabel view as an example — it adds a leading star
   image to a given text, and also applies a specific foreground color and font
   to make that text stand out as being “featured”:
   
   struct FeaturedLabel: View {
       var text: String
   
       var body: some View {
           HStack {
               Image(systemName: "star")
               Text(text)
           }
           .foregroundColor(.orange)
           .font(.headline)
       }
   }
   
   While the above may look like a typical custom view, the exact same rendered
   UI could just as easily be achieved using a “modifier-like” View protocol
   extension instead — like this:
   
   extension View {
       func featured() -> some View {
           HStack {
               Image(systemName: "star")
               self
           }
           .foregroundColor(.orange)
           .font(.headline)
       }
   }
   
   Here’s what those two different solutions look like side-by-side when placed
   within an example ContentView:
   
   struct ContentView: View {
       var body: some View {
           VStack {
               // View-based version:
               FeaturedLabel(text: "Hello, world!")
   
               // Modifier-based version:
               Text("Hello, world!").featured()
           }
       }
   }
   
   One key difference between our two solutions, though, is that the latter can
   be applied to any view, while the former only enables us to create
   String-based featured labels. That’s something that we could address, though,
   by turning our FeaturedLabel into a custom container view that accepts any
   kind of View-conforming content, rather than just a plain string:
   
   struct FeaturedLabel<Content: View>: View {
       @ViewBuilder var content: () -> Content
   
       var body: some View {
           HStack {
               Image(systemName: "star")
               content()
           }
           .foregroundColor(.orange)
           .font(.headline)
       }
   }
   
   Above we’re adding the ViewBuilder attribute to our content closure in order
   to enable the full power of SwiftUI’s view building API to be used at each
   call site (which, for example, lets us use if and switch statements when
   building the content for each FeaturedLabel).
   
   We might still want to make it easy to initialize a FeaturedLabel instance
   with a string, though, rather than always having to pass a closure containing
   a Text view. Thankfully, that’s something that we can easily make possible
   using a type-constrained extension:
   
   extension FeaturedLabel where Content == Text {
       init(_ text: String) {
           self.init {
               Text(text)
           }
       }
   }
   
   Above we’re using an underscore to remove the external parameter label for
   text, to mimic the way SwiftUI’s own, built-in convenience APIs work for
   types like Button and NavigationLink.
   
   With those changes in place, both of our two solutions now have the exact
   same amount of flexibility, and can easily be used to create both text-based
   labels, as well as labels that render any kind of SwiftUI view that we want:
   
   struct ContentView: View {
       @State private var isToggleOn = false
   
       var body: some View {
           VStack {
               // Using texts:
               Group {
                   // View-based version:
                   FeaturedLabel("Hello, world!")
   
                   // Modifier-based version:
                   Text("Hello, world!").featured()
               }
   
               // Using toggles:
               Group {
                   // View-based version:
                   FeaturedLabel {
                       Toggle("Toggle", isOn: $isToggleOn)
                   }
   
                   // Modifier-based version:
                   Toggle("Toggle", isOn: $isToggleOn).featured()
               }
           }
       }
   }
   
   So at this point, we might really start to ask ourselves — what exactly is
   the difference between defining a piece of UI as a view versus a modifier? Is
   there really any practical differences at all, besides code style and
   structure?
   
   Well, what about state? Let’s say that we wanted to make our new featured
   labels automatically fade in when they first appear? That would require us to
   define something like a @State-marked opacity property that we’d then animate
   over using an onAppear closure — for example like this:
   
   struct FeaturedLabel<Content: View>: View {
       @ViewBuilder var content: () -> Content
       @State private var opacity = 0.0
   
       var body: some View {
           HStack {
               Image(systemName: "star")
               content()
           }
           .foregroundColor(.orange)
           .font(.headline)
           .opacity(opacity)
   .onAppear {
       withAnimation {
           opacity = 1
       }
   }
       }
   }
   
   At first, participating in the SwiftUI state management system might seem
   like something that only proper view types can do, but it turns out that
   modifiers have the exact same capability — as long as we define such a
   modifier as a proper ViewModifier-conforming type, rather than just using a
   View protocol extension:
   
   struct FeaturedModifier: ViewModifier {
       @State private var opacity = 0.0
   
       func body(content: Content) -> some View {
           HStack {
               Image(systemName: "star")
               content
           }
           .foregroundColor(.orange)
           .font(.headline)
           .opacity(opacity)
   .onAppear {
       withAnimation {
           opacity = 1
       }
   }
       }
   }
   
   With the above in place, we can now replace our previous featured method
   implementation with a call to add our new FeaturedModifier to the current
   view — and both of our two featured label approaches will once again have the
   exact same end result:
   
   extension View {
       func featured() -> some View {
           modifier(FeaturedModifier())
       }
   }
   
   Also worth noting is that when wrapping our code within a ViewModifier type,
   that code is lazily evaluated when needed, rather than being executed
   up-front when the modifier is first added, which could make a difference
   performance-wise in certain situations.
   
   So, regardless of whether we want to change the styles or structure of a
   view, or introduce a new piece of state, it’s starting to become clear that
   SwiftUI views and modifiers have the exact same capabilities. But that brings
   us to the next question — if there are no practical differences between the
   two approaches, how do we choose between them?
   
   At least to me, it all comes down to the structure of the resulting view
   hierarchy. Although we were, technically, changing the view hierarchy when
   wrapping one of our featured labels within an HStack in order to add our star
   image, conceptually, that was more about styling than it was about structure.
   When applying the featured modifier to a view, its layout or placement within
   the view hierarchy didn’t really change in any meaningful way — it still just
   remained a single view with the exact same kind of overall layout, at least
   from a high-level perspective.
   
   That’s not always the case, though. So let’s take a look at another example
   which should illustrate the potential structural differences between views
   and modifiers a bit more clearly.
   
   Here we’ve written a SplitView container, which takes two views — one
   leading, and one trailing — and then renders them side-by-side with a divider
   between them, while also maximizing their frames so that they’ll end up
   splitting the available space equally:
   
   struct SplitView<Leading: View, Trailing: View>: View {
       @ViewBuilder var leading: () -> Leading
       @ViewBuilder var trailing: () -> Trailing
   
       var body: some View {
           HStack {
               prepareSubview(leading())
               Divider()
               prepareSubview(trailing())
           }
       }
   
       private func prepareSubview(_ view: some View) -> some View {
           view.frame(maxWidth: .infinity, maxHeight: .infinity)
       }
   }
   
   Just like before, we could definitely achieve the exact same result using a
   modifier-based approach instead — which could look like this:
   
   extension View {
       func split(with trailingView: some View) -> some View {
           HStack {
               maximize()
               Divider()
               trailingView.maximize()
           }
       }
   
       func maximize() -> some View {
           frame(maxWidth: .infinity, maxHeight: .infinity)
       }
   }
   
   However, if we once again put our two solutions next to each other within the
   same example ContentView, then we can start to see that this time the two
   approaches do look quite different in terms of structure and clarity:
   
   struct ContentView: View {
       var body: some View {
           VStack {
               // View-based version:
               SplitView(leading: {
                   Text("Leading")
               }, trailing: {
                   Text("Trailing")
               })
   
               // Modifier-based version:
               Text("Leading").split(with: Text("Trailing"))
           }
       }
   }
   
   Looking at the view-based call site above, it’s very clear that our two texts
   are being wrapped within a container, and it’s also easy to tell which of
   those two texts will end up being the leading versus trailing view.
   
   That same thing can’t really be said for the modifier-based version this
   time, though, which really requires us to know that the view that we’re
   applying the modifier to will end up in the leading slot. Plus, we can’t
   really tell that those two texts will end up being wrapped in some kind of
   container at all. It looks more like we’re styling the leading label using
   the trailing label somehow, which really isn’t the case.
   
   While we could attempt to solve that clarity problem with more verbose API
   naming, the core issue would still remain — that the modifier-based version
   doesn’t properly show what the resulting view hierarchy will be in this case.
   So, in situations like the one above, when we’re wrapping multiple siblings
   within a parent container, opting for a view-based solution will often give
   us a much clearer end result.
   
   On the flip side, if all that we’re doing is applying a set of styles to a
   single view, then implementing that as either a “modifier-like” extension, or
   using a proper ViewModifier type, will most often be the way to go. And for
   everything in between — such as our earlier “featured label” example — it all
   really comes down to code style and personal preference as to which solution
   will be the best fit for each given project.
   
   Just look at how SwiftUI’s built-in API was designed — containers (such as
   HStack and VStack) are views, while styling APIs (such as padding and
   foregroundColor) are implemented as modifiers. So, if we follow that same
   approach as much as possible within our own projects, then we’ll likely end
   up with UI code that feels consistent and inline with SwiftUI itself.
   
   I hope that you found this article interesting and useful. Feel free to find
   me on Mastodon, or contact me via email, if you have any questions, comments,
   or feedback.
   
   Thanks for reading!

 * * Read more about swiftui
     
     
     AVOIDING SWIFTUI’S ANYVIEW
     
     Patterns, tips and techniques that can help us avoid using AnyView.
   
   * Another article about swiftui
     
     
     BUILDING AN ASYNCHRONOUS SWIFTUI BUTTON
   
   * Continue exploring swiftui
     
     
     RENDERING TEXTURED VIEWS WITH SWIFTUI
     
     Tiling, slicing and resizing background images.


 * OBSERVING THE CONTENT OFFSET OF A SWIFTUI SCROLLVIEW
   
    * swiftui
   
   Published on 30 Jan 2023
   Discover page available: SwiftUI
   
   When building various kinds of scrollable UIs, it’s very common to want to
   observe the current scroll position (or content offset, as UIScrollView calls
   it) in order to trigger layout changes, load additional data when needed, or
   to perform other kinds of actions depending on what content that the user is
   currently viewing.
   
   However, when it comes to SwiftUI’s ScrollView, there’s currently (at the
   time of writing) no built-in way to perform such scrolling observations.
   While embedding a ScrollViewReader within a scroll view does enable us to
   change the scroll position in code, it strangely (especially given its name)
   doesn’t let us read the current content offset in any way.
   
   One way to solve that problem would be to utilize the rich capabilities of
   UIKit’s UIScrollView, which — thanks to its delegate protocol and the
   scrollViewDidScroll method — provides an easy way to get notified whenever
   any kind of scrolling occurred. However, even though I’m normally a big fan
   of using UIViewRepresentable and the other SwiftUI/UIKit interoperability
   mechanisms, in this case, we’d have to write quite a bit of extra code to
   bridge the gap between the two frameworks.
   
   That’s mainly because — at least on iOS — we can only embed SwiftUI content
   within a UIHostingController, not within a self-managed UIView. So if we
   wanted to build a custom, observable version of ScrollView using
   UIScrollView, then we’d have to wrap that implementation in a view
   controller, and then manage the relationship between our UIHostingController
   and things like the keyboard, the scroll view’s content size, safe area
   insets, and so on. Not impossibly by any means, but still, a fair bit of
   additional work and complexity.
   
   So, let’s instead see if we can find a completely SwiftUI-native way to
   perform such content offset observations.
   
   
   RESOLVING FRAMES USING GEOMETRYREADER
   
   One thing that’s key to realize before we begin is that both UIScrollView and
   SwiftUI’s ScrollView perform their scrolling by offsetting a container that’s
   hosting our actual scrollable content. They then clip that container to their
   bounds to produce the illusion of the viewport moving. So if we can find a
   way to observe the frame of that container, then we’ll essentially have found
   a way to observe the scroll view’s content offset.
   
   That’s where our good old friend GeometryReader comes in (wouldn’t be a
   proper SwiftUI layout workaround without it, right?). While GeometryReader is
   mostly used to access the size of the view that it’s hosted in (or, more
   accurately, that view’s proposed size), it also has another neat trick up its
   sleeve — in that it can be asked to read the frame of the current view
   relative to a given coordinate system.
   
   To use that capability, let’s start by creating a PositionObservingView,
   which lets us bind a CGPoint value to the current position of that view
   relative to a CoordinateSpace that we’ll also pass in as an argument. Our new
   view will then embed a GeometryReader as a background (which will make that
   geometry reader take on the same size as the view itself) and will assign the
   resolved frame’s origin as our offset using a preference key — like this:
   
   struct PositionObservingView<Content: View>: View {
       var coordinateSpace: CoordinateSpace
   @Binding var position: CGPoint
       @ViewBuilder var content: () -> Content
   
       var body: some View {
           content()
               .background(GeometryReader { geometry in
                   Color.clear.preference(
       key: PreferenceKey.self,
       value: geometry.frame(in: coordinateSpace).origin
   )
               })
               .onPreferenceChange(PreferenceKey.self) { position in
                   self.position = position
               }
       }
   }
   
   To learn more about how the @ViewBuilder attribute can be used when building
   custom SwiftUI container views, check out this article.
   
   The reason we use SwiftUI’s preference system above is because our
   GeometryReader will be invoked as part of the view updating process, and
   we’re not allowed to directly mutate our view’s state during that process.
   So, by using a preference instead, we can deliver our CGPoint values to our
   view in an asynchronous fashion, which then lets us assign those values to
   our position binding.
   
   Now all that we need to do is to implement the PreferenceKey type that’s used
   above, and we’ll be good to go:
   
   private extension PositionObservingView {
       struct PreferenceKey: SwiftUI.PreferenceKey {
           static var defaultValue: CGPoint { .zero }
   
           static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
               // No-op
           }
       }
   }
   
   We don’t actually need to implement any kind of reduce algorithm above, since
   we’ll only have a single view delivering values using that preference key
   within any given hierarchy (since our implementation is entirely contained
   within our PositionObservingView).
   
   Alright, so now we have a view that’s capable of reading and observing its
   own position within a given coordinate system. Let’s now use that view to
   build a ScrollView wrapper that’ll let us accomplish our original goal — to
   be able to read the current content offset within such a scroll view.
   
   
   FROM POSITION TO CONTENT OFFSET
   
   Our new ScrollView wrapper will essentially have two responsibilities — one,
   it’ll need to convert the position of our inner PositionObservingView into
   the current scroll position (or content offset), and two, it’ll also need to
   define a CoordinateSpace that the inner view can use to resolve its position.
   Besides that, it’ll simply forward its configuration parameters to its
   underlying ScrollView, so that we can decide what axes we want each scroll
   view to operate on, and so that we can decide whether or not to display any
   scrolling indicators.
   
   The good news is that converting our inner view’s position into content
   offset is as easy as negating both the x and y components of those CGPoint
   values. That’s because, as discussed earlier, a scroll view’s content offset
   is essentially just the distance that the container has been moved relative
   to the scroll view’s bounds.
   
   So let’s go ahead and implement our custom scroll view, which we’ll name
   OffsetObservingScrollView (spelling out ContentOffset does feel a bit too
   verbose in this case):
   
   struct OffsetObservingScrollView<Content: View>: View {
       var axes: Axis.Set = [.vertical]
       var showsIndicators = true
       @Binding var offset: CGPoint
       @ViewBuilder var content: () -> Content
   
       // The name of our coordinate space doesn't have to be
       // stable between view updates (it just needs to be
       // consistent within this view), so we'll simply use a
       // plain UUID for it:
       private let coordinateSpaceName = UUID()
   
       var body: some View {
           ScrollView(axes, showsIndicators: showsIndicators) {
               PositionObservingView(
                   coordinateSpace: .named(coordinateSpaceName),
                   position: Binding(
                       get: { offset },
                       set: { newOffset in
                           offset = CGPoint(
       x: -newOffset.x,
       y: -newOffset.y
   )
                       }
                   ),
                   content: content
               )
           }
           .coordinateSpace(name: coordinateSpaceName)
       }
   }
   
   Note how we’re able to create a completely custom Binding for our inner
   view’s position parameter, by defining a getter and setter using closures.
   That’s a great option in situations like the one above, when we want to
   transform a value before assigning it to another Binding.
   
   That’s it! We now have a drop-in replacement for SwiftUI’s built-in
   ScrollView which enables us to observe the current content offset — which we
   can then bind to any state property that we’d like, for example in order to
   change the layout of a header view, to report analytics events to our server,
   or to perform any other kind of scroll position-based operation. You can find
   a complete example that uses the above OffsetObservingScrollView in order to
   implement a collapsable header view right here.
   
   I hope that you found this article useful. If you have any questions,
   comments, or feedback, then feel free to contact me on Mastodon, or send me
   an email.
   
   Thanks for reading!


 * * SWIFTUI
     
     Get the most out of Apple’s new UI framework.
   
   * Listen to a podcast episode about swiftui
     
     
     104: “THE MAGIC OF AUGMENTED REALITY” WITH SPECIAL GUEST ROXANA JULA
   
   * Listen to a podcast episode about swiftui
     
     
     118: “WHAT’S NEW IN SWIFTUI IN IOS 16?” WITH SPECIAL GUEST NATALIA
     PANFEROVA


 * PODCAST: “THE EVOLUTION OF SWIFT” WITH SPECIAL GUEST NICK LOCKWOOD
   
    * swift evolution
    * language features
   
   Published on 19 Dec 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   On this final episode of 2022, Nick Lockwood returns to the show to discuss
   the overall evolution of Swift and its ecosystem of tools and libraries. How
   has Swift changed since its original introduction in 2014, how does it
   compare to other modern programming languages, and how might the language
   continue to evolve in 2023 and beyond?
   
   
   SPONSORS
   
    * Bitrise: Rock-solid continuous integration for your Swift projects. Go to
      bitrise.io/swift to get started for free.
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
   
   
   LINKS
   
    * Nick on Mastodon
    * John on Mastodon
    * ShapeScript
    * Kotlin
    * Rust
    * NSProxy
    * Lisp
    * Macros in C and C++
    * Reflection in Swift
    * PHP
    * The Result type
    * Classes vs structs
    * Swift’s API design guidelines
    * Swift Concurrency
    * Swift Async Algorithms
    * The Future of Foundation
    * Swift Collections
    * Swift Evolution proposal for function back deployment
    * Building editable lists with SwiftUI
    * The Swift features that power SwiftUI’s API
    * Publish (static site generation in Swift)
    * swift-sh by Max Howell
    * Swift Evolution proposal for adding macros to the language
    * Accessing a property wrapper’s enclosing instance
    * Intro and outro music by Dariusz Dziuk

 * * Read more about Swift’s language features
     
     
     CALLING INSTANCE METHODS AS STATIC FUNCTIONS
   
   * Another article about Swift’s language features
     
     
     HOW SWIFT 5.3 ENHANCES SWIFTUI’S DSL
     
     Reduced verbosity, control flow improvements, and more.
   
   * Continue exploring Swift’s language features
     
     
     OPTIONALS
     
     From various ways of unwrapping and handling optional values, to how they
     can be extended with new APIs.


 * PODCAST: “SWIFT CONCURRENCY IN PRACTICE” WITH SPECIAL GUEST BEN SCHEIRMAN
   
    * concurrency
   
   Published on 18 Nov 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Ben Scheirman returns to the show to discuss how Swift’s built-in concurrency
   features, such as async/await and tasks, can be used in practice when
   building apps for Apple’s platforms.
   
   
   SPONSORS
   
    * Essential Developer: Join the iOS Architect Crash Course to accelerate
      your journey towards becoming a senior developer. It’s 100% free and held
      entirely online.
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
   
   
   LINKS
   
    * Ben on Twitter
    * John on Twitter
    * NSScreencast
    * Combine Swift
    * The Nike SNKRS app
    * Discover concurrency
    * Episode with Doug Gregor about Swift concurrency
    * The delegate pattern
    * PromiseKit
    * RxSwift
    * Discover Combine
    * Implementing debouncing using Combine
    * Grand Central Dispatch (GCD)
    * Async sequences and streams
    * Retrofitting existing APIs with async/await support
    * Async properties
    * The Just publisher
    * The MainActor attribute
    * Point-Free’s Combine schedulers
    * Previous episode with Ben about UICollectionView
    * Connecting and merging Combine publishers
    * Tonal Therapy
    * Intro and outro music by Dariusz Dziuk


 * * CONCURRENCY
     
     Explore Swift’s built-in concurrency system.
   
   * Read more about concurrency
     
     
     CREATING COMBINE-COMPATIBLE VERSIONS OF ASYNC/AWAIT-BASED APIS
   
   * Another article about concurrency
     
     
     AUTOMATICALLY RETRYING AN ASYNCHRONOUS SWIFT TASK


 * COMBINING OPAQUE RETURN TYPES WITH PRIMARY ASSOCIATED TYPES
   
    * language features
    * protocols
   
   Published on 12 Nov 2022
   Basics article available: Protocols
   
   Ever since Swift was first introduced, it’s been very common to need to use
   type erasure when working with generic protocols — ones that either reference
   Self within their requirements, or make use of associated types.
   
   For example, in earlier versions of Swift, when using Apple’s Combine
   framework for reactive programming, every time we wanted to return a
   Publisher from a function or computed property, we had to first type-erase it
   by wrapping it within an AnyPublisher — like this:
   
   struct UserLoader {
       var urlSession = URLSession.shared
       var decoder = JSONDecoder()
   
       func loadUser(withID id: User.ID) -> AnyPublisher<User, Error> {
           urlSession
               .dataTaskPublisher(for: urlForLoadingUser(withID: id))
               .map(\.data)
               .decode(type: User.self, decoder: decoder)
               .eraseToAnyPublisher()
       }
   
       private func urlForLoadingUser(withID id: User.ID) -> URL {
           ...
       }
   }
   
   The reason type erasure had to be used in situations like that is because
   simply declaring that our method returns something that conforms to the
   Publisher protocol wouldn’t give the compiler any information as to what kind
   of output or errors that the publisher emits.
   
   Of course, an alternative to type erasure would be to declare the actual,
   concrete type that the above method returns. But when using frameworks that
   rely heavily on generics (such as Combine and SwiftUI), we very often end up
   with really complex nested types that would be very cumbersome to declare
   manually.
   
   This is a problem that was partially addressed in Swift 5.1, which introduced
   the some keyword and the concept of opaque return types, which are very often
   used when building views using SwiftUI — as they let us leverage the compiler
   to infer what concrete View-conforming type that’s returned from a given
   view’s body:
   
   struct ArticleView: View {
       var article: Article
   
       var body: some View {
           ScrollView {
               VStack(alignment: .leading) {
                   Text(article.title).font(.title)
                   Text(article.text)
               }
               .padding()
           }
       }
   }
   
   While the above way of using the some keyword works great in the context of
   SwiftUI, when we’re essentially just passing a given value into the framework
   itself (after all, we’re never expected to access the body property
   ourselves), it wouldn’t work that well when defining APIs for our own use.
   
   For example, replacing the AnyPublisher return type with some Publisher (and
   removing the call to eraseToAnyPublisher) within our UserLoader from before
   would technically work in isolation, but would also make each call site
   unaware of what type of output that our publisher produces — as we’d be
   dealing with a completely opaque Publisher type that can’t access any of the
   protocol’s associated types:
   
   struct UserLoader {
       ...
   
       func loadUser(withID id: User.ID) -> some Publisher {
           urlSession
               .dataTaskPublisher(for: urlForLoadingUser(withID: id))
               .map(\.data)
               .decode(type: User.self, decoder: decoder)
       }
   
       ...
   }
   
   UserLoader()
       .loadUser(withID: userID)
       .sink(receiveCompletion: { completion in
           ...
       }, receiveValue: { output in
           // We have no way of getting a compile-time guarantee
           // that the output argument here is in fact a User
           // value, so we'd have to use force-casting to turn
           // that argument into the right type:
           let user = output as! User
           ...
       })
       .store(in: &cancellables)
   
   This is where Swift 5.7’s introduction of primary associated types comes in.
   If we take a look at the declaration of Combine’s Publisher protocol, we can
   see that it’s been updated to take advantage of this feature by declaring
   that its associated Output and Failure types are primary (by putting them in
   angle brackets right after the protocol’s name):
   
   protocol Publisher<Output, Failure> {
       associatedtype Output
       associatedtype Failure: Error
       ...
   }
   
   That in turn enables us to use the some keyword in a brand new way — by
   declaring what exact types that our return value will use for each of the
   protocol’s primary associated types. So if we first update our UserLoader to
   use that new feature:
   
   struct UserLoader {
       ...
   
       func loadUser(withID id: User.ID) -> some Publisher<User, Error> {
           urlSession
               .dataTaskPublisher(for: urlForLoadingUser(withID: id))
               .map(\.data)
               .decode(type: User.self, decoder: decoder)
       }
   
       ...
   }
   
   Then we’ll no longer be required to use force-casting at each call site — all
   while also avoiding any kind of manual type erasure, as the compiler will now
   retain full type safety all the way from our loadUser method to each of its
   call sites:
   
   UserLoader()
       .loadUser(withID: userID)
       .sink(receiveCompletion: { completion in
           ...
       }, receiveValue: { user in
           // We're now getting a properly typed User
           // value passed into this closure.
           ...
       })
       .store(in: &cancellables)
   
   Of course, since primary associated types isn’t just a Combine-specific
   thing, but rather a proper Swift feature, we can also use the above pattern
   when working with our own generic protocols as well.
   
   For example, let’s say that we’ve defined a Loadable protocol that lets us
   abstract different ways of loading a given value behind a single, unified
   interface (this time using Swift concurrency):
   
   protocol Loadable<Value> {
       associatedtype Value
   
       func load() async throws -> Value
   }
   
   struct NetworkLoadable<Value: Decodable>: Loadable {
       var url: URL
   
       func load() async throws -> Value {
           // Load the value over the network
           ...
       }
   }
   
   struct DatabaseLoadable<Value: Identifiable>: Loadable {
       var id: Value.ID
   
       func load() async throws -> Value {
           // Load the value from the app's local database
           ...
       }
   }
   
   A big benefit of using a pattern like that is that it enables us to very
   neatly separate concerns, as each call site doesn’t have to be aware of
   exactly how a given value is loaded — we can simply return some Loadable from
   a given function, and thanks to our primary associated type, we get full type
   safety without having to reveal what underlying type that’s used to perform
   the actual loading:
   
   func loadableForArticle(withID id: Article.ID) -> some Loadable<Article> {
       let url = urlForLoadingArticle(withID: id)
       return NetworkLoadable(url: url)
   }
   
   However, one important limitation of opaque return types is that the compiler
   requires all code paths within a scope that returns an opaque type to always
   return the exact same type. So, if we wanted to dynamically switch between
   two different Loadable implementations, then we’d get a compiler error if we
   tried to keep using the some keyword like we did above:
   
   // Error: Function declares an opaque return type 'some Loadable<Article>',
   // but the return statements in its body do not have matching underlying types.
   func loadableForArticle(withID id: Article.ID) -> some Loadable<Article> {
       if useLocalData {
       return DatabaseLoadable(id: id)
   }
   
       let url = urlForLoadingArticle(withID: id)
       return NetworkLoadable(url: url)
   }
   
   One way to solve the above problem would be to use the good old fashioned
   approach of introducing a type-erasing AnyLoadable type, which we could use
   to wrap both of our underlying Loadable instances — but at this point, that
   does arguably feel like a step backwards, since we’d have to write that
   type-erased wrapper manually. Or do we?
   
   It turns out that we can, in fact, keep leveraging the compiler even in these
   kinds of more dynamic situations — all that we have to do is replace the some
   keyword with Swift’s new any keyword, and the compiler will actually perform
   all of the required type erasure on our behalf:
   
   func loadableForArticle(withID id: Article.ID) -> any Loadable<Article> {
       if useLocalData {
           return DatabaseLoadable(id: id)
       }
   
       let url = urlForLoadingArticle(withID: id)
       return NetworkLoadable(url: url)
   }
   
   Just like when using some in combination with primary associated types, using
   any retains full type-safety, and still enables us to use all available
   Loadable APIs, and maintain complete awareness that the returned instance
   loads Article values. Neat!
   
   It’s important to point out, though, that using the any keyword in the above
   kind of way turns our method’s return value into a so-called existential,
   which does come with a certain performance overhead, and might also prevent
   us from using certain generic APIs. For example, if we were to use the any
   keyword within the earlier Combine-based example, then we’d be locked out of
   applying any kind of operators (like map or flatMap) on the returned
   publisher. So, when possible, it’s definitely preferable to use the some
   keyword instead.
   
   I hope that you found this article useful. If you want to learn more about
   some and any, then check out my earlier article about those keywords, which
   focuses on how they can be used when declaring properties and parameter
   types. And if you have any questions, comments, or feedback, then feel free
   to reach out.
   
   Thanks for reading!

 * * Read more about Swift’s language features
     
     
     5 SMALL BUT SIGNIFICANT IMPROVEMENTS IN SWIFT 5.1
   
   * Another article about Swift’s language features
     
     
     ORGANIZING DEFAULT ARGUMENT VALUES
   
   * Continue exploring Swift’s language features
     
     
     USING KEY PATHS TO CREATE CONVENIENCE APIS


 * PODCAST: “RESPONSIVE AND SMOOTH UIS” WITH SPECIAL GUEST ADAM BELL
   
    * ui development
    * performance
   
   Published on 31 Oct 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Adam Bell returns to the podcast to discuss different techniques and
   approaches for optimizing UI code, and how to utilize tools like animations
   in order to build iOS apps that feel fast and responsive.
   
   
   SPONSORS
   
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
    * Bitrise: Rock-solid continuous integration for your Swift projects. Go to
      bitrise.io/swift to get started for free.
   
   
   LINKS
   
    * Adam on Twitter
    * John on Twitter
    * Motion
    * CloudKit
    * Debouncing
    * CATransaction
    * Grand Central Dispatch
    * UITraitCollection
    * SIMD
    * CAAnimation
    * Modifying a view’s transform
    * Snapshotting a UIView
    * CALayer
    * View controller transitions
    * Extracting the animation curve used for keyboard presentation
    * Adding spring parameters to a UIView animation
    * beginFromCurrentState animation option
    * Intro and outro music by Dariusz Dziuk

 * * Read more about ui development
     
     
     IMPORTING INTERACTIVE UIKIT VIEWS INTO SWIFTUI
     
     Why rewrite views when we can reuse them?
   
   * Another article about performance
     
     
     PICKING THE RIGHT DATA STRUCTURE IN SWIFT
     
     How different data structures can have a big impact on performance.
   
   * Continue exploring ui development
     
     
     RENDERING TEXTURED VIEWS WITH SWIFTUI
     
     Tiling, slicing and resizing background images.


 * PODCAST: “FREELANCING AND WWDC22 HIGHLIGHTS” WITH SPECIAL GUEST DONNY WALS
   
    * wwdc22
    * language features
    * project management
   
   Published on 17 Sep 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Donny Wals returns to the show to talk about being an iOS developer
   freelancer, and to discuss some of the key new APIs, Swift language features,
   and frameworks that were introduced at WWDC22.
   
   
   SPONSORS
   
    * Essential Developer: Join the iOS Architect Crash Course to accelerate
      your journey towards becoming a senior developer. It’s 100% free and held
      entirely online.
    * Bitrise: Rock-solid continuous integration for your Swift projects. Go to
      bitrise.io/swift to get started for free.
   
   
   LINKS
   
    * Donny on Twitter
    * John on Twitter
    * “What’s new in SwiftUI in iOS 16?”, with Natalia Panferova
    * SwiftUI’s new NavigationStack API
    * Building “desktop-class” iPad apps
    * Swift Charts
    * The SwiftUI Layout protocol
    * UIHostingConfiguration
    * NSUserActivity
    * WidgetKit
    * Live Activities
    * AsyncCompatibilityKit
    * Swift 5.7’s new optional unwrapping syntax
    * Intro and outro music by Dariusz Dziuk

 * * Another episode about Swift’s language features
     
     
     103: “WHAT’S NEW IN SWIFT 5.5” WITH SPECIAL GUEST ANTOINE VAN DER LEE
   
   * Read more about Swift’s language features
     
     
     CONDITIONAL COMPILATION WITHIN SWIFT EXPRESSIONS
   
   * Another article about wwdc22
     
     
     SWITCHING BETWEEN SWIFTUI’S HSTACK AND VSTACK


 * PODCAST: “THE ROLE OF SYSTEM DESIGN” WITH SPECIAL GUEST GUI RAMBO
   
    * architecture
    * project management
   
   Published on 31 Aug 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Gui Rambo returns to the show to talk about the role and importance of system
   design when building apps and open source tools, and how common app
   architectures and design patterns can be augmented with custom systems.
   
   
   SPONSORS
   
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
    * Bitrise: Rock-solid continuous integration for your Swift projects. Go to
      bitrise.io/swift to get started for free.
   
   
   LINKS
   
    * Rambo on Twitter
    * John on Twitter
    * Stacktrace
    * AirBuddy
    * ChibiStudio
    * MVVM
    * MVC
    * The factory pattern
    * The observer pattern
    * Combine
    * Swift Concurrency
    * Async streams
    * Diagrams
    * MindNode
    * VirtualBuddy
    * DocC
    * Sparkle
    * Intro and outro music by Dariusz Dziuk

 * * Read more about architecture
     
     
     ALTERNATIVES TO PROTOCOLS IN SWIFT
     
     Four different ways of defining abstractions in Swift.
   
   * Another article about architecture
     
     
     SPLITTING UP SWIFT TYPES
     
     Enabling composition by first decomposing larger types into smaller
     building blocks.
   
   * Watch a video about architecture
     
     
     THE DEVELOPER JOURNEY FROM PRAGMA CONFERENCE
     
     Preparing ourselves, and our code, for future changes.


 * ESSENTIAL DEVELOPER
   
    * Sponsored
   
   Published on 13 Jul 2022
   
   Thanks a lot to Caio and Mike, the two developers behind Essential Developer,
   for sponsoring Swift by Sundell. Essential Developer was founded to help iOS
   developers accelerate their journeys towards becoming complete senior
   developers, and on July 18th, Caio and Mike will kick off the next edition of
   their iOS Architect Crash Course, which you can sign up for completely for
   free by going to essentialdeveloper.com/sundell.
   
   During that course, which consists of three online lectures, you’ll get to
   explore concepts like app architecture, maintaining and refactoring legacy
   code, and how to effectively utilize techniques like composition within iOS
   code bases. Those are all concepts that most senior developers are expected
   to be very familiar with, but can also be hard to explore and practice on
   your own. That’s why so many developers have found this course to be so
   incredibly valuable.
   
   You’ll also get to ask your questions during the lectures as well, and
   there’s even bonus mentorship sessions available. All of this for the
   fantastic price of… free!
   
   If this sounds interesting to you, then head over to the Essential Developer
   website to sign up for the iOS Architect Crash Course today. It’s held
   completely online, so you can attend from anywhere in the world. But don’t
   wait too long to sign up because the next edition (at the time of writing)
   already starts on July 18th.
   
   Hope you’ll enjoy the course, and thanks a lot to Caio and Mike for
   sponsoring Swift by Sundell, which helps me keep the website and the podcast
   free and accessible to everyone.


 * PODCAST: “WHAT’S NEW IN SWIFTUI IN IOS 16?” WITH SPECIAL GUEST NATALIA
   PANFEROVA
   
    * swiftui
    * uikit
   
   Published on 11 Jul 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Natalia Panferova joins John to discuss some of the key new features that are
   coming to SwiftUI and UIKit in iOS 16, and to talk about her experience
   working on SwiftUI at Apple.
   
   
   SPONSORS
   
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
    * Essential Developer: Join the iOS Architect Crash Course to accelerate
      your journey towards becoming a senior developer. The next edition starts
      on July 18th, and it’s 100% free and held entirely online.
   
   
   LINKS
   
    * Natalia on Twitter
    * John on Twitter
    * Natalia’s website: nilcoalescing.com
    * The Layout protocol
    * GeometryReader
    * AttributedString
    * Natalia’s article about the new SwiftUI navigation APIs
    * NavigationStack
    * NavigationSplitView
    * NavigationViewStyle
    * Programmatic navigation in SwiftUI (before iOS 16)
    * How to sync the width or height of two SwiftUI views?
    * AnyLayout
    * ViewThatFits
    * Natalia’s article about the new SwiftUI sheet APIs
    * Swift Charts
    * Rendering SwiftUI views within UITableView or UICollectionView cells on
      iOS 16
    * Building modern collection views
    * SwiftUI/UIKit interoperability
    * Intro and outro music by Dariusz Dziuk

 * * Read more about swiftui
     
     
     BUILDING AN ASYNCHRONOUS SWIFTUI BUTTON
   
   * Another article about swiftui
     
     
     DEFINING DYNAMIC COLORS IN SWIFT
     
     Using either SwiftUI or UIKit.
   
   * Continue exploring swiftui
     
     
     OBSERVING COMBINE PUBLISHERS IN SWIFTUI VIEWS
     
     Lightweight state observations.


 * SWITCHING BETWEEN SWIFTUI’S HSTACK AND VSTACK
   
    * swiftui
    * layout
    * wwdc22
   
   Published on 08 Jul 2022
   Discover page available: SwiftUI
   
   SwiftUI’s various stacks are some of the framework’s most fundamental layout
   tools, and enable us to define groups of views that are aligned either
   horizontally, vertically, or stacked in terms of depth.
   
   When it comes to the horizontal and vertical variants (HStack and VStack), we
   might sometimes end up in a situation where we want to dynamically switch
   between the two. For example, let’s say that we’re building an app that
   contains the following LoginActionsView, which lets the user pick from a list
   of actions when logging in:
   
   Preview
   
   struct LoginActionsView: View {
       ...
   
       var body: some View {
           VStack {
               Button("Login") { ... }
               Button("Reset password") { ... }
               Button("Create account") { ... }
           }
           .buttonStyle(ActionButtonStyle())
       }
   }
   
   struct ActionButtonStyle: ButtonStyle {
       func makeBody(configuration: Configuration) -> some View {
           configuration.label
               .fixedSize()
               .frame(maxWidth: .infinity)
               .padding()
               .foregroundColor(.white)
               .background(Color.blue)
               .cornerRadius(10)
       }
   }
   
   Above, we’re using the fixedSize modifier to prevent our button labels from
   getting truncated, which is something that we should only do if we’re sure
   that a given view’s content won’t ever be larger than the view itself. To
   learn more, check out part three of my guide to SwiftUI’s layout system.
   
   Currently, our buttons are stacked vertically, and fill all of the available
   space on the horizontal axis (you can use the above code sample’s PREVIEW
   button to see what that looks like). While that looks great on iPhones that
   are in portrait orientation, let’s say that we instead wanted to use a
   horizontal stack when our UI is rendered in landscape mode.
   
   
   GEOMETRYREADER TO THE RESCUE?
   
   One way to do that would be to use a GeometryReader to measure the currently
   available space, and based on whether the width of that space is larger than
   its height, we render our content using either an HStack or a VStack.
   
   While we could definitely place that logic right within our LoginActionsView
   itself, chances are quite high that we’ll want to reuse that code at some
   point in the future, so let’s instead create a dedicated view that’ll perform
   our dynamic stack-switching logic as a stand-alone component.
   
   To make our code even more future-proof, we won’t hard-code what alignment or
   spacing that our two stack variants will use. Instead, let’s do what SwiftUI
   itself does, and parametrize those attributes while also assigning the same
   default values that the framework uses — like this:
   
   struct DynamicStack<Content: View>: View {
       var horizontalAlignment = HorizontalAlignment.center
   var verticalAlignment = VerticalAlignment.center
   var spacing: CGFloat?
       @ViewBuilder var content: () -> Content
   
       var body: some View {
           GeometryReader { proxy in
               Group {
                   if proxy.size.width > proxy.size.height {
                       HStack(
                           alignment: verticalAlignment,
                           spacing: spacing,
                           content: content
                       )
                   } else {
                       VStack(
                           alignment: horizontalAlignment,
                           spacing: spacing,
                           content: content
                       )
                   }
               }
           }
       }
   }
   
   Since we made our new DynamicStack use the same kind of API that HStack and
   VStack use, we can now simply swap out our previous VStack for an instance of
   our new, custom stack within our LoginActionsView:
   
   Preview
   
   struct LoginActionsView: View {
       ...
   
       var body: some View {
           DynamicStack {
               Button("Login") { ... }
               Button("Reset password") { ... }
               Button("Create account") { ... }
           }
           .buttonStyle(ActionButtonStyle())
       }
   }
   
   Neat! However, like the above code sample’s PREVIEW shows, using a
   GeometeryReader to perform our dynamic stack switching does come with a quite
   significant downside, in that geometry readers always fill all of the
   available space on both the horizontal and vertical axis (in order to
   actually be able to measure that space). In our case, that means that our
   LoginActionsView will no longer just stretch out horizontally, but it’ll now
   also move to the top of the screen.
   
   While there are various ways that we could address those problems (for
   example by using a technique similar to the one we used to make multiple
   views have the same width or height in this Q&A article), the question is
   really whether measuring the available space is really a good approach when
   it comes to determining the orientation of our dynamic stacks.
   
   
   A CASE FOR SIZE CLASSES
   
   Instead, let’s use Apple’s size class system to decide whether our
   DynamicStack should use an HStack or a VStack under the hood. The benefit of
   doing that is not just that we’ll be able to retain the same compact layout
   that we had before introducing a GeometryReader into the mix, but also that
   our DynamicStack will start behaving in a way that’s very similar to how
   built-in system components behave across all devices and orientations.
   
   To start observing the current horizontal size class, all we have to do is to
   use SwiftUI’s environment system — by declaring an @Environment-marked
   property (with the horizontalSizeClass key path) within our DynamicStack,
   which will then let us switch on the current sizeClass value within our
   view’s body:
   
   Preview
   
   struct DynamicStack<Content: View>: View {
       ...
       @Environment(\.horizontalSizeClass) private var sizeClass
   
       var body: some View {
           switch sizeClass {
           case .regular:
               hStack
           case .compact, .none:
               vStack
           @unknown default:
               vStack
           }
       }
   }
   
   private extension DynamicStack {
       var hStack: some View {
           HStack(
               alignment: verticalAlignment,
               spacing: spacing,
               content: content
           )
       }
   
       var vStack: some View {
           VStack(
               alignment: horizontalAlignment,
               spacing: spacing,
               content: content
           )
       }
   }
   
   With the above in place, our LoginActionsView will now dynamically switch
   between having a horizontal layout when rendered using the regular size class
   (for example in landscape on larger iPhones, or in either orientation when
   running full-screen on iPad), and a vertical layout when any other size class
   configuration is used. All while still using a compact vertical layout that
   doesn’t use any more space than what’s needed to render its content.
   
   
   USING THE LAYOUT PROTOCOL
   
   Although we’ve already ended up with a neat solution that works across all
   iOS versions that support SwiftUI, let’s also explore a few new layout tools
   that are being introduced in iOS 16 (which at the time of writing is still in
   beta as part of Xcode 14).
   
   One such tool is the new Layout protocol, which both enables us to build
   completely custom layouts that can be integrated directly into SwiftUI’s own
   layout system (more on that in a future article), while also providing us
   with a new way to dynamically switch between various layouts in a very
   smooth, full animatable way.
   
   That’s because it turns out that Layout is not just an API for us third-party
   developers, but Apple have also made SwiftUI’s own layout containers use that
   new protocol as well. So, rather than using HStack and VStack directly as
   container views, we can instead use them as Layout-conforming instances that
   are wrapped using the AnyLayout type — like this:
   
   private extension DynamicStack {
       var currentLayout: AnyLayout {
           switch sizeClass {
           case .regular, .none:
               return horizontalLayout
           case .compact:
               return verticalLayout
           @unknown default:
               return verticalLayout
           }
       }
   
       var horizontalLayout: AnyLayout {
           AnyLayout(HStack(
               alignment: verticalAlignment,
               spacing: spacing
           ))
       }
   
       var verticalLayout: AnyLayout {
           AnyLayout(VStack(
               alignment: horizontalAlignment,
               spacing: spacing
           ))
       }
   }
   
   The above works since both HStack and VStack directly conform to the new
   Layout protocol when their Content type is EmptyView (which is the case when
   we don’t pass any content closure to such a stack), as we can see if we take
   a peak at SwiftUI’s public interface:
   
   extension VStack: Layout where Content == EmptyView {
       ...
   }
   
   Note that, due to a regression, the above conditional conformance was omitted
   from Xcode 14 beta 3. According to Matt Ricketson from the SwiftUI team, a
   temporary workaround would be to instead use the underlying _HStackLayout and
   _VStackLayout types directly. Hopefully that regression will be fixed in
   future betas.
   
   Now that we’re able to resolve what layout to use through our new
   currentLayout property, we can now update our body implementation to simply
   call the AnyLayout that’s returned from that property as if it was a function
   — like this:
   
   struct DynamicStack<Content: View>: View {
       ...
   
       var body: some View {
           currentLayout(content)
       }
   }
   
   The reason that we can apply our layout by calling it as a function (even
   though it’s actually a struct) is because the Layout protocol uses Swift’s
   “call as function” feature.
   
   So what’s the difference between our previous solution and the above,
   Layout-based one? The key difference (besides the fact that the latter
   requires iOS 16) is that switching layouts preserves the identity of the
   underlying views that are being rendered, which isn’t the case when swapping
   between an HStack and a VStack. The result of that is that animations will be
   much smoother, for example when switching device orientations, and we’re also
   likely to get a small performance boost when performing such changes as well
   (since SwiftUI always performs best when its view hierarchies are as static
   as possible).
   
   
   PICKING THE VIEW THAT FITS
   
   But we’re not quite done yet, because iOS 16 also gives us another
   interesting new layout tool that could potentially be used to implement our
   DynamicStack — which is a new view type called ViewThatFits. Like its name
   implies, that new container will pick the view that best fits within the
   current context, based on a list of candidates that we pass when initializing
   it.
   
   In our case, that means that we could pass it both an HStack and a VStack,
   and it’ll automatically switch between them on our behalf:
   
   struct DynamicStack<Content: View>: View {
       ...
   
       var body: some View {
           ViewThatFits {
               HStack(
                   alignment: verticalAlignment,
                   spacing: spacing,
                   content: content
               )
   
               VStack(
                   alignment: horizontalAlignment,
                   spacing: spacing,
                   content: content
               )
           }
       }
   }
   
   Note that it’s important that we place the HStack first in this case, since
   the VStack will likely always fit, even within contexts where we want our
   layout to be horizontal (such as in full-screen mode on iPad). It’s also
   important to point out that the above ViewThatFits-based technique will
   always attempt to use our HStack, even when rendered with the compact size
   class, and will only pick our VStack-based layout when the HStack doesn’t
   fit.
   
   
   CONCLUSION
   
   So that’s four different ways to implement a dedicated DynamicStack view that
   dynamically switches between an HStack and a VStack depending on the current
   context. I hope you enjoyed this article, and if you have any questions,
   comments, or feedback, then feel free to reach out via either Twitter or
   email.
   
   Thanks for reading!


 * * SWIFTUI
     
     Get the most out of Apple’s new UI framework.
   
   * Listen to a podcast episode about swiftui
     
     
     60: “DEPLOYING SWIFTUI IN PRODUCTION” WITH SPECIAL GUEST DAVID SMITH
   
   * Listen to a podcast episode about swiftui
     
     
     87: “THE SWIFTUI LAYOUT SYSTEM” WITH SPECIAL GUEST CHRIS EIDHOF
     
     How the layout system works.


 * PODCAST: “SWIFT 5.7, GENERICS, AND THE ROAD TO SWIFT 6” WITH SPECIAL GUEST
   BEN COHEN
   
    * wwdc22
    * apple interview
    * generics
   
   Published on 10 Jun 2022
   Listen using:  Apple PodcastsOvercastCastroPocket CastsRSS
   
   Ben Cohen, manager of the Swift team at Apple, joins John on this WWDC22
   special to discuss Swift 5.7, how generics have been made more powerful and
   easy to use, and how the language is expected to evolve towards Swift 6.
   
   
   SPONSORS
   
    * Bitrise: Rock-solid continuous integration for your Swift projects. Go to
      bitrise.io/swift to get started for free.
    * NordVPN: Get an exclusive discount on NordVPN’s excellent VPN service, by
      going to nordvpn.com/sundell. They even have a 30-day money-back
      guarantee.
   
   
   LINKS
   
    * Ben on Twitter
    * John on Twitter
    * Swift Async Algorithms
    * Swift Collections
    * Using the new ‘some’ and ‘any’ keywords
    * Type erasure
    * “What’s New in Swift”, from WWDC22
    * “Embracing Swift Generics”, from WWDC22
    * WeatherKit
    * Regex Literals
    * RegexBuilder
    * Result builders
    * App Intents
    * Sourcery
    * Doug Gregor’s “Eliminate data races using Swift Concurrency” talk
    * Ben’s Swift concurrency talk from WWDC21
    * Grand Central Dispatch
    * Swift Distributed Actors
    * Connecting async/await to other Swift code
    * The Swift Mentorship Program
    * Intro and outro music by Dariusz Dziuk

 * Article
   
   
   USING THE ‘SOME’ AND ‘ANY’ KEYWORDS TO REFERENCE GENERIC PROTOCOLS IN SWIFT
   5.7
   
    * wwdc22
    * generics
    * protocols
   
   Published on 09 Jun 2022
   
   How Swift 5.7 makes generic protocols more powerful and easier to work with,
   thanks to the ‘some’ and ‘any’ keywords.

 * Article
   
   
   SWIFT 5.7’S NEW OPTIONAL UNWRAPPING SYNTAX
   
    * wwdc22
    * language features
    * optionals
   
   Published on 07 Jun 2022
   
   A quick look at a new, more concise way to unwrap optional values that’s
   being introduced in Swift 5.7.

 * Article
   
   
   RENDERING SWIFTUI VIEWS WITHIN UITABLEVIEW OR UICOLLECTIONVIEW CELLS ON IOS
   16
   
    * wwdc22
    * uikit
    * swiftui
   
   Published on 07 Jun 2022
   
   Exploring how iOS 16’s new UIHostingConfiguration API enables us to inline
   SwiftUI views within our UITableView or UICollectionView cells.

 * Podcast episode
   
   
   116: “THE EVOLUTION OF SWIFTUI” WITH SPECIAL GUEST CHRIS EIDHOF
   
    * swiftui
    * architecture
   
   Published on 18 May 2022
   
   Chris Eidhof returns to the podcast to talk about how SwiftUI has evolved
   since its initial release, to share several key learnings from using it over
   the past few years, and to discuss concepts like app architecture and state
   management.

 * Special
   
   
   SWIFT BY SUNDELL TURNS FIVE YEARS OLD TODAY! HERE’S WHAT’S NEXT FOR THE
   WEBSITE AND THE PODCAST
   
   Published on 05 May 2022
   
   Celebrating the fifth birthday of this website, while also sharing some
   important announcements about its future.

 * Podcast episode
   
   
   115: “A FRAMEWORK AND AN APP” WITH SPECIAL GUEST SIMON STØVRING
   
    * developer tools
    * performance
    * maintenance
   
   Published on 30 Apr 2022
   
   Simon Støvring returns to the show to talk about how he built his new text
   editor Runestone, how to effectively manage an app’s settings, performance
   tuning, and implementing an app’s core logic as a stand-alone framework.

 * Article
   
   
   TYPE PLACEHOLDERS IN SWIFT
   
    * language features
    * generics
   
   Published on 14 Apr 2022
   
   New in Swift 5.6: We can now use type placeholders to select what generic
   types that we want the compiler to infer. Let’s take a look at how those
   placeholders work, and what kinds of situations that they could be really
   useful in.

 * Podcast episode
   
   
   114: “ACCESSIBILITY ON APPLE’S PLATFORMS” WITH SPECIAL GUEST SOMMER PANAGE
   
    * accessibility
    * ui development
   
   Published on 21 Mar 2022
   
   Sommer Panage returns to the show to discuss Apple’s various accessibility
   APIs and tools, how to incorporate accessibility support into a team’s
   overall development workflow, and what it was like being an engineering
   manager at Apple.

 * More to read
   
   
   BROWSE ALL ARTICLES

 * More to listen to
   
   
   BROWSE ALL PODCAST EPISODES

 * More to watch
   
   
   BROWSE ALL VIDEOS

Copyright © Sundell sp. z o.o. 2023.

Built in Swift using Publish.

Twitter | RSS | Contact