WebStorm

[TOC]

本章介绍

一、注册码/破解

注册码获取:

进入http://idea.lanyus.com进行获取。

二、代码格式化

三、WebStorm好用的工具

1、WebStorm文档注释技巧

  • 1、Webstorm设置 -> Live Template -> JavaScript -> 右上角“+

文档注释技巧

  • 2、文档注释技巧2_模板的编辑
1
2
3
4
5
6
7
8
9
10
11
/**
* $FileName$
*
* @Description: $FileDesc$
*
* @author ciyouzen
* @email dvlproad@163.com
* @date $date$ $time$
*
* Copyright (c) dvlproad. All rights reserved.
*/

文档注释技巧2_模板的编辑

①、设置模板内容中的变量定义

文档注释技巧2_模板的编辑2_Edit Variables

②、勾选你选将该模板应用到的编程语言/地方

勾选你选将该模板应用到的编程语言/地方

四、WebStorm快捷键

五、更多好用WebStorm插件推荐

热重载HotReload

[TOC]

通过InjectionIII实现iOS App的Hot Reload

一、设置

https://github.com/krzysztofzablocki/Inject

Individual Developer setup (once per machine)

If anyone in your project wants to use injection, they only need to:

  • You must add “-Xlinker -interposable” (without the double quotes and on separate lines) to the “Other Linker Flags” of all targets in your project for the Debug configuration (qualified by the simulator SDK to avoid complications with bitcode), refer to InjectionForXcode documentation if you run into any issues
  • Download newest version of Xcode Injection from it’s GitHub Page
  • Unpack it and place under /Applications
  • Make sure that the Xcode version you are using to compile our projects is under the default location: /Applications/Xcode.app
  • Run the injection application
  • Select open project / open recent from it’s menu and pick the right workspace file you are using

After choosing the project in Injection app, launch the app

  • If everything is configured correctly you should see similar log in the console:
1
2
3
> 💉 InjectionIII connected /Users/merowing/work/SourceryPro/App.xcworkspace
> 💉 Watching files under /Users/merowing/work/SourceryPro
>

1、项目中设置:

1、Podfile

1
pod 'InjectHotReload'

2、在Xcode – Targets – Build Settings – “Other Linker Flags” 中添加

1
2
-Xlinker
-interposable

3、在项目启动的时候,代码

1
2
3
#if DEBUG
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
#endif

2、设置监听

1、到 https://github.com/johnno1962/InjectionIII 中的 Release 里下载App

2、打开APP,选择要监听的位置(Open Project),并确认 File Watcher 是打开的。

image-20250315000808395

3、运行效果

1、运行项目,岂会打出如下日志

image-20250315002604154

确认Injection connected有没有打印,也就是说有没有真的运行这个工具。

附:

2、执行保存,会有截图中的1效果。

执行修改2处的颜色,3处的文字,发现并没有更新。需要退出重进才能看到修改。

即:

1
2
如果修改的是一个普通页面的内容,最好是退出这个页面,再进入这个页面
如果修改的是cell / item上面的内容,需要上下滚动才能看到效果

image-20250315002204989

End

protobuf的安装

[toc]

protobuf-iOS简单总结(编译、环境搭建)

使⽤Protobuf\ 可以⽐json的数据量⼩⾄少⼀个数量级。

一、Protobuf介绍

新项目打算使用新的序列化数据结构协议,即Protobuf(Google)。之前网络通信和通用数据 交换等应用场景中最常用的就是JSON和XML。Protobuf相较于两者,其效率、兼容性更为出 色。

Protobuf(全称是Protocol Buffers)

定义和描述如下: Protocol Buffers是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用 于(数据)通信协议、数据存储等。(支持 Java、C++、Python 等多种语言,支持多个 平台)

二、安装

检查是否安装成功,执行

1
protoc --version

一、安装流程

