Swift 5 Release Notes for Xcode 10.2 beta

Update your code to use new language features and test your apps against changes.

Read these notes when you’re writing Swift apps in Xcode 10.2.

  • Swift apps no longer include dynamically linked libraries for the Swift standard library and Swift SDK overlays in build variants for devices running iOS 12.2, watchOS 5.2, and tvOS 12.2. As a result, Swift apps can be smaller when deployed for testing using TestFlight, or when thinning an app archive for local development distribution.

    To see the difference in file sizes between an app that’s thinned for iOS 12.2 and an app that’s thinned for iOS 12.1 or earlier, set your app’s deployment target to iOS 12.1 or earlier, then create an archive of your app with the scheme set to Generic iOS Device. After building the archive, select Distribute App from the Archives organizer, then select Development distribution. Be sure to select a specific device—such as iPhone XS—in the App Thinning pull-down menu. When the distribution process completes, open the App Thinning Size Report in the newly created folder. The variant for iOS 12.2 will be smaller than the variant for iOS 12.1 and earlier. The exact size difference depends on the number of system frameworks your app uses.

    For information about app thinning, see What is app thinning? in Xcode Help. For information about app file sizes, see View builds and file sizes in App Store Connect Help.

  • The @dynamicCallable attribute lets you call named types like you call functions using a simple syntactic sugar. The primary use case is dynamic language interoperability. (SE-0216)

    For example:

@dynamicCallable struct ToyCallable { func dynamicallyCall(withArguments: [Int]) {} func dynamicallyCall(withKeywordArguments: KeyValuePairs<String, Int>) {}
} let x = ToyCallable() x(1, 2, 3)
// Desugars to `x.dynamicallyCall(withArguments: [1, 2, 3])` x(label: 1, 2)
// Desugars to `x.dynamicallyCall(withKeywordArguments: ["label": 1, "": 2])`
  • Key paths now support the identity keypath (\.self), a WritableKeyPath that refers to its entire input value (SE-0227):

let id = \Int.self
var x = 2
print(x[keyPath: id]) // Prints "2"
x[keyPath: id] = 3
print(x[keyPath: id]) // Prints "3"
  • Prior to Swift 5, you could write an enumeration case that took variadic arguments: 

enum X { case foo(bar: Int...) }

func baz() -> X { return .foo(bar: 0, 1, 2, 3) } 

This wasn’t intentionally supported and now generates an error. (46821582)

Instead, change the enumeration case to take an array and explicitly pass an array in:

enum X { case foo(bar: [Int]) } 
func baz() -> X { return .foo(bar: [0, 1, 2, 3]) } 
  • In Swift 5 mode, try? with an expression of an Optional type flattens the resulting optional, instead of returning a nested optional. (SE-0230)

  • If a type T conforms to one of the protocols in Initialization with Literals—such as ExpressibleByIntegerLiteral—and literal is a literal expression, then T(literal) creates a literal of type T using the corresponding protocol, rather than calling an initializer of T with a value of the protocol’s default literal type.

    For example, expressions like UInt64(0xffff_ffff_ffff_ffff) are now valid, where previously they would overflow the default integer literal type of Int. (SE-0213)

  • String interpolation has improved performance, clarity, and efficiency. (SE-0228)

    The older _ExpressibleByStringInterpolation protocol is removed; if you have code that makes use of this protocol, you need to update it for the new design. You can use #if to conditionalize code between Swift 4.2 and Swift 5. For example:

#if compiler(<5)
extension MyType: _ExpressibleByStringInterpolation { /*...*/ }
extension MyType: ExpressibleByStringInterpolation { /*...*/ }
  • The DictionaryLiteral type is renamed KeyValuePairs. (SE-0214) (23435865)

  • Swift strings bridged into Objective-C code may now return a non-nil value from CFStringGetCStringPtr(_:_:) when appropriate, and the pointer returned from -UTF8String is tied to the string’s lifetime rather than the innermost autorelease pool. Correct programs shouldn’t have any problems and may see significant speed-ups. However, it may cause previously untested code to run, which could expose latent bugs; for example, if there’s a check for a non-nil value, the branch may never have been taken prior to Swift 5. (26236614)

  • The Sequence protocol no longer has a SubSequence associated type. Methods on Sequence that previously returned SubSequence now return concrete types. For example, suffix(_:) now returns an Array. (47323459)

    Extensions on Sequence that use SubSequence should be amended to either similarly use a concrete type, or be amended to be extensions on Collection instead, where SubSequence remains available. (45761817)

    For example:

