ajax同步属性_创建一个同步的UserDefaults属性包装器

2023-10-17 14:10

本文主要是介绍ajax同步属性_创建一个同步的UserDefaults属性包装器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ajax同步属性

Since the birth of Swift’s property wrappers, I have seen numerous articles discussing how to create a wrapped variable that can persist itself to the UserDefaults sector. While many of the code examples suffice for the simplest case, I’ve still had some questions gnawing at the back of my head.

自Swift的属性包装器诞生以来,我已经看过许多文章,讨论如何创建一个包装的变量,该变量可以持久保存到UserDefaults部门。 尽管许多代码示例足以满足最简单的情况,但我仍然有些疑问仍然困扰着我。

  • If several of these instances would ever need to be alive at the same time, how will they synchronize?

    如果其中几个实例需要同时处于活动状态,它们将如何同步?
  • How do they synchronize if another process accesses the UserDefaults file, perhaps directly through the file system?

    如果另一个进程(可能直接通过文件系统)访问UserDefaults文件,它们如何同步?

In this article, we look at how to make a property wrapper that persists your variables in UserDefaults. They also stay on top of any value changes, regardless of where they originate.

在本文中,我们将研究如何制作一个属性包装器,以将变量保留在UserDefaults中。 无论它们来自何处,它们也始终处于任何价值变化之上。

分析一个简单的实现 (Analyzing a Simple Implementation)

Let’s take a look at a simple implementation of a property wrapper for persisting values in UserDefaults, to get a sense of what it does well and where it fails. We then use these realizations to build a wrapper that handles synchronization like a charm.

让我们看一下用于在UserDefaults中持久保存值的属性包装器的简单实现,以了解它的作用和失败之处。 然后,我们使用这些实现来构建一个包装,该包装像魅力一样处理同步。

The above is the most straightforward wrapper I’ve seen so far. It does not attempt to cache the currently persisted value; it merely relies on the caching mechanisms of UserDefaults. This solution is not terrible if that’s all you need. However, it becomes a headache as soon as you want to be able to reactively propagate changes out to, for example, a UI.

上面是到目前为止我所见过的最简单的包装器。 它不会尝试缓存当前持久化的值。 它仅依赖于UserDefaults的缓存机制。 如果这就是您所需要的,那么此解决方案并不可怕。 但是,一旦您希望能够以响应方式将更改传播到例如UI上,就会变得很头疼。

进行改进 (Making Our Improvements)

To be able to publish any changes made, we need to cache the value inside of our object. We can then listen to the notifications that UserDefault sends through NotificationCenter, and update our cached value whenever we receive one of those. This approach alleviates the problem of synchronization between multiple wrapper instances since each of them triggers a notification when they set a new value. It does, however, require us to switch from writing a struct to writing a class, since NotificationCenter can only register reference type objects.

为了能够发布所做的任何更改,我们需要将值缓存在对象内部。 然后,我们可以侦听UserDefault通过NotificationCenter发送的通知,并在收到其中之一时更新我们的缓存值。 这种方法减轻了多个包装器实例之间的同步问题,因为每个包装器实例在设置新值时都会触发通知。 但是,这确实需要我们从编写结构切换为编写类,因为NotificationCenter只能注册引用类型对象。

As we can see in the above implementation, we change a few things so that the object makes use of the cached value property. We also conform to the ObservableObject protocol and make use of Combine’s Published construct to let others react to any changes.

正如我们在上述实现中所看到的,我们做了一些更改,以便对象利用缓存的value属性。 我们还遵守ObservableObject协议,并利用Combine的Published结构让其他人对任何更改做出React。

The real improvement here is that the wrapper has a chance to react to any changes made through an instance of UserDefaults. Since all other wrapper objects go through UserDefaults, they are covered too.

真正的改进是包装器有机会对通过UserDefaults实例进行的任何更改做出React。 由于所有其他包装对象都通过UserDefaults,因此它们也被覆盖。

Does this mean that we are safe?Unfortunately not.

这是否意味着我们安全?

照顾意外地方的变化 (Taking Care of Changes From Unexpected Places)

What would happen if someone set a new value for our key from another process? Or updates the default values by writing straight to the property list file that holds them? With this implementation, we don’t have a way of handling that. It looks like we’ve spotted a potential improvement!