https://blog.csdn.net/dalehui/article/details/17593383?utm_medium=distribute.pc_relevant_t0.none-task-blog-searchFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-searchFromBaidu-1.control

1
2
3
4
5
6
7
(1)进入终端 跳转至protobuf文件夹. cd xxxxxxxxxxxxxx(路径)
(2)切换用户身份. sudo su
(3)执行 ./configure
(4)执行 make
(5)执行 make check(可能message.cc会报错,解决办法请看下面)
(6)执行 make install
(7)检查是否安装成功,执行 protoc --version
1
protoc --proto_path=./ --objc_out=./ XXX.proto

image-20201202200227595

三、如何编译protobuf

End

node

[toc]

前言、查看之前是否安装过node

查看之前是否安装过node

1
node -v

常识:

终端执行node -v查看是否安装并配置了其环境变量。如果执行无果,也有可能是安装了,但未配置环境变量。又因为node的安装目录一般是放在 usr/src下。所以,查看命令为

1
2
cd usr/src
ls

如果看到本地有node文件即代表有安装了,只是不一定有配置环境变量

node_install_check

如果没有安装, 则按以下步骤进行安装。

一、node的安装

1、可视化安装node的方法

访问node官网,下载稳定版

image-20201022150722483

安装即可。

2、终端命令安装node的方法(云服务器安装常用的方式)

下面我们以在 CentOS 下源码安装 Node.js 为例

2.1、进入 https://nodejs.org/en/download/ 获取最新的Nodejs版本的下载地址(不建议使用最新的node版本,建议使用V12的)

node_comman_install_1

Nodejs版本的下载注意:不建议使用最新的node版本,建议使用V12的

否则如你使用V14的时候,执行yapi server会出现如下警告提示

image-20210804152703816

出现这样的问题是node版本过高的原因,将版本14降到12便可以解决。首先将原node卸载,然后去官网下载12的版本

拷贝链接,得到 https://nodejs.org/dist/v14.15.1/node-v14.15.1.tar.gz

在终端下载该版本

1
2
cd /usr/local/src/
wget https://nodejs.org/dist/v14.15.1/node-v14.15.1.tar.gz

node_comman_install_2

2.2、解压源码

1
2
3
ls 														# 查看该目录下的文件

tar zxvf node-v14.15.1.tar.gz # 解压制定的压缩包

2.3、编译安装

1
2
3
4
cd node-v14.15.1
./configure --prefix=/usr/local/node/14.15.1
make
make install

node_comman_install3

虽然看似成功了,但其实有警告。

1
2
WARNING: failed to autodetect C++ compiler version (CXX=g++)
WARNING: warnings were emitted in the configure phase

需要解决该警告,如果不解决就继续执行make命令,则会发生失败,失败截图如下:

node_comman_install_3_2

所以,我们先需要安装gcc,安装gcc成功后,重新执行./configure --prefix=/usr/local/node/14.15.1确保命令成功,且无警告。才能保证后续的make等命令才能跟着成功。

安装gcc的命令如下

1
yum -y install gcc gcc-c++ kernel-devel //安装gcc、c++编译器以及内核文件

node_comman_install_3_gcc

重新执行./configure --prefix=/usr/local/node/14.15.1命令,警告解除了

node_comman_install_3_success

然后,我们继续剩余的还没执行的命令

1
2
make
make install

执行make成功的截图如下:(我表示在阿里云CentOS系统上,从早上10点多,执行到下午三点多才执行结束。好坑啊。。。。)

node_comman_install_4

make install的执行就很快了,几秒钟中结束。OK!

2.4、 配置NODE_HOME,进入profile编辑环境变量

1
vim /etc/profile

该文件内容初始如下截图:

node_comman_install_6

输入字母i,进行插入模式,来设置 nodejs 环境变量,即在 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 一行的上面添加如下内容:

1
2
3
#set for nodejs
export NODE_HOME=/usr/local/node/14.15.1
export PATH=$NODE_HOME/bin:$PATH

