swift keypath_我使用Swift KeyPath进行实验的故事

本文讲述了作者使用Swift KeyPath进行的一系列实验,通过实例解析KeyPath的用法和应用场景。
摘要由CSDN通过智能技术生成

swift keypath

Image for post
Unsplsh.com Unsplsh.com

KeyPath refers to a property itself instead of property’s value. They‘re useful when you want to perform operations on property, rather on the value behind it.

KeyPath是指属性本身而不是属性的值。 当您要对属性(而不是属性值)执行操作时,它们很有用。

Let’s take an example:

让我们举个例子:

Image for post

KeyPath let us refer to the properties without accessing them using . like this: \type name.path .

KeyPath让我们无需使用访问属性即可引用属性. 像这样: \type name.path

nameKeyPath syntax in the screenshot is <User, String> where User is type name and String is path name.

屏幕快照中的nameKeyPath语法为<User,String>,其中User为类型名称, String为路径名称。

This struct has an issue now, it won’t let me update nameKeyPath value as it’s declared let. It gives below error on assigning value so to update nameKeyPath value from outside of type need to declare it public.

这个结构现在有问题,因为声明为let ,所以不会让我更新nameKeyPath值。 它在分配值时出现以下错误,因此从类型外部更新nameKeyPath值需要将其声明为public。

Image for post

Let’s make the name of User public, on making it public key path becomes WritableKeyPath<User, String>. Values can be assigned only on WritableKeyPath

让我们将Username User public,将其公钥路径变为WritableKeyPath<User, String> 。 只能在WritableKeyPath上分配值

Image for post

Although it helps in meeting criteria but the type is mutated from outside, had to compromise by making name and user property var.

尽管它有助于满足条件,但是类型是从外部变异的,但必须通过使nameuser属性var折衷。

Let’s use private(set)

让我们使用private(set)

Image for post

Now I have 2 problems:

现在我有两个问题:

  • I don’t have access to WritableKeyPath outside Type, so compiler gives error on assigning data using KeyPath

    我无法访问Type之外的WritableKeyPath ,因此编译器在使用KeyPath分配数据时出现错误

  • Another is I are mutating property, ‘mutating’ function can only be called on vars

    另一个是我正在变异属性,“变异”功能只能在vars上调用

To mitigate this problem, I created a protocol that can be called on any struct to make a new copy with only one property changed.

为了缓解这个问题,我创建了一个协议,可以在任何结构上调用该协议以仅更改一个属性即可创建新副本。

使用KeyPath修改Struct属性值 (Modify Struct Property value using KeyPath)

Image for post

Using update function I can update value of any property.

使用update功能,我可以更新任何属性的值。

Image for post

First KeyPath is casted toWritableKeyPath and then update(keyPath:value:) is called on it.

首先将KeyPath update(keyPath:value:)WritableKeyPath ,然后在其上调用update(keyPath:value:)

This solution works perfectly for updating any property value but let’s say I have to update the value of 3 properties that requires us to repeat the code of casting multiple times. So let’s move casting to protocol extension. While moving casting code I realized that instead of KeyPath I should pass PartialKeyPath which just accepts root type.

该解决方案非常适合更新任何属性值,但是假设我必须更新3个属性的值,这需要我们重复多次铸造代码。 因此,让我们将强制转换扩展到协议扩展。 在移动转换代码时,我意识到我应该传递PartialKeyPath而不是KeyPath ,该PartialKeyPath仅接受根类型。

  • PartialKeyPath — It’s useful when you need to send keyPath to another function or you want to store keypaths of similar type.

    PartialKeyPath-当您需要将keyPath发送到另一个函数或要存储类似类型的键路径时,此功能很有用。

  • AnyKeyPath — It’s useful when you want to store key paths of any type into an array.

    AnyKeyPath —在要将任何类型的键路径存储到数组中时很有用。

Image for post

Finally 🎉 KeyPathEditable protocol can be conformed by any struct to make a new copy with only one property changed

最后🎉KeyPathEditable方案可以通过任何结构效法作出新的副本只有一个属性改变

Image for post

Complete source code can be found here

完整的源代码可以在这里找到

使用KeyPath修改类属性 (Modify class property using KeyPath)

We can’t use existing KeyPathEditable protocol here as that creates a copy on modifying property value. Let’s create a new protocol to modify a property value only

我们不能在这里使用现有的KeyPathEditable协议,因为它会在修改属性值时创建一个副本。 让我们创建一个新协议以仅修改属性值

If you notice apart from copy there is one more difference b/w this protocol and previous protocol. With class type we can’t specify Self type in protocol, it gives error:

如果您发现除copy外,本协议与以前的协议还有另一个不同之处。 对于class类型,我们无法在协议中指定“ Self类型,但会出现错误:

Error: protocol can only be used as a generic constraint because it has Self or associated type requirements

错误:协议只能用作通用约束,因为它具有“自我”或相关联的类型要求

To fix this error I used associatedtype Root and passed type in function argument

要解决此错误,我使用了associatedtype Root并在函数参数中传递了类型

Protocol can bee consumed like this:

协议可以像这样消耗蜂:

Finally 🎉 ReferenceKeyPathEditable protocol can be conformed by any class to modify property value while keeping property setter private for other types.

最后,任何类都可以使用ReferenceKeyPathEditable协议来修改属性值,同时使属性设置器对其他类型保持私有。

Image for post

Complete source code can be found here

完整的源代码可以在这里找到

具有功能的KeyPath: (KeyPath with Functions:)

  • map()

    地图()

KeyPath with functions can be used when you have a requirement to work with a single property. I mostly like this for high level functions.

当您需要使用单个属性时,可以使用带有函数的KeyPath。 我最喜欢这种高级功能。

Image for post

It helps while reading as well. In a map with closure, our intention is to map user by name property but we specify by value. Although it works but keyPath fits better here as by keyPath we say to map by given path.

它也有助于阅读。 在带闭包的地图中,我们的意图是通过name属性映射用户,但我们通过值进行指定。 尽管它可以工作,但是keyPath在这里更适合,因为我们说要通过给定路径映射keyPath。

  • filter() — keypath can be used with a filter as well

    filter() -键路径也可以与过滤器一起使用

  • sort()

    分类()

Swift standard library doesn’t provide a function to sort by keypath but we can add utility function in extension:

Swift标准库没有提供按键路径排序的函数,但是我们可以在扩展中添加实用程序函数:

Image for post

Complete source code can be find here

完整的源代码可以在这里找到

P.S: It was fun playing with it

PS:玩起来很有趣

For more insights, this article is worth to read

有关更多见解,本文值得一读

https://klundberg.com/blog/swift-4-keypaths-and-you/

https://klundberg.com/blog/swift-4-keypaths-and-you/

Image for post

您可以通过以下方式与我联系: (You can reach out to me at:)

Linkedin: Aaina Jain

Linkedin: Aaina Jain

Twitter: __aainajain

推特: __aainajain

翻译自: https://medium.com/flawless-app-stories/the-story-of-my-experiments-with-swift-keypath-3a55809ffecf

swift keypath

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值