extension Sequence { func dropTwo() -> SubSequence { return self.dropFirst(2) }


extension Sequence { func dropTwo() -> DropFirstSequence<Self> { return self.dropFirst(2) }


extension Collection { func dropTwo() -> SubSequence { return self.dropFirst(2) }
  • The String structure’s native encoding switched from UTF-16 to UTF-8, which may improve the relative performance of String.UTF8View compared to String.UTF16View. Consider re-evaluating any code specifically tuned to use String.UTF16View for performance. (42339222)

  • Targets can now declare some commonly used, target-specific build settings when using the Swift 5 Package.swift tools-version. The new settings can also be conditionalized based on platform and build configuration. The included build settings support Swift- and C-language defines, C language header search paths, linked libraries, and linked frameworks. (SE-0238) (23270646)

  • Packages can now customize the minimum deployment target setting for Apple platforms when using the Swift 5 Package.swift tools-version. Building a package emits an error if any of the package dependencies of the package specify a minimum deployment target greater than the package’s own minimum deployment target. (SE-0236) (28253354)

  • A new dependency mirroring feature allows top-level packages to override dependency URLs. (SE-0219) (42511642)

    Use the following command to set a mirror: 

$ swift package config set-mirror \
--package-url <original URL> --mirror-url <mirror URL>
  • The swift test command can generate code coverage data in a standard format suitable for consumption by other code coverage tools using the flag --enable-code-coverage. The generated code coverage data is available inside <build-dir>/<configuration>/codecov. (44567442)

  • Swift 5 no longer supports the Swift 3 Package.swift tools-version. Packages still on the Swift 3 Package.swift tools-version should update to a newer tools-version. (41974124)

  • Package manager operations for larger packages are now significantly faster. (35596212)

  • The Swift Package Manager has a new --disable-automatic-resolution flag that forces the package resolution to fail when the Package.resolved entries are no longer compatible with the dependency versions specified in the Package.swift manifest file. This feature can be useful for a continuous integration system to check if a package’s Package.resolved is out of date. (45822895)

  • The swift run command has a new --repl option that launches the Swift REPL with support for importing library targets of a package. This allows you to easily experiment with API from a package target without needing to build an executable that calls that API. (44889181)

  • For more information about using the Swift Package Manager, visit Using the Package Manager on swift.org.

  • Exclusive memory access is now enforced at runtime by default in optimized (-O and -Osize) builds. Programs that violate exclusivity will trap at runtime with an “overlapping access” diagnostic message. You can disable this using a command line flag: -enforce-exclusivity=unchecked, but doing so may result in undefined behavior. Runtime violations of exclusivity typically result from simultaneous access of class properties, global variables—including variables in top-level code—or variables captured by escaping closures. (SR-7139) (37830912)

  • Swift 3 mode has been removed. Supported values for the -swift-version flag are 4, 4.2, and 5. (43101816)

  • In Swift 5 mode, switches over enumerations that are declared in Objective-C or that come from system frameworks are required to handle unknown cases—cases that might be added in the future, or that may be defined privately in an Objective-C implementation file. Formally, Objective-C allows storing any value in an enumeration as long as it fits in the underlying type. These unknown cases can be handled by using the new @unknown default case, which still provides warnings if any known cases are omitted from the switch. They can also be handled using a normal default case.

    If you’ve defined your own enumeration in Objective-C and you don’t need clients to handle unknown cases, you can use the NS_CLOSED_ENUM macro instead of NS_ENUM. The Swift compiler recognizes this and doesn’t require switches to have a default case.

    In Swift 4 and 4.2 modes, you can still use @unknown default. If you omit it and an unknown value is passed into the switch, the program traps at runtime, which is the same behavior as Swift 4.2 in Xcode 10.1. (SE-0192) (39367045)

  • Default arguments are now printed in SourceKit-generated interfaces for Swift modules, instead of just using a placeholder default. (18675831)

  • unowned and unowned(unsafe) variables now support Optional types. (47326769)

  • The Swift compiler crashes in the “Merge swiftmodule” build step if any members of the UIAccessibility structure are referenced. The build log includes a message that says:

Cross-reference to module 'UIKit'
... UIAccessibility
... in an extension in module 'UIKit'
... GuidedAccessError 

This issue may also occur with other types that contain NS_ERROR_ENUM enumerations, but UIAccessibility is the most common one. (47152185)

Workaround: Build that target using the Whole Module option for the Compilation Mode build setting under “Swift Compiler - Code Generation”. This is the default for most Release configurations.

  • To reduce the size taken up by Swift metadata, convenience initializers defined in Swift now only allocate an object ahead of time if they’re calling a designated initializer defined in Objective-C. In most cases, this has no effect on your program, but if your convenience initializer is called from Objective-C, the initial allocation from +alloc is released without any initializer being called. This can be problematic for users of the initializer that don’t expect any sort of object replacement to happen. One instance of this is with init(coder:): the implementation of NSKeyedUnarchiver may behave incorrectly if it calls into Swift implementations of init(coder:) and the archived object graph contains cycles.