node_comman_install_6_2

插入完成后,按ESC,然后输入:wq进行保存并退出。然后执行以下命令来编译/etc/profile 从而使刚才的环境变量配置生效

1
source /etc/profile

node_comman_install_7

验证是否安装配置成功

1
node -v

输出 v14.15.1 表示配置成功

npm模块安装路径

1
/usr/local/node/14.15.1/lib/node_modules/

至此,命令安装nodejs结束。

注:Nodejs 官网提供了编译好的 Linux 二进制包,你也可以下载下来直接应用。

二、node指定版本的安装、切换、删除

有时候你之前安装的node版本可能太高,导致在执行某些命令的时候识别不到,那时候,你可能需要切换下node版本。切换node版本的方法如下:

1、先利用工具n安装指定的node版本,再进行切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看当前使用的node的版本
node -v

# 查看npm的版本
npm -v

# 安装指定的node版本
npm install -g n # 利用npm安装工具n,之后再用n来安装指定的node版本

# 安装指定版本(最好用),版本v自定义
sudo n v12.19.0 # 利用工具n来安装node指定的12.19.0的版本

# 删除已经安装的版本
sudo n rm 14.19.0

image-20201118141002543

2、进行node的版本的切换(不一定能够立即生效)

1
2
# 输入命令n进入node的版本切换界面
n

image-20201118141135112

通过上下选择,选定指定的node版本,或者按q退出。

我们选定12.19.0的版本回车后,退出执行node -v查看当前的node版本,发现还是之前的版本。所以我们应该还要再执行一步生效操作。

image-20201118141320375

3、添加环境变量,使得上述进行的node版本切换能够生效

1
2
3
4
5
6
7
8
export NODE_HOME=/usr/local
export PATH=$NODE_HOME/bin:$PATH
export NODE_PATH=$NODE_HOME/lib/node_modules:$PATH

source ~/.bash_profile # MacOS的环境变量文件
source /etc/profile # 云服务器的环境变量文件

node -v

image-20201118141513712

为避免每次都得终端执行export命令,建议 vim ~/.bash_profile

三、其他

sudo cnpm install -g n

image-20190517182929169

sudo n stable

image-20190517183108288

二、npm执行警告⚠️处理

1、npm 解决缺失 core-js 的问题

1
core-js@1.2.7: core-js@<2.6.5 is no longer maintained. Please, upgrade to core-js@3 or at least to actual version of core-js@2.

image-20190520002140149

解决办法:使用 npm 或者 cnpm 执行以下命令
npm install core-js@3

2、npm 解决缺失 react-dom 的问题

1
antd@3.18.1 requires a peer of react-dom@>=16.0.0 but none is installed. You must install peer dependencies yourself.

image-20190520003332237

3、npm 解决缺失 react 的问题

1
npm WARN react-native@0.59.8 requires a peer of react@16.8.3 but none is installed. You must install peer dependencies yourself.

数学

三维空间中向量的旋转

问题

在三维空间中,计算一个向量 v v v(或点 v v v)绕另一个向量 u u u旋转 θ \theta θ角后的坐标。

方法

罗德里格旋转公式(Rodrigues’ Rotation Formula):
v ′ = v c o s θ + u × v s i n θ + ( u ⋅ v ) u ( 1 − c o s θ ) v’ = v cos \theta + u \times v sin \theta + (u \cdot v) u ( 1 - cos \theta)
v

=vcosθ+u×vsinθ+(u⋅v)u(1−cosθ)

公式推导可见 旋转之二 - 三维空间中的旋转:罗德里格旋转公式

数学

sin, cos都是三角函数,分别叫做“正弦”、“余弦”、“正切”。

在初中阶段,这三个三角函数是这样解释的:

