Swift 5有什么新功能?

嗨,我叫伊利亚。 我是Tinkoff.ru的iOS开发人员。 在本文中,我将简要概述Swift 5中的主要更改。这些更改在发行说明中进行了描述。 对于尚未熟悉自己的人,欢迎猫来!



应用程序的大小将减小!


用Swift 5编写并针对iOS 12.2,watchOS 5.2,tvOS 12.2编译的应用程序将不包含Swift标准库和Swift SDK的动态库。 这意味着应用程序的大小将减少很多。 如果您相信此推文 ,则空项目的大小将从2.4 Mb减少到24 Kb。 对于小型应用程序,这是一个很好的结果,但是对于大型应用程序,则没有太大的区别。

@dynamicCallable( SE-0216


@dynamicCallable属性允许将对象作为函数使用。 此类对象称为功能对象或函子(可在此处找到更多详细信息)。 功能对象使用C ++,Python,JavaScript和其他语言,而在Swift中则添加了它们以与这些语言兼容。 事实是,Swift现在可以与API C和Objective-C很好地交互,并且语言开发人员希望添加与动态语言(Python,JavaScript,Ruby和其他语言)的交互。

为了使类型成为函子,必须在其声明中添加@dynamicCallable属性。 考虑一个可用于在数组中加数字的Reducer结构示例:

@dynamicCallable struct Reducer { ... } 

然后,您需要实现以下一种或两种方法:

 func dynamicallyCall(withArguments: ExpressibleByArrayLiteral) func dynamicallyCall(withKeywordArguments: ExpressibleByDictionaryLiteral) 

第一个功能允许您通过传递数组作为参数来访问对象。 第二个函数允许您访问对象,并传递与参数相同的数组,但是使用参数的名称。

例如, Reducer结构的第一个功能的实现如下所示:

 func dynamicallyCall(withArguments arguments: [Int]) -> Int { return arguments.reduce(0, +) } 

然后应用如下结构:

 let reducer = Reducer() let sum = reducer(1, 2, 3) // sum = 6 

我们将使用Comparator结构的示例来考虑第二种方法的实现,通过该示例我们可以比较两个数字:

 @dynamicCallable struct Comparator { func dynamicallyCall(withKeywordArguments arguments: KeValuePairs<String, Int>) -> ComparisonResult { guard let lhs = arguments["lhs"], let rhs = arguments["rhs"], lhs != rhs else { return .orderedSame } return lhs > rhs ? .orderedDescending : .orderedAscending } } 

您可以按以下方式使用此结构:

 let comparator = Comparator() let comparisionResult = comparator(lhs: 1, rhs: 2) // comparisionResult = .orderedAscending 

开关中的未知属性( SE-0192


许多人都知道,在处理枚举值时,有必要描述所有情况,并尽量不要使用默认值。 尽管此要求增加了一定的安全性,但它也有一个缺点,因为在枚举中更改值时,您需要添加其处理。 系统框架仍可能会更改其中一个枚举,但是您的应用程序尚未对此进行处理(例如,使用LABiometryType进行了更改 )。

Swift 5将添加unknown属性,这将允许您在处理枚举时分离2个不同的场景:

  • 对于所有未在switch中处理的情况,都应执行默认代码
  • 所有案例都在switch中处理,如果添加了新案例,那么您需要在默认情况下使用代码

让我们看一个例子:

 enum HTTPMethod { case post, get, put } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") default: print("Put") } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") @unknown default: print("Unknown HTTP method") } 

摆脱double可选,因为使用try调用了函数? ( SE-0230


当然有很多人遇到这样的事实,即在调用throwable函数时,它使用try方法返回Optional ,结果是一个包装在两个Optional中的类型。 这不是很方便,因此在Swift 5中,请尝试吗? 在这种情况下,将返回仅包装在一个Optional中的类型。

这是Swift 5之前的样子:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType?? 

因此它将在Swift 5中:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType? 

多重性检查( SE-0225


要检查一个数字与另一个数字的多重性,可以使用isMultiple(:)函数,而不是除数的余数(%):

 //   let isEven = 4 % 2 == 0 //   let isEvent = 4.isMultiple(of: 2) 

所做的更改很小,但是使代码更清晰,并简化了代码搜索。

对带有条件的序列中的元素数进行计数( SE-0220


在Swift 5中,Sequence类型将添加count(其中:(Element)-> Bool)-> Int方法,该方法允许您一次计算满足给定条件的序列中的元素数。 在此之前,我必须结合使用filtercount 。 该方法将节省在filter方法中创建新数组时分配的内存。

一个例子:

 let countOfZeroes = [0, 1, 2, 0, 4].count(where: { $0 == 0 }) // countOfZeroes = 2 

词典中的CompactMapValues方法( SE-0218


此方法将Array中的 compactMapDictionary中的 mapValues组合在一起。 调用此方法的结果是,创建了一个具有转换值的字典,其中没有等于nil的值。

一个例子:

 let dictionary = ["a": "1", "b": "2", "c": "Number"] let resultDictionary = dictionary.compactMapValues { Int($0) } // resultDictionary = ["a": 1, "b": 2] 

原始字符串( SE-0200


新增了写引号和反斜杠用作常规字符而不是特殊字符的行的功能。 为此,请在行的开头和结尾添加#字符。

一个例子:

 let string1 = #"   " ""# let string2 = #"  \ "# 

如果要在创建行时插入变量,则在反斜杠后需要添加#号:

 let string = #"   \#(variable)"# 

如果该行带有#号,则需要在该行的开头和结尾添加两个##符号:

 let string = ##"   #"## 

序列协议不再包含关联的类型SubSequence( SE-0234


SubSequence的关联类型已从Sequence协议移至Collection, 现在 Sequence中所有返回SubSequence的方法返回特定类型。 例如, 后缀方法现在返回一个Array 。 这是受此更改影响的方法的完整列表:

 extension Sequence { public func dropFirst(_ k: Int = 1) -> DropFirstSequence<Self> public func dropLast(_ k: Int = 1) -> [Element] public func suffix(_ maxLength: Int) -> [Element] public func prefix(_ maxLength: Int) -> PrefixSequence<Self> public func drop(while predicate: (Element) throws -> Bool) rethrows -> DropWhileSequence<Self> public func prefix(while predicate: (Element) throws -> Bool) rethrows -> [Element] public func split( maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true, whereSeparator isSeparator: (Element) throws -> Bool ) rethrows -> [ArraySlice<Element>] } 

现在,使用这些方法将变得更加容易。

协议限制


协议现在以实现该协议的类的形式支持该限制。 换句话说,您现在可以指示协议只能由特定的类实现。 例如:

 protocol Viewable: UIView {} protocol Viewable where Self: UIView {} 

Swift 4.2支持第二个录制选项,但可能会导致编译错误或运行时。 在Swift 5中,不会发生此错误。

结论


这不是Swift 5中更改的完整列表;此处仅收集主要更改。 通常,所呈现的变化是积极的,并使语言更易于理解和灵活。 最主要的是,“转换为当前的Swift语法”应该很轻松。

就这样,谢谢您的阅读。

Source: https://habr.com/ru/post/zh-CN437942/


All Articles