    In a future release, the compiler will guarantee that a convenience initializer never discards the object it was invoked on as long as the initializer it delegates to via self.init is also exposed to Objective-C, either because it’s defined in Objective-C, or because it’s marked with @objc, or because it overrides an initializer exposed to Objective-C, or because it satisfies a requirement of an @objc protocol. (46823518)

  • If a key path literal refers to a property that’s defined in Objective-C or is defined with the @objc and dynamic modifiers in Swift, then compilation may fail with an “unsupported relocation of local symbol 'L_selector'” error, or the key path may not generate the correct hash value or equality comparison with other key paths at runtime. (47184763)

    Workaround: You can define a wrapper property that isn’t @objc, and refer to that key path instead. The resulting key path isn’t equal to a key path that would have referred to the original Objective-C property, but applying the key path has the same effect.

  • Some projects might experience compile time regressions from previous releases. (47304789)

  • Swift command line projects crash on launch with “dyld: Library not loaded” errors. (46824656)

    Workaround: Add a user-defined build setting SWIFT_FORCE_STATIC_LINK_STDLIB=YES.

  • Extension binding now supports extensions of nested types which themselves are defined inside extensions. Previously this could fail with some declaration orders, producing spurious “undeclared type” errors. (SR-631) (20337822)

  • In Swift 5 mode, a class method that returns Self can no longer be overridden with a method that returns a concrete class type that isn’t final. Such code isn’t type safe and needs to be updated. (SR-695) (47322892)

    For example:

class Base { class func factory() -> Self { /*...*/ }
} class Derived: Base { class override func factory() -> Derived { /*...*/ } } 
  • In Swift 5 mode, attempting to declare a static property with the same name as a nested type is now always correctly rejected. Previously, it was possible to perform such a redeclaration in an extension of a generic type. (SR-7251) (47325738)

    For example:

struct Foo<T> {}
extension Foo { struct i {} // Error: Invalid redeclaration of 'i'. // (Prior to Swift 5, this didn’t produce an error.) static var i: Int { return 0 }
  • Designated initializers with variadic parameters are now correctly inherited in subclasses. (16331406)

  • In Swift 5 mode, @autoclosure parameters can no longer be forwarded to @autoclosure arguments in another function call. Instead, you must explicitly call the function value with parentheses: (); the call itself is wrapped inside an implicit closure, guaranteeing the same behavior as in Swift 4 mode. (SR-5719) (37321597)

    For example:

func foo(_ fn: @autoclosure () -> Int) {}
func bar(_ fn: @autoclosure () -> Int) { foo(fn) // Incorrect, `fn` can’t be forwarded and has to be called. foo(fn()) // OK
  • Complex recursive type definitions involving classes and generics that would previously cause deadlocks at runtime are now fully supported. (38890298)

  • In Swift 5 mode, when casting an optional value to a generic placeholder type, the compiler will be more conservative with the unwrapping of the value. The result of such a cast now more closely matches the result you would get in a nongeneric context. (SR-4248) (47326318)

    For example:

func forceCast<U>(_ value: Any?, to type: U.Type) -> U { return value as! U } let value: Any? = 42
print(forceCast(value, to: Any.self))
// Prints "Optional(42)"
// (Prior to Swift 5, this would print "42".) print(value as! Any)
// Prints "Optional(42)"
  • Protocols can now constrain their conforming types to those that subclass a given class. Two equivalent forms are supported:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 

Swift 4.2 accepted the second form, but it wasn’t fully implemented and could sometimes crash at compile time or runtime. (SR-5581) (38077232)

  • In Swift 5 mode, when setting a property from within its own didSet or willSet observer, the observer will now only avoid being recursively called if the property is set on self (either implicitly or explicitly). (SR-419) (32334826)

    For example:

class Node { var children = [Node]() var depth: Int = 0 { didSet { if depth < 0 { // Won’t recursively call didSet, because this is setting depth on self. depth = 0 } // Will call didSet for each of the children, // as this isn’t setting the property on self. // (Prior to Swift 5, this didn’t trigger property // observers to be called again.) for child in children { child.depth = depth + 1 } } }
  • #sourceLocation is now honored when diagnostics are emitted in Xcode. That is, if your source uses #sourceLocation to map lines in a generated file back to the original source, diagnostics now show up in the original source file rather than in the generated file. (43647151)

  • Using a generic type alias as the parameter or return type of an @objc method no longer results in the generation of an invalid Objective-C header. (SR-8697) (43347303)