- Swift 5.0 new feature update
- Long-awaited
Swift, 5.0
At last,Swift, 5.0
isSwift
One of the most closely watched versions of the legendaryABI
Stable version - As the
The Xcode 10.2 beta
Release,Swift, 5.0
A beta version has also been released, which I believe brings many optimizations and improvements - The following runtime environment is in
The Xcode 10.2 beta
In the environment
New features
dynamicCallable
- SE-0216
@dynamicCallable
forSwift
Added a new property that allows named types to be called using a simple syntactic sugar like a function call- If you need to add
@dynamicCallable
Property 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 be
String
.Int
And so on… KeyValuePairs
The 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
@dynamicCallable
Precautions for Use- You can apply it to structures, enumerations, classes, and protocols.
- If you implement
withKeywordArguments:
And it didn’t happenwithArguments:
, you can still call it without a parameter label - If your implementation
withKeywordArguments:
orwithArguments:
The markedthrow
, calls to the type will also be thrownthrow
- The extension cannot be added
@dynamicCallable
Can 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
Swift
Each 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 followingSwift
understand"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
- in
Swift4.2
And 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 - in
Swift 5
If the current value is optional, thentry?
Values are not wrapped in optional values, so the end result is just oneString?
- So in
Swift 5
In the end, the return value is always just an optional value - Again, if you use an optional link
as?
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 types
isMultiple
- 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
- in
Swift
In the previous version, there was a functionfilter
You 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 - in
Swift 5
A 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
- in
Swift4.x
The version has two functionscompactMap
andmapValues
compactMap
: Returns a new array after an operation, similarlyflatMap
mapValues
: dictionary functions, for dictionariesvalue
Value performs an operation that returns changesvalue
After 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-0218in
Swift 5
A new function is added to thecompactMapValues
compactMapValues
Is to combine the functions of the above two methods and return a pairvalue
New 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
Sequence
The agreement no longer hasSubSequence
Association type. Previously returnedSubSequence
theSequence
Method will now return the concrete type- use
SubSequence
theSequence
The extension should be modified to similarly use concrete types, or modified toCollection
The extension inCollection
In theSubSequence
Is 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 of
Swift 5
Package manager,Targets
You can declare some common target-specific onesbuild settings
Set up the - New Settings can also be conditional based on platform and build configurations. Contains build Settings support
Swift
andC
Language definition,C
Language header file search path, link library and link framework
SE- 0236
- In the use of
Swift 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!