Swift 5.3: What's New?

Hi Habr! The Swift programming language is very popular due to its use in writing applications for iOS, so its development is of interest to everyone involved in this area.

Let's see what's new for Swift version 5.3 developers.

Multiple trailing closures


The new version ( SE-0279 ) offers a new syntax for finite closures that allows you to call multiple closures as function parameters in a more readable way. This minimizes the use of too many parentheses in the function signature.

import Foundation

func load(url: String, success: (Data) -> Void, failure: (Error) -> Void) {
    
}

// old  version

load(url: "someURL", success: { data in }, failure: { error in })

// new multiple trailing closures

load(url: "someURL") { (data) in
    // do smth
} failure: { (error) in
    // do smth
}

On the example of 2 call options, it can be seen that visually the second one looks a little nicer.

Multi-Pattern Catch Clauses


Currently, each catch clause in a do-catch statement can contain only one pattern. To work around this problem, developers will use the capabilities of switch options to include pattern matching in the body of catch statements, thereby increasing nested and duplicated code ( SE-0276 ).

Catch items now allow the user to specify a comma-separated list of templates with the ability to bind variables to the catch body, as in a switch.

enum NetworkError: Error {
    case failure, timeout
}

// old  version
func networkCall(){
  do{
    try someNetworkCall()
  } catch NetworkError.timeout{
    print("timeout")
  } catch NetworkError.failure{
    print("failure")
  }
}

// new multi-Pattern catch clauses
func networkCall(){
  do{
    try someNetworkCall()
  } catch NetworkError.failure, NetworkError.timeout {
    print("handle for both")
  }
}

Synthesized Comparable Conformance for Enums


Until now, comparing 2 elements of an enumeration was not a “pleasant” thing. It was necessary to conform Comparable and write a static function <to determine whether the original value is less than another.

Now Swift ( SE-0266 ) allows you not to “sweat” over the implementation of all these things, and you do not need to explicitly implement the protocol as long as your enumeration has the same types. If the corresponding values ​​are not specified, the listings will be compared in the semantic order of the declaration.

enum Brightness: Comparable {
    case low(Int)
    case medium
    case high
}

([.high, .low(1), .medium, .low(0)] as [Brightness]).sorted()
// [Brightness.low(0), Brightness.low(1), Brightness.medium, Brightness.high]

the number of selfs can be reduced


From now on, self can be omitted in those places where it is no longer needed ( SE-0269 ). Previously, using self in closures was necessary when we captured values ​​from the outer scope.

struct OldView: View {

    var body: some View {
        Button(action: {
            self.sayHello()
        }) {
            Text("Press")
        }
    }
    
    func sayHello() {}
}

struct NewView: View {

    var body: some View {
        Button {
            sayHello()
        } label: {
            Text("Press")
        }
    }
    
    func sayHello(){}
}

Where in generic


A new version of the language ( SE-0267 ) introduced the ability to attach where to functions within generic types and extensions.

struct Stack<Element> {
    private var array = [Element]()

    mutating func push(_ obj: Element) {
        array.append(obj)
    }

    mutating func pop(_ obj: Element) -> Element? {
        array.popLast()
    }
}

extension Stack {
    func sorted() -> [Element] where Element: Comparable {
        array.sorted()
    }
}

A new sorted () method can be added to the stack, but only for those cases when the elements inside the stack conform Comparable.

New Type Float16


Introduced Float16 half precision floating point ( SE-0277 ). With the advent of machine learning on mobile devices in recent years, this only indicates Apple’s ambitions to promote this topic. Float 16 is commonly used on mobile GPUs for computing and as a compressed format for weights in ML applications.

let f16: Float16 = 7.29

Swift 5.3 has introduced many enhancements to the Swift Package Manager (SPM). Consider them.

  1. SE-0271 (Package Manager Resources) allows SPM to contain resources such as images, audio, JSON, and more.
  2. SE-0272 (Package Manager Binary Dependencies) allows SPM to use binary packages along with existing source package support. This means that shared, closed source SDKs such as Firebase can now be integrated using SPM.
  3. SE-0273 (Package Manager Conditional Target Dependencies) allows you to configure targets so that they have dependencies only for specific platforms and configurations. For example, you can designate special additional frameworks when compiling for Linux.
  4. SE-0278 allows you to add localized resources.

Thus, it can be stated that version 5.3 introduced some good innovations that will be picked up over time by developers.

All Articles