Technology Blog

Look deep into latest news and innovations happening in the Tech industry with our highly informational blog.

What’s new in Swift 5.3

hkis

The Announcement

On the 25th of March Apple announced that the release process for Swift 5.3 has begun, it’s a major change since it will improve the overall language quality and performance, and will make Swift available for multiple platforms as Windows and Linux. But let’s see in detail whats new.

swift-5-3-banner

Enum Cases as Protocol Witnesses

Currently a class extending a protocol needs to match exactly the protocol’s requirements, for example if we write static requirements within a protocol:

protocol DecodingError {
  static var fileCorrupted: Self { get }
  static func keyNotFound(_ key: String) -> Self
}

And then we try to conform an enum to our protocol, we’ll face the following error:

pic courtesy: medium.com

With SE-0280 this will no longer cause a compiling error.

Multiple Trailing Closures

Swift 5.3 finally introduced the possibility to use multiple trailing closures.

Some Background

First of all for those who don’t know what a trailing closure is, it’s a simple syntactic sugar that we can use when we have a closure parameter in a function:

func networkCall(parameter:Int, onSuccess:(Any)->Void) {
    //network call
    onSuccess("someNetworkResult")
}

and we can simply call the function as follows:

networkCall(parameter: 1) { (result) in

    print(result) 

}
The problem

This is an amazing feature and allows us to write cleaner and easier to read code, however it’s currently limited only to the last parameter of a function as we can see in the following example:

pic courtesy: medium.com

The Proposed Solution

With SE-0279 we will be allowed to insert extra trailing closures, just by adding extra labels, therefore the following code will compile.

networkCall(parameter: 1){(progress) in
    
    print(progress)
    
}, onSuccess{ (result) in
    
    print(result)
}

A New Float16 Type

The last decade has seen a dramatic increase in the use of floating-point types smaller than (32-bit) Float. The most widely implemented is Float16, which is used extensively on mobile GPUs for computation, as a pixel format for HDR images, and as a compressed format for weights in ML applications.

Introducing the type to Swift is especially important for interoperability with shader-language programs; users frequently need to set up data structures on the CPU to pass to their GPU programs. Without the type available in Swift, they are forced to use unsafe mechanisms to create these structures.

Multi-Pattern Catch Clauses

Currently swift allows only a single error type for each catch clause, that means that if we define the following enum

enum NetworkError: Error {
    case timeout, serverError
}

Assuming someNetworkCall is a function that throws a NetworkError, and we want to handle both errors, we will need to write two separate catch clauses:

func networkCall(){
  do{
    try someNetworkCall()
  }catch NetworkError.timeout{
    print("error")
  }catch NetworkError.serverError{
    print("error")
  }

}

With SE-0276 we will be allowed to handle both errors on a single catch clause, with the following code:

func networkCall(){
  do{
    try someNetworkCall()
  }catch NetworkError.timeout, NetworkError.serverError{
    print("error")
  }
}

Add Collection Operations on Noncontiguous Elements

Currently we can use Range to refer to multiple consecutive positions in a Collection, but there’s not a simple way to do this for discontiguous positions, based on some condition.

For example if we have an array of numbers from 0 to 15 and we want to get a sub range of the Array, let’s say with only even numbers, the language doesn’t provide any way to get it, or even to get a sub Array with elements with non contiguous positions, but we can only select a range of contiguous elements:

pic courtesy: medium.com

SE-0270 adds a super useful “RangeSet” Method that will allow us to get a subRange of all the indexes of the elements that satisfy a specific condition, therefore, if we want to get only even numbers from the previous array, the following code will work:

var numbers = Array(1...15)

// Find the indices of all the even numbers
let indicesOfEvens = numbers.subranges(where: { $0.isMultiple(of: 2) })

// Perform an operation with just the even numbers
let sumOfEvens = numbers[indicesOfEvens].reduce(0, +)
// sumOfEvens == 56
// You can gather the even numbers at the beginning
let rangeOfEvens = numbers.moveSubranges(indicesOfEvens, to: numbers.startIndex)
// numbers == [2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15]
// numbers[rangeOfEvens] == [2, 4, 6, 8, 10, 12, 14]

Increase Availability of Implicit self in @escaping Closures when Reference Cycles are Unlikely to Occur

Currently in closures we need to use explicit self even in some cases where reference cycles are unlikely to happen, for example because we already captured self in the current closure:

pic courtesy: medium.com

To make our code compile we need to add explicit self to x in order to reference it.

Refine didSet Semantics

Currently, if we have a property with a “didSet” observer, the getter to get the oldValue is always called, even if observer doesn’t contain any reference to the oldValue in its body, for example the following code

struct Container {
  var items: [Int] = .init(repeating: 1, count: 100) { //creates an Array of 100 elements 
    didSet {
      print("value set")//oldValue never Accessed
    }
  }
  
  mutating func update() {
    for index in 0..<items.count {
      items[index] = index + 1
    }
  }
}

var container = Container()
container.update()

creates 100 copies of the array in the memory to provide the oldValue, even though they’re not used at all, causing performance issues.

With SE-0268 the property getters will be no longer called if they’re not accessed within the didSet resulting in a performance boost.

class Foo {
  var bar = 0 {
    didSet { print("didSet called") }
  }

  var baz = 0 {
    didSet { print(oldValue) }
  }
}

let foo = Foo()
// This will not call the getter to fetch the oldValue
foo.bar = 1
// This will call the getter to fetch the oldValue
foo.baz = 2

Where Clauses on Contextually Generic Declarations

Currently a where clause on a member declaration can be used only by placing the member inside a specific extension, but this can sound confusing, let’s make an example.

Let’s say we want to extend the Array implementation to sort element of 3 different types, for which we want to define a different sorting logic.
Currently we would need to extend Array 3 times:

extension Array where Element == String {
    func sortStrings() { ... } //some specific sorting logic
}
extension Array where Element == Int {
    func sortInts() { ... } //some specific sorting logic
}
extension Array where Element: Equatable {
    func sort() { ... } //some specific sorting logic
}

With SE-0267 we can implement that logic by simply adding the where clause to the function in a single extension:

extension Array where Element: Equatable {
    func sort() { ... }

    func sortInts() where Element == Int { ... }

    func sortStrings() where Element == String { ... }
}

Synthesized Comparable Conformance for Enum Types

Let’s say we want to define an Enum whose cases have an obvious semantic order, for example:

enum SchoolGrades {
   case F         
   case E
   case D
   case C
   case B
   case A
}

If we try to compare its values we got the following error:

pic courtesy: medium.com

What’s wrong here?

In order to compare two Objects, they need to conform the Comparable protocol:

pic courtesy: medium.com

looking at the warning this will generate a loop, since the < function will be calling itself, therefore we need to compare the rawValues so that we can finally compare our grades.

pic courtesy: medium.com

This, is just a simple case, and it adds a lot of boilerplate code.

With SE-0266 this will not be necessary and we don’t need any additional code to compare Enums.

For more information and to build a mobile APP using iOS, Hire iOS Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop your mobile APP using iOS, please visit our technology page.

Content Source:

  1. medium.com