如果有人在另一个过程中为我们的密钥设置了新的值,将会发生什么? 还是直接写入保存默认值的属性列表文件来更新默认值? 使用此实现,我们没有一种处理方法。 看来我们已经发现了潜在的改进!

The UserDefaults property list is the least common denominator that may cause our wrappers or the UserDefaults instance to go out-of-sync. This file is a classic key-value list that can be read and written to, just like any other. To pick up on changes that originate from strange places, we need to monitor that list and react to any write operations that occur. To do that, we are going to engineer a FileWriteMonitor.

UserDefaults属性列表是最小公分母,它可能导致我们的包装器或UserDefaults实例不同步。 该文件是一个经典的键值列表,可以像其他任何文件一样被读取和写入。 要获取来自陌生地方的更改,我们需要监视该列表并对发生的所有写操作做出React。 为此,我们将设计一个FileWriteMonitor

There are probably many things going on in this piece of code that some may not have seen before. The FileWriteMonitor keeps a DispatchSourceFileSystemObject instance. That is a long word to describe an object that lets us observe events in a file descriptor.

在这段代码中可能发生了许多以前可能未曾看到的事情。 FileWriteMonitor保留一个DispatchSourceFileSystemObject实例。 这是一个很长的字眼,用来描述一个对象,它使我们可以观察文件描述符中的事件。

Speaking of which, our monitor also keeps track of a file descriptor. A file descriptor is a POSIX construct that allows us to get an abstract handle to access a file. It is this beauty, together with the DispatchSourceFileSystemObject, that is going to make magic for us.

说到这一点,我们的监视器还跟踪文件描述符。 文件描述符是POSIX构造,它使我们能够获取访问文件的抽象句柄。 正是这种美感与DispatchSourceFileSystemObject一起为我们带来了魔力。

Focus your attention on the .connectDispatchSource method. If we have obtained a file descriptor and created an event source before, we cancel and close them. These actions make sure we don’t leave a lot of loose ends hanging around.

将注意力集中在.connectDispatchSource方法上。 如果之前已经获得文件描述符并创建了事件源,则取消并关闭它们。 这些动作确保了我们不会留下很多松散的末端。

Once that is done, we obtain a new file descriptor for the file we are interested in. In our case, this is the UserDefaults property list file. From the descriptor, we create a new event source that will observe and propagate write and delete operations to us. In the event handler, we check for the event that triggered our handler. We reconnect our event source to a new file descriptor if we observe a delete event. If the event source passes us a write event, we call the onWrite closure that we got in the initializer.

一旦完成,我们将为感兴趣的文件获取一个新的文件描述符。在我们的例子中,这是UserDefaults属性列表文件。 从描述符中,我们创建一个新的事件源,它将观察并向我们传播写入和删除操作。 在事件处理程序中,我们检查触发了处理程序的事件。 如果观察到delete事件,我们会将事件源重新连接到新的文件描述符。 如果事件源向我们传递了一个写事件,我们将调用初始化程序中获得的onWrite闭包。

Now, let’s take this thing for a spin. Let’s see how we can use it to complete our property wrapper.

现在,让我们旋转一下。 让我们看看如何使用它来完成我们的属性包装器。

Pay special attention to the initializer in this piece of code. We first obtain a URL for the UserDefaults list, which we pass into our FileWriteMonitor together with a closure. That closure calls an update method which reads out the new value from the file and caches it. You may also notice that it passes the new value to UserDefaults, which allows it to update its cache and send a notification to the other property wrappers that may want to update their caches as well.

在这段代码中要特别注意初始化程序。 我们首先获取UserDefaults列表的URL,并将其与闭包一起传递到FileWriteMonitor 。 该闭包调用一个update方法,该方法从文件中读取新值并将其缓存。 您可能还会注意到,它将新值传递给UserDefaults,这使它可以更新其缓存并将通知发送给可能也要更新其缓存的其他属性包装器。

Image for post
Our final property wrapper at play!
我们最后的属性包装器正在发挥作用!

更多灵感 (More Inspiration)

In case you are interested to learn more, I post a fair share of articles. Feel free to follow me to get an update when there’s something new to read!

如果您有兴趣了解更多信息,我会发布很多文章。 有新内容要阅读时,请随时关注我以获取更新!

Until next time, you may be interested in reading about how to perform Monte Carlo simulations on a mobile device, or how to program in a protocol-oriented fashion. Below are links to those articles!