在一个直角三角形中,设∠C=90°,∠A, B, C 所对的边分别记作 a,b,c,那么对于锐角∠A,它的对边 a 和斜边 c 的比值 a/c 叫做∠A的正弦,记作 sinA;它的邻直角边 b 和斜边 c 的比值 b/c 叫做∠A的余弦,记作 cosA;它的对边 a 和邻直角边 b 的比值 a/b 叫做∠A的正切,记作 tanA。

在高中阶段,这三个三角函数是这样解释的:

在一个平面直角坐标系中,以原点为圆心,1 为半径画一个圆,这个圆交 x 轴于 A 点。以 O 为旋转中心,将 A 点逆时针旋转一定的角度α至 B 点,设此时 B 点的坐标是(x,y),那么此时 y 的值就叫做α的正弦,记作 sinα;此时 x 的值就叫做α的余弦,记作 cosα;y 与 x 的比值 y/x 就叫做α的正切,记作 tanα。

img

asin,acos,atan应该是Matlab里的函数(程序),数学中分别被记为(也是规范的记法) arcsin, arccos,arctan, 分别是sin,cos,tan 的限制在 [-pi/2,pi/2], [0, pi], (-pi/2, pi/2) 的反函数(函数的逆)。(三角函数本身是没有反函数的)

开发随笔

iOS开发常用之图像浏览及处理:https://cloud.tencent.com/developer/article/1372590

在swiftui中的View,需要根据其下的一个isToggled: Bool 属性更新界面,不能用@ObservedObject ,那怎么修饰该属性,

在 SwiftUI 中,如果你需要根据一个 Bool 类型的属性更新界面,但又不能使用 @ObservedObject (可能是因为这个属性是局部变量,或者它不是 ObservableObject 的属性),你可以使用 @State 或 @Binding 属性包装器来实现。使用 @State @State 是一个属性包装器,用于定义一个私有的状态变量,这个变量的值改变时,视图会自动更新。它适用于定义在视图或视图模型内部的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import SwiftUI

struct MyView: View {
@State private var isToggled: Bool = false

var body: some View {
Toggle("Toggle", isOn: $isToggled)
if isToggled {
Text("Toggle is on")
} else {
Text("Toggle is off")
}
}
}

在这个例子中, isToggled 是一个 @State 变量,当它被修改时(如通过 Toggle 控件),视图会自动更新。使用 @Binding 如果你需要在多个视图之间共享状态,或者状态定义在父视图中,你可以使用 @Binding 。 @Binding 允许你创建一个指向父视图中 @State 或 @ObservableObject 属性的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import SwiftUI

struct ParentView: View {
@State private var isToggled: Bool = false

var body: some View {
MyView(isToggled: $isToggled)
}
}

struct MyView: View {
@Binding var isToggled: Bool

var body: some View {
Toggle("Toggle", isOn: $isToggled)
if isToggled {
Text("Toggle is on")
} else {
Text("Toggle is off")
}
}
}

在这个例子中, ParentView 定义了一个 @State 变量 isToggled ,并将其通过 @Binding 传递给 MyView 。这样,当 MyView 中的 Toggle 控件改变 isToggled 的值时, ParentView 中的 isToggled 也会更新,从而导致视图的更新。这两种方法都可以让你根据 Bool 类型的属性更新 SwiftUI 视图,而不需要使用 @ObservedObject 。选择哪种方法取决于你的具体需求,比如状态是否需要在多个视图间共享,或者状态是否需要持久化。

请使用swift,自定义一个视图,当外部的shouldUpdateUI变化的时候,该视图更新

在SwiftUI中,如果你想要创建一个自定义视图,该视图可以根据外部的 shouldUpdateUI 布尔值的变化来更新,你可以使用 @Binding 来实现这个功能。下面是一个简单的自定义视图示例,它接受一个 @Binding 参数,并根据这个参数的值来决定是否显示某些内容或更新UI。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import SwiftUI

