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

    相关文章

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

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

    k8s按需创建PV和使用PVC详解

    《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

    Linux创建服务使用systemctl管理详解

    《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

    idea+spring boot创建项目的搭建全过程

    《idea+springboot创建项目的搭建全过程》SpringBoot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目,:本文主要介绍idea+springb... 目录一.idea四种搭建方式1.Javaidea命名规范2JavaWebTomcat的安装一.明确tomcat

    vue监听属性watch的用法及使用场景详解

    《vue监听属性watch的用法及使用场景详解》watch是vue中常用的监听器,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作,:本文主要介绍vue监听属性watch的用法及使用场景... 目录1. 监听属性 watch2. 常规用法3. 监听对象和route变化4. 使用场景附Watch 的

    Git打标签从本地创建到远端推送的详细流程

    《Git打标签从本地创建到远端推送的详细流程》在软件开发中,Git标签(Tag)是为发布版本、标记里程碑量身定制的“快照锚点”,它能永久记录项目历史中的关键节点,然而,仅创建本地标签往往不够,如何将其... 目录一、标签的两种“形态”二、本地创建与查看1. 打附注标http://www.chinasem.cn

    Python与MySQL实现数据库实时同步的详细步骤

    《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

    Spring创建Bean的八种主要方式详解

    《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

    MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

    《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

    Python如何调用另一个类的方法和属性

    《Python如何调用另一个类的方法和属性》在Python面向对象编程中,类与类之间的交互是非常常见的场景,本文将详细介绍在Python中一个类如何调用另一个类的方法和属性,大家可以根据需要进行选择... 目录一、前言二、基本调用方式通过实例化调用通过类继承调用三、高级调用方式通过组合方式调用通过类方法/静