• Swift 5.0 new feature update
  • Long-awaitedSwift, 5.0At last,Swift, 5.0isSwiftOne of the most closely watched versions of the legendaryABIStable version
  • As theThe Xcode 10.2 betaRelease,Swift, 5.0A beta version has also been released, which I believe brings many optimizations and improvements
  • The following runtime environment is inThe Xcode 10.2 betaIn the environment

New features

dynamicCallable

  • SE-0216
  • @dynamicCallableforSwiftAdded a new property that allows named types to be called using a simple syntactic sugar like a function call
  • If you need to add@dynamicCallableProperty must implement one or two of the following methods
func dynamicallyCall(withArguments args: [Int]) -> Double

func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double
Copy the code
  • Note:
  • In addition to accepting various inputs, you can also provide multiple overloads for various outputs, with custom return values, which can beString.IntAnd so on…
  • KeyValuePairsThe use and introduction of, not usedMay refer to

For an example, RandomNumberGenerator generates a random number

Definition and invocation prior to Swift 5.0

// Define the mode
struct RandomNumberGenerator {
    func generate(numberOfZeroes: Int) -> Double {
        let maximum = pow(10.Double(numberOfZeroes))
        return Double.random(in: 0. maximum) } }// Call mode
let random = RandomNumberGenerator(a)let num = random.generate(numberOfZeroes: 2)
print(num)
Copy the code

Use the @dynamicCallable attribute in Swift 5.0

// Define the mode
@dynamicCallable
struct RandomNumberGenerator {
    func dynamicallyCall(withArguments args: [Int]) -> Double {
        let numberOfZeroes = Double(args.first ?? 0)
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0. maximum) } }// Call mode
let random = RandomNumberGenerator(a)let num = random(2)
// random(2) equals random. DynamicallyCall (withArguments: [2])
print(num)
Copy the code
  • @dynamicCallablePrecautions for Use
  • You can apply it to structures, enumerations, classes, and protocols.
  • If you implementwithKeywordArguments:And it didn’t happenwithArguments:, you can still call it without a parameter label
  • If your implementationwithKeywordArguments:orwithArguments:The markedthrow, calls to the type will also be thrownthrow
  • The extension cannot be added@dynamicCallableCan only be added to major types
  • You can still add other methods and attributes to your defined types, and they work fine

WritableKeyPath

  • SE-0227
  • Add the ability to identify the key path by reference to the entire input value that applies it
  • SwiftEach value in. Has a special pseudo-attribute. Self, which refers to the entire value
let id = \Int.self  
var x = 1
print(id)   ////Swift.WritableKeyPath<Swift.Int, Swift.Int>
x.self = 2
print(x)   //2
print(x.self)  //2

print(x[keyPath: id])  //2
x[keyPath: id] = 3
print(x[keyPath: id])  //3
Copy the code

Optional parameters

Before Swift 5, it was possible to write an enumeration with mutable parameters, but starting with Swift 5, the call would return an error, as follows

enum X {
    // No error is reported when the cut is not called
    case foo(bar: Int...). }func baz(a) -> X {
    // An error is reported when called here
    return .foo(bar: 0.1.2.3)}Copy the code

After Swift 5, the above definition is changed to array parameters, not mutable parameters, as follows

enum X {
    case foo(bar: [Int])}func baz(a) -> X {
    return .foo(bar: [0.1.2.3])}Copy the code

Raw Strings

\To deal with

  • Se-0200 adds the ability to create raw strings in which backslashes and quotes are interpreted as literal symbols rather than escape characters or string terminators
  • Single-line string literals can be padded with backslashes to preserve the original string, otherwise an error will be reported
// Text reference type
// Error
let quote = "Alice: "How long is forever?" White Rabbit: "Sometimes, just one second.""
// Write it correctly
let quote1 = "Alice: \"How long is forever? \" White Rabbit: \"Sometimes, just one second.\""


// Regular table French type
// Error
let ucCaseCheck = "enum\s+.+\{.*case\s+[:upper:]"
// Write it correctly
let ucCaseCheck = "enum\\s+.+\\{.*case\\s+[:upper:]"
Copy the code

#To deal with

  • To use the raw string, use the#Wrap the string
  • #The symbols at the beginning and end of the string become part of the string separator, so the followingSwiftunderstand"Rain"and"-"The surrounding individual quotes should be treated as literal quotes rather than closing strings
  • Raw strings also allow backslashes, but treat backslashes as literal characters in strings, not as escape characters
let rain = #"The "rain" in "Spain" falls mainly on the Spaniards."#

let keypaths = #"Swift keypaths such as \Person.name hold uninvoked references to properties."#

let answer = 42
let dontpanic = #"The answer to life, the universe, and everything is \#(answer)."#
Copy the code

Note: we used the \#(answer) reference variable above instead of \(answer), because the backslash in a string wrapped in # will be failed as a literal character instead of an escape character, so we must add an extra #

# #To deal with

  • Used at the beginning and end of a string#Processing, you can use special characters like backslashes in a string, if you need to use them in a string#And how to deal with it?
  • use#Wrap string, default to#Is the end of the string,#The following text will no longer be processed, in which case we will use it# #To deal with
  • Note: The identifiers at the beginning and end of a string must be the same
let str = ##"My dog said "woof"#gooddog"# #Copy the code

Multiline string

Raw strings are fully compatible with Swift’s multi-line string system – just use #””” “start, then “””# end