// 自定义视图
struct UpdateableView: View {
@Binding var shouldUpdateUI: Bool

var body: some View {
VStack {
if shouldUpdateUI {
Text("UI is being updated!")
.foregroundColor(.blue)
} else {
Text("UI is up to date.")
.foregroundColor(.green)
}
}
.onAppear {
// 可以在视图出现时执行某些操作
print("View appears. Should update UI? $shouldUpdateUI)")
}
.onChange(of: shouldUpdateUI) { newValue in
// 当 shouldUpdateUI 发生变化时执行某些操作
print("shouldUpdateUI changed to $newValue)")
}
}
}

// 使用自定义视图的示例
struct ContentView: View {
@State private var shouldUpdateUI = false

var body: some View {
VStack {
Toggle("Toggle UI Update", isOn: $shouldUpdateUI)
UpdateableView(shouldUpdateUI: $shouldUpdateUI)
}
}
}

@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

在这个例子中:

• UpdateableView 是一个自定义视图,它接受一个 @Binding var shouldUpdateUI: Bool 参数。这个参数允许 UpdateableView 监听 shouldUpdateUI 值的变化,并根据这个值来更新其显示的内容。

• 在 UpdateableView 中,使用了一个 VStack 来包含一些文本视图。根据 shouldUpdateUI 的值,显示不同的文本。

• .onAppear 修饰符用于在视图出现时打印一条消息,表明视图已经出现,并显示当前 shouldUpdateUI 的状态。• .onChange(of:) 修饰符用于监听 shouldUpdateUI 值的变化,并在变化时打印一条消息。• ContentView 是一个包含 Toggle 和 UpdateableView 的视图。 Toggle 允许用户切换 shouldUpdateUI 的值,从而触发 UpdateableView 的更新。这个示例展示了如何创建一个可以根据外部状态变化来更新的自定义视图。你可以根据需要调整 UpdateableView 中的UI和逻辑。

通过这种方式 在ContentView使用 UpdateableView,需要写成 UpdateableView(shouldUpdateUI: $shouldUpdateUI),有没有其他方式 uiUpdateObserver

如果你想要避免在 ContentView 中使用 UpdateableView(shouldUpdateUI: $shouldUpdateUI) 这样的写法,可以考虑以下几种替代方案:1. 使用 @EnvironmentObject 或 @ObservedObject 你可以将 shouldUpdateUI 的状态提升到一个更高的层级,比如使用 @EnvironmentObject 或 @ObservedObject ,这样 UpdateableView 就可以直接访问这个状态,而不需要通过参数传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import SwiftUI

class EnvironmentModel: ObservableObject {
@Published var shouldUpdateUI: Bool = false
}

struct UpdateableView: View {
@EnvironmentObject var environmentModel: EnvironmentModel

var body: some View {
VStack {
if environmentModel.shouldUpdateUI {
Text("UI is being updated!")
.foregroundColor(.blue)
} else {
Text("UI is up to date.")
.foregroundColor(.green)
}
}
}
}

struct ContentView: View {
@StateObject var environmentModel = EnvironmentModel()

var body: some View {
UpdateableView()
.environmentObject(environmentModel)
}
}

@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

在这个例子中, EnvironmentModel 是一个包含 shouldUpdateUI 状态的 ObservableObject 。 UpdateableView 通过 @EnvironmentObject 直接访问这个状态,而不需要通过参数传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import SwiftUI

class UIUpdateModel: ObservableObject {
@Published var shouldUpdateUI: Bool = false
}


struct ContentView: View {
//@ObservedObject var model: UIUpdateModel /// 方法1:
@EnvironmentObject var model: UIUpdateModel /// 方法2:

var body: some View {
Text("Should Update UI: $model.shouldUpdateUI)")
}
}

使用swiftui, 在一个视图A中,有一个dateModel的属性对象。且视图A中有子视图B,希望只接收dateModel的date属性。视图A中还有另一个子视图C,点击子视图C会更新dateModel的date值为当前时间,现在希望视图B也能够更新。我的要求是DateModel 不继承ObservableObject, 其属性也都不能用@Published修饰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class DateModel {
var date: Date = Date()
}