在下一次之前,您可能有兴趣阅读有关如何在移动设备上执行蒙特卡洛模拟或如何以面向协议的方式进行编程的信息。 以下是这些文章的链接!

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/swlh/creating-a-synchronized-userdefaults-property-wrapper-b2d9629b0aae

ajax同步属性


http://www.taodudu.cc/news/show-7979671.html

相关文章:

  • 区块链论文6(teether检测智能合约漏洞并自动生成漏洞路径)
  • 根据各工序时间画aoe网_干货 | 你知道建筑主体施工工序吗?(附:超详细流程图)...
  • 毛坯房装修顺序是怎样的 装修注意事项
  • Neo4j 桌面版的使用教程
  • 7.3.2 用管道匹配多个分组
  • C++内存管理及内存问题的分析
  • apt和dpkg包管理器
  • 内核态下基于动态感染技术的应用程序执行保护(五 动态感染)
  • 李彦宏的“罪己诏
  • 剪枝论文三( Sparse Structure Selection)
  • Transformer论文解读二(Vision Transformer)
  • 语义分割论文解读三(HRNetv1, HRNetv2)
  • 网络参数重组论文四(Diverse Branch Block)
  • 剪枝论文五(Connection pruning)
  • 网络参数重组论文二(ACNet,RepMLP)
  • 蒸馏论文十(Structured Knowledge Distillation for Dense Prediction)
  • 蒸馏论文四(Relational Knowledge Distillation)
  • Transformer论文解读三(distillation token)
  • 目标检测论文解读四(检测蒸馏论文三篇)
  • 蒸馏论文一(knowledge distillation)
  • Transformer论文解读五(Swin Transformer)
  • 网络参数重组论文一(RepVGG)
  • 目标检测论文解读五(YOLOF)
  • Transformer论文解读四(SegFormer)
  • 蒸馏论文二(Attention Transfer)
  • 网络参数重组经典论文
  • 语义分割经典论文详解
  • 剪枝论文四(ThiNet)
  • 蒸馏论文八(分类蒸馏论文八篇)
  • 知识蒸馏经典论文详解
  • 这篇关于ajax同步属性_创建一个同步的UserDefaults属性包装器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/225921

    相关文章

    C#高效实现在Word文档中自动化创建图表的可视化方案

    《C#高效实现在Word文档中自动化创建图表的可视化方案》本文将深入探讨如何利用C#,结合一款功能强大的第三方库,实现在Word文档中自动化创建图表,为你的数据呈现和报告生成提供一套实用且高效的解决方... 目录Word文档图表自动化:为什么选择C#?从零开始:C#实现Word文档图表的基本步骤深度优化:C

    Python列表的创建与删除的操作指南

    《Python列表的创建与删除的操作指南》列表(list)是Python中最常用、最灵活的内置数据结构之一,它支持动态扩容、混合类型、嵌套结构,几乎无处不在,但你真的会创建和删除列表吗,本文给大家介绍... 目录一、前言二、列表的创建方式1. 字面量语法(最常用)2. 使用list()构造器3. 列表推导式

    HTML5的input标签的`type`属性值详解和代码示例

    《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

    input的accept属性让文件上传安全高效

    《input的accept属性让文件上传安全高效》文章介绍了HTML的input文件上传`accept`属性在文件上传校验中的重要性和优势,通过使用`accept`属性,可以减少前端JavaScrip... 目录前言那个悄悄毁掉你上传体验的“常见写法”改变一切的 html 小特性:accept真正的魔法:让

    C#借助Spire.XLS for .NET实现在Excel中添加文档属性

    《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

    JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

    《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

    Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

    《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

    C++11中的包装器实战案例

    《C++11中的包装器实战案例》本文给大家介绍C++11中的包装器实战案例,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录引言1.std::function1.1.什么是std::function1.2.核心用法1.2.1.包装普通函数1.2.

    java创建xls文件放到指定文件夹中实现方式

    《java创建xls文件放到指定文件夹中实现方式》本文介绍了如何在Java中使用ApachePOI库创建和操作Excel文件,重点是如何创建一个XLS文件并将其放置到指定文件夹中... 目录Java创建XLS文件并放到指定文件夹中步骤一:引入依赖步骤二:创建XLS文件总结Java创建XLS文件并放到指定文件

    Java 虚拟线程的创建与使用深度解析

    《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三