let multiline = #"""
    The answer to life,
    the universe,
    and everything is \#(answer).
    """#
Copy the code

try? nested

Let’s start with the following code

struct User {
    var id: Int

    init? (id:Int) {
        if id < 1 {
            return nil
        }

        self.id = id
    }

    func getMessages(a) throws -> String {
        // complicated code here
        return "No messages"}}Copy the code

In Swift4.2 and earlier versions

let user = User(id: 1)
// Let messages: String??
let messages = try? user? .getMessages()// We need it if we want non-optional values
print((messages ?? "")??"")
// Multiple strong solutions are not recommended
print(messages!!)
Copy the code
  • inSwift4.2And its predecessors, the above returns an optional value with two levels of nesting, which can be much more cumbersome to handle if there are multiple levels of nesting
  • inSwift 5If the current value is optional, thentry?Values are not wrapped in optional values, so the end result is just oneString?
  • So inSwift 5In the end, the return value is always just an optional value
  • Again, if you use an optional linkas?You still only have one level of optionality
let user = User(id: 1)
// Type: let messages: String?
let messages = try? user? .getMessages()print(messages ?? "")
Copy the code

isMultiple

  • SE-0225Added a method for integer typesisMultiple
  • This method checks whether an integer is a multiple of another integer
let rowNumber = 4

if rowNumber.isMultiple(of: 2) {
    print("Even")}else {
    print("Odd")}// This method is equivalent to
if rowNumber % 2= =0 {}
Copy the code

count

  • SE-0220
  • inSwiftIn the previous version, there was a functionfilterYou can filter out the elements that meet the conditions in the array, forming a new array, detailed use can refer toAdvanced use of Swift functional programming
  • inSwift 5A new function is added to thecount(where:)Gets the number of eligible elements in the array
let arr = [1.2.34.5.6.7.8.12.45.6.9]

let filter = arr.filter({$0 > 10 })
print(filter)  / / [45] 12, 34,

let count = arr.count(where: {$0 > 10 })
print(count)  / / 3
Copy the code

compactMapValues

  • inSwift4.xThe version has two functionscompactMapandmapValues
  • compactMap: Returns a new array after an operation, similarlyflatMap
  • mapValues: dictionary functions, for dictionariesvalueValue performs an operation that returns changesvalueAfter the new dictionary
let times = [
    "first": 2."second": 43."three": 12."four": 3
]

let compact = times.compactMap({ $0.value > 10 })
print(compact)
// [true, false, true, false]

let mapValues = times.mapValues({ $0 + 2 })
print(mapValues)
// ["second": 45, "first": 4, "three": 14, "four": 5]
Copy the code
  • SE-0218inSwift 5A new function is added to thecompactMapValues
  • compactMapValuesIs to combine the functions of the above two methods and return a pairvalueNew dictionary after operation, and automatically filter unqualified key-value pairs
let times1 = [
    "Hudson": "38"."Clarke": "42"."Robinson": "35"."Hartis": "DNF"
]

let comMap2 = times1.compactMapValues({ Int($0)})print(comMap2)
// ["Clarke": 42, "Robinson": 35, "Hudson": 38]
Copy the code

SubSequence

  • SequenceThe agreement no longer hasSubSequenceAssociation type. Previously returnedSubSequencetheSequenceMethod will now return the concrete type
  • useSubSequencetheSequenceThe extension should be modified to similarly use concrete types, or modified toCollectionThe extension inCollectionIn theSubSequenceIs still available
// Swift 5 is not supported
extension Sequence {
    func dropTwo(a) -> SubSequence {
        return self.dropFirst(2)}}// It is recommended to change to
extension Sequence {
    func dropTwo(a) -> DropFirstSequence<Self> { 
        return self.dropFirst(2)}}/ / or
extension Collection {
    func dropTwo(a) -> SubSequence {
        return self.dropFirst(2)}}Copy the code

Other Related Updates

SE-0214

The DictionaryLiteral type was renamed KeyValuePairs

SE-0238

  • In the use ofSwift 5Package manager,TargetsYou can declare some common target-specific onesbuild settingsSet up the
  • New Settings can also be conditional based on platform and build configurations. Contains build Settings supportSwiftandCLanguage definition,CLanguage header file search path, link library and link framework

SE- 0236

  • In the use ofSwift 5“, you can customize the lowest version number supported by the project. If the lowest version supported by the dependent package of the project is greater than the lowest version number of the project, the project displays an error

SR-695

Class methods that return Self are no longer supported in Swift 5

// Not supported
class Base { 
    class func factory() - >Self { / *... * /}}Copy the code

SR-631

Extensions in different files are not mutually identifiable

class FirstClass {}extension FirstClass {
    class SecondClass {}}"SecondClass is not a member type of FirstClass"
extension FirstClass.SecondClass { 
    class ThirdClass {}}Copy the code

SR-7251

In Swift 5, the variable name declared in a declared class cannot be the same as the class name

struct S {}
extension S {
  static var i: Int { return 0 }
  struct i {} // error: the declaration of "I" is invalid
}

// The following way is ok
struct S1<T> {}
extension S1 {
  static var i: Int { return 0 }
  struct i {} // This is fine!
}
Copy the code

reference

  • Swift 5 official document
  • What’s new in Swift 5.0

Please scan the following wechat official account and subscribe to my blog!