struct ContentView: View {
@EnvironmentObject var dateModel: DateModel
@State private var date: Date? // 可选类型,无需初始值

var body: some View {
VStack {
Text("主视图 A").font(.headline)
if let date = date {
SubViewB(date: Binding(get: { date }, set: { self.date = $0 }))
} else {
Text("日期尚未加载")
}
SubViewC(dateModel: dateModel) {
self.date = dateModel.date
}
}
.onAppear {
self.date = dateModel.date // 初始化时同步值
}
.padding()
}
}

这时候如果要将ContentView作为SuperContainer的子视图怎么办,要求在 SuperContainer中使用ContentView的时候不用传入参数。如何 让ContentView 中的 @State private var date: Date 可以不提供默认值吗

在 SwiftUI 中,@State 属性通常需要一个初始值,因为它是用来管理视图状态的本地存储。SwiftUI 需要在视图的生命周期中始终能访问到一个有效的值。如果不提供默认值,编译器会报错。

替代方法

1
2
// 方法1:
@State private var date: Date? // 可选类型,无需初始值

如果您确实希望在 ContentView 中的 date 初始化时无需默认值,可以考虑以下方法:

子视图需要父视图中模型中的一个属性来更新界面

子视图 B 接收 @Binding 的 date,只负责显示,不直接修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct SubViewB: View {
@Binding var date: Date

var body: some View {
Text("当前日期: \(date, formatter: dateFormatter)")
.padding()
.background(Color.yellow.opacity(0.3))
.cornerRadius(10)
}
}

private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter
}()


struct SubViewC: View {
var dateModel: DateModel
var onUpdate: () -> Void // 回调通知主视图

var body: some View {
Button(action: {
dateModel.date = Date() // 更新模型
onUpdate() // 通知主视图更新
}) {
Text("更新日期到当前时间")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}

方法1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

struct ContentView: View {
@EnvironmentObject var dateModel: DateModel
@State private var date: Date? // 可选类型,无需初始值

var body: some View {
VStack {
Text("主视图 A").font(.headline)
if let date = date {
SubViewB(date: Binding(get: { date }, set: { self.date = $0 }))
}
SubViewC(dateModel: dateModel) {
self.date = dateModel.date
}
}
.onAppear {
self.date = dateModel.date // 初始化时同步值
}
.padding()
}
}


// 优化:可以省去额外多开辟了一个 date 变量。
struct ContentView: View {
@EnvironmentObject var dateModel: DateModel
@EnvironmentObject var dateSettingViewUpdateObserver: UIUpdateModel

var body: some View {
VStack {
Text("主视图 A").font(.headline)

SubViewB(date: Binding(get: { dateModel.date }, set: { dateModel.date = $0 })) // 1、保证视图触发更新时候使用到新数据
.environmentObject(uiUpdateObserver) // 2、保证能触发视图更新

SubViewC(dateModel: dateModel) {
dateModel.date = Date() // 在这里更新日期


}
}
.padding()
}
}

func updateUI() {
dateModel.date = dateModel.date.addingTime(hours: 24)

//shouldUpdateUI.toggle()
uiUpdateObserver.updateListeners()
}

// 此时C的操作不会引起B的变化,需要额外处理
struct SubViewC: View {
//@Binding var shouldUpdateUI: Bool
@EnvironmentObject var uiUpdateObserver: UIUpdateModel

var dateModel: DateModel
var onUpdate: () -> Void // 回调通知主视图

var body: some View {
Button(action: {
dateModel.date = Date() // 更新模型
onUpdate() // 通知主视图更新
}) {
Text("更新日期到当前时间")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}

class UIUpdateModel: ObservableObject {
@Published var shouldUpdate: Bool = false

func updateListeners() {
shouldUpdate.toggle()
}
}