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

swift keypath

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:

让我们举个例子:

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 where User is type name and String is path name.

屏幕快照中的nameKeyPath语法为,其中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。

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

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

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)

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)

Using update function I can update value of any property.

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

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 —在要将任何类型的键路径存储到数组中时很有用。

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

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

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协议来修改属性值,同时使属性设置器对其他类型保持私有。

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。 我最喜欢这种高级功能。

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标准库没有提供按键路径排序的函数,但是我们可以在扩展中添加实用程序函数:

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/

您可以通过以下方式与我联系: (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

你可能感兴趣的:(python)