react-native-mmkv 2.1.2 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MMKV/CHANGELOG.md +14 -0
- package/MMKV/Core/Core.xcodeproj/project.pbxproj +1 -1
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +1 -1
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +1 -1
- package/MMKV/Core/MMKV.cpp +70 -7
- package/MMKV/Core/MMKV.h +9 -7
- package/MMKV/Core/MMKVPredef.h +1 -1
- package/MMKV/README.md +19 -19
- package/README.md +6 -2
- package/android/src/main/cpp/MmkvHostObject.cpp +79 -56
- package/ios/JSIUtils.mm +24 -25
- package/ios/MmkvHostObject.mm +48 -17
- package/ios/MmkvModule.mm +4 -1
- package/lib/commonjs/MMKV.js.map +1 -1
- package/lib/commonjs/createMMKV.web.js +6 -6
- package/lib/commonjs/createMMKV.web.js.map +1 -1
- package/lib/commonjs/hooks.js +9 -4
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/module/MMKV.js.map +1 -1
- package/lib/module/createMMKV.web.js +6 -6
- package/lib/module/createMMKV.web.js.map +1 -1
- package/lib/module/hooks.js +9 -4
- package/lib/module/hooks.js.map +1 -1
- package/lib/typescript/MMKV.d.ts +9 -9
- package/lib/typescript/hooks.d.ts +11 -4
- package/package.json +1 -1
- package/react-native-mmkv.podspec +1 -1
package/MMKV/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# MMKV Change Log
|
|
2
2
|
|
|
3
|
+
## v1.2.13 / 2022-03-30
|
|
4
|
+
|
|
5
|
+
### Android
|
|
6
|
+
* Fix crash on using Ashmem while `MMKV_DISABLE_CRYPT` macro is defined.
|
|
7
|
+
|
|
8
|
+
### iOS
|
|
9
|
+
* Add ability to retrieve key existece while getting value, aka `-[MMKV getXXX:forKey:hasValue:]` methods.
|
|
10
|
+
|
|
11
|
+
### POSIX
|
|
12
|
+
* Add ability to retrieve key existece while getting value, aka `MMKV::getXXX(key, defaultValue, hasValue)` methods.
|
|
13
|
+
|
|
14
|
+
### Win32
|
|
15
|
+
* Add ability to retrieve key existece while getting value, aka `MMKV::getXXX(key, defaultValue, hasValue)` methods.
|
|
16
|
+
|
|
3
17
|
## v1.2.12 / 2022-01-17
|
|
4
18
|
### Changes for All platforms
|
|
5
19
|
* Fix a bug that a subsequential `clearAll()` call may fail to take effect in multi-process mode.
|
package/MMKV/Core/MMKV.cpp
CHANGED
|
@@ -607,8 +607,11 @@ bool MMKV::getVector(MMKVKey_t key, vector<string> &result) {
|
|
|
607
607
|
|
|
608
608
|
#endif // MMKV_APPLE
|
|
609
609
|
|
|
610
|
-
bool MMKV::getBool(MMKVKey_t key, bool defaultValue) {
|
|
610
|
+
bool MMKV::getBool(MMKVKey_t key, bool defaultValue, bool *hasValue) {
|
|
611
611
|
if (isKeyEmpty(key)) {
|
|
612
|
+
if (hasValue != nullptr) {
|
|
613
|
+
*hasValue = false;
|
|
614
|
+
}
|
|
612
615
|
return defaultValue;
|
|
613
616
|
}
|
|
614
617
|
SCOPED_LOCK(m_lock);
|
|
@@ -616,16 +619,25 @@ bool MMKV::getBool(MMKVKey_t key, bool defaultValue) {
|
|
|
616
619
|
if (data.length() > 0) {
|
|
617
620
|
try {
|
|
618
621
|
CodedInputData input(data.getPtr(), data.length());
|
|
622
|
+
if (hasValue != nullptr) {
|
|
623
|
+
*hasValue = true;
|
|
624
|
+
}
|
|
619
625
|
return input.readBool();
|
|
620
626
|
} catch (std::exception &exception) {
|
|
621
627
|
MMKVError("%s", exception.what());
|
|
622
628
|
}
|
|
623
629
|
}
|
|
630
|
+
if (hasValue != nullptr) {
|
|
631
|
+
*hasValue = false;
|
|
632
|
+
}
|
|
624
633
|
return defaultValue;
|
|
625
634
|
}
|
|
626
635
|
|
|
627
|
-
int32_t MMKV::getInt32(MMKVKey_t key, int32_t defaultValue) {
|
|
636
|
+
int32_t MMKV::getInt32(MMKVKey_t key, int32_t defaultValue, bool *hasValue) {
|
|
628
637
|
if (isKeyEmpty(key)) {
|
|
638
|
+
if (hasValue != nullptr) {
|
|
639
|
+
*hasValue = false;
|
|
640
|
+
}
|
|
629
641
|
return defaultValue;
|
|
630
642
|
}
|
|
631
643
|
SCOPED_LOCK(m_lock);
|
|
@@ -633,16 +645,25 @@ int32_t MMKV::getInt32(MMKVKey_t key, int32_t defaultValue) {
|
|
|
633
645
|
if (data.length() > 0) {
|
|
634
646
|
try {
|
|
635
647
|
CodedInputData input(data.getPtr(), data.length());
|
|
648
|
+
if (hasValue != nullptr) {
|
|
649
|
+
*hasValue = true;
|
|
650
|
+
}
|
|
636
651
|
return input.readInt32();
|
|
637
652
|
} catch (std::exception &exception) {
|
|
638
653
|
MMKVError("%s", exception.what());
|
|
639
654
|
}
|
|
640
655
|
}
|
|
656
|
+
if (hasValue != nullptr) {
|
|
657
|
+
*hasValue = false;
|
|
658
|
+
}
|
|
641
659
|
return defaultValue;
|
|
642
660
|
}
|
|
643
661
|
|
|
644
|
-
uint32_t MMKV::getUInt32(MMKVKey_t key, uint32_t defaultValue) {
|
|
662
|
+
uint32_t MMKV::getUInt32(MMKVKey_t key, uint32_t defaultValue, bool *hasValue) {
|
|
645
663
|
if (isKeyEmpty(key)) {
|
|
664
|
+
if (hasValue != nullptr) {
|
|
665
|
+
*hasValue = false;
|
|
666
|
+
}
|
|
646
667
|
return defaultValue;
|
|
647
668
|
}
|
|
648
669
|
SCOPED_LOCK(m_lock);
|
|
@@ -650,16 +671,25 @@ uint32_t MMKV::getUInt32(MMKVKey_t key, uint32_t defaultValue) {
|
|
|
650
671
|
if (data.length() > 0) {
|
|
651
672
|
try {
|
|
652
673
|
CodedInputData input(data.getPtr(), data.length());
|
|
674
|
+
if (hasValue != nullptr) {
|
|
675
|
+
*hasValue = true;
|
|
676
|
+
}
|
|
653
677
|
return input.readUInt32();
|
|
654
678
|
} catch (std::exception &exception) {
|
|
655
679
|
MMKVError("%s", exception.what());
|
|
656
680
|
}
|
|
657
681
|
}
|
|
682
|
+
if (hasValue != nullptr) {
|
|
683
|
+
*hasValue = false;
|
|
684
|
+
}
|
|
658
685
|
return defaultValue;
|
|
659
686
|
}
|
|
660
687
|
|
|
661
|
-
int64_t MMKV::getInt64(MMKVKey_t key, int64_t defaultValue) {
|
|
688
|
+
int64_t MMKV::getInt64(MMKVKey_t key, int64_t defaultValue, bool *hasValue) {
|
|
662
689
|
if (isKeyEmpty(key)) {
|
|
690
|
+
if (hasValue != nullptr) {
|
|
691
|
+
*hasValue = false;
|
|
692
|
+
}
|
|
663
693
|
return defaultValue;
|
|
664
694
|
}
|
|
665
695
|
SCOPED_LOCK(m_lock);
|
|
@@ -667,16 +697,25 @@ int64_t MMKV::getInt64(MMKVKey_t key, int64_t defaultValue) {
|
|
|
667
697
|
if (data.length() > 0) {
|
|
668
698
|
try {
|
|
669
699
|
CodedInputData input(data.getPtr(), data.length());
|
|
700
|
+
if (hasValue != nullptr) {
|
|
701
|
+
*hasValue = true;
|
|
702
|
+
}
|
|
670
703
|
return input.readInt64();
|
|
671
704
|
} catch (std::exception &exception) {
|
|
672
705
|
MMKVError("%s", exception.what());
|
|
673
706
|
}
|
|
674
707
|
}
|
|
708
|
+
if (hasValue != nullptr) {
|
|
709
|
+
*hasValue = false;
|
|
710
|
+
}
|
|
675
711
|
return defaultValue;
|
|
676
712
|
}
|
|
677
713
|
|
|
678
|
-
uint64_t MMKV::getUInt64(MMKVKey_t key, uint64_t defaultValue) {
|
|
714
|
+
uint64_t MMKV::getUInt64(MMKVKey_t key, uint64_t defaultValue, bool *hasValue) {
|
|
679
715
|
if (isKeyEmpty(key)) {
|
|
716
|
+
if (hasValue != nullptr) {
|
|
717
|
+
*hasValue = false;
|
|
718
|
+
}
|
|
680
719
|
return defaultValue;
|
|
681
720
|
}
|
|
682
721
|
SCOPED_LOCK(m_lock);
|
|
@@ -684,16 +723,25 @@ uint64_t MMKV::getUInt64(MMKVKey_t key, uint64_t defaultValue) {
|
|
|
684
723
|
if (data.length() > 0) {
|
|
685
724
|
try {
|
|
686
725
|
CodedInputData input(data.getPtr(), data.length());
|
|
726
|
+
if (hasValue != nullptr) {
|
|
727
|
+
*hasValue = true;
|
|
728
|
+
}
|
|
687
729
|
return input.readUInt64();
|
|
688
730
|
} catch (std::exception &exception) {
|
|
689
731
|
MMKVError("%s", exception.what());
|
|
690
732
|
}
|
|
691
733
|
}
|
|
734
|
+
if (hasValue != nullptr) {
|
|
735
|
+
*hasValue = false;
|
|
736
|
+
}
|
|
692
737
|
return defaultValue;
|
|
693
738
|
}
|
|
694
739
|
|
|
695
|
-
float MMKV::getFloat(MMKVKey_t key, float defaultValue) {
|
|
740
|
+
float MMKV::getFloat(MMKVKey_t key, float defaultValue, bool *hasValue) {
|
|
696
741
|
if (isKeyEmpty(key)) {
|
|
742
|
+
if (hasValue != nullptr) {
|
|
743
|
+
*hasValue = false;
|
|
744
|
+
}
|
|
697
745
|
return defaultValue;
|
|
698
746
|
}
|
|
699
747
|
SCOPED_LOCK(m_lock);
|
|
@@ -701,16 +749,25 @@ float MMKV::getFloat(MMKVKey_t key, float defaultValue) {
|
|
|
701
749
|
if (data.length() > 0) {
|
|
702
750
|
try {
|
|
703
751
|
CodedInputData input(data.getPtr(), data.length());
|
|
752
|
+
if (hasValue != nullptr) {
|
|
753
|
+
*hasValue = true;
|
|
754
|
+
}
|
|
704
755
|
return input.readFloat();
|
|
705
756
|
} catch (std::exception &exception) {
|
|
706
757
|
MMKVError("%s", exception.what());
|
|
707
758
|
}
|
|
708
759
|
}
|
|
760
|
+
if (hasValue != nullptr) {
|
|
761
|
+
*hasValue = false;
|
|
762
|
+
}
|
|
709
763
|
return defaultValue;
|
|
710
764
|
}
|
|
711
765
|
|
|
712
|
-
double MMKV::getDouble(MMKVKey_t key, double defaultValue) {
|
|
766
|
+
double MMKV::getDouble(MMKVKey_t key, double defaultValue, bool *hasValue) {
|
|
713
767
|
if (isKeyEmpty(key)) {
|
|
768
|
+
if (hasValue != nullptr) {
|
|
769
|
+
*hasValue = false;
|
|
770
|
+
}
|
|
714
771
|
return defaultValue;
|
|
715
772
|
}
|
|
716
773
|
SCOPED_LOCK(m_lock);
|
|
@@ -718,11 +775,17 @@ double MMKV::getDouble(MMKVKey_t key, double defaultValue) {
|
|
|
718
775
|
if (data.length() > 0) {
|
|
719
776
|
try {
|
|
720
777
|
CodedInputData input(data.getPtr(), data.length());
|
|
778
|
+
if (hasValue != nullptr) {
|
|
779
|
+
*hasValue = true;
|
|
780
|
+
}
|
|
721
781
|
return input.readDouble();
|
|
722
782
|
} catch (std::exception &exception) {
|
|
723
783
|
MMKVError("%s", exception.what());
|
|
724
784
|
}
|
|
725
785
|
}
|
|
786
|
+
if (hasValue != nullptr) {
|
|
787
|
+
*hasValue = false;
|
|
788
|
+
}
|
|
726
789
|
return defaultValue;
|
|
727
790
|
}
|
|
728
791
|
|
package/MMKV/Core/MMKV.h
CHANGED
|
@@ -47,6 +47,8 @@ enum MMKVMode : uint32_t {
|
|
|
47
47
|
#endif
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
#define OUT
|
|
51
|
+
|
|
50
52
|
class MMKV {
|
|
51
53
|
#ifndef MMKV_ANDROID
|
|
52
54
|
std::string m_mmapKey;
|
|
@@ -253,19 +255,19 @@ public:
|
|
|
253
255
|
bool getVector(MMKVKey_t key, std::vector<std::string> &result);
|
|
254
256
|
#endif // MMKV_APPLE
|
|
255
257
|
|
|
256
|
-
bool getBool(MMKVKey_t key, bool defaultValue = false);
|
|
258
|
+
bool getBool(MMKVKey_t key, bool defaultValue = false, OUT bool *hasValue = nullptr);
|
|
257
259
|
|
|
258
|
-
int32_t getInt32(MMKVKey_t key, int32_t defaultValue = 0);
|
|
260
|
+
int32_t getInt32(MMKVKey_t key, int32_t defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
259
261
|
|
|
260
|
-
uint32_t getUInt32(MMKVKey_t key, uint32_t defaultValue = 0);
|
|
262
|
+
uint32_t getUInt32(MMKVKey_t key, uint32_t defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
261
263
|
|
|
262
|
-
int64_t getInt64(MMKVKey_t key, int64_t defaultValue = 0);
|
|
264
|
+
int64_t getInt64(MMKVKey_t key, int64_t defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
263
265
|
|
|
264
|
-
uint64_t getUInt64(MMKVKey_t key, uint64_t defaultValue = 0);
|
|
266
|
+
uint64_t getUInt64(MMKVKey_t key, uint64_t defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
265
267
|
|
|
266
|
-
float getFloat(MMKVKey_t key, float defaultValue = 0);
|
|
268
|
+
float getFloat(MMKVKey_t key, float defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
267
269
|
|
|
268
|
-
double getDouble(MMKVKey_t key, double defaultValue = 0);
|
|
270
|
+
double getDouble(MMKVKey_t key, double defaultValue = 0, OUT bool *hasValue = nullptr);
|
|
269
271
|
|
|
270
272
|
// return the actual size consumption of the key's value
|
|
271
273
|
// pass actualSize = true to get value's length
|
package/MMKV/Core/MMKVPredef.h
CHANGED
package/MMKV/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT)
|
|
2
2
|
[](https://github.com/Tencent/MMKV/pulls)
|
|
3
|
-
[](https://github.com/Tencent/MMKV/releases)
|
|
4
4
|
[](https://github.com/Tencent/MMKV/wiki/home)
|
|
5
5
|
|
|
6
6
|
中文版本请参看[这里](./README_CN.md)
|
|
@@ -11,14 +11,14 @@ MMKV is an **efficient**, **small**, **easy-to-use** mobile key-value storage fr
|
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
* **Efficient**. MMKV uses mmap to keep memory synced with
|
|
14
|
+
* **Efficient**. MMKV uses mmap to keep memory synced with files, and protobuf to encode/decode values, making the most of Android to achieve the best performance.
|
|
15
15
|
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
|
16
16
|
|
|
17
17
|
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `sync`, no `apply` calls needed.
|
|
18
18
|
|
|
19
19
|
* **Small**.
|
|
20
|
-
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
|
21
|
-
* **About 50K in binary size**: MMKV adds about 50K per architecture on App size, and much less when zipped (
|
|
20
|
+
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics, and nothing more. It's really tidy.
|
|
21
|
+
* **About 50K in binary size**: MMKV adds about 50K per architecture on App size, and much less when zipped (APK).
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
## Getting Started
|
|
@@ -28,8 +28,8 @@ Add the following lines to `build.gradle` on your app module:
|
|
|
28
28
|
|
|
29
29
|
```gradle
|
|
30
30
|
dependencies {
|
|
31
|
-
implementation 'com.tencent:mmkv:1.2.
|
|
32
|
-
// replace "1.2.
|
|
31
|
+
implementation 'com.tencent:mmkv:1.2.13'
|
|
32
|
+
// replace "1.2.13" with any available version
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
@@ -78,19 +78,19 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc
|
|
|
78
78
|
|
|
79
79
|
## Features
|
|
80
80
|
|
|
81
|
-
* **Efficient**. MMKV uses mmap to keep memory synced with
|
|
81
|
+
* **Efficient**. MMKV uses mmap to keep memory synced with files, and protobuf to encode/decode values, making the most of iOS/macOS to achieve the best performance.
|
|
82
82
|
|
|
83
|
-
* **Easy-to-use**. You can use MMKV as you go, no configurations needed. All changes are saved immediately, no `synchronize` calls needed.
|
|
83
|
+
* **Easy-to-use**. You can use MMKV as you go, no configurations are needed. All changes are saved immediately, no `synchronize` calls are needed.
|
|
84
84
|
|
|
85
85
|
* **Small**.
|
|
86
86
|
* **A handful of files**: MMKV contains encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
|
87
|
-
* **Less than 30K in binary size**: MMKV adds less than 30K per architecture on App size, and much less when zipped (
|
|
87
|
+
* **Less than 30K in binary size**: MMKV adds less than 30K per architecture on App size, and much less when zipped (IPA).
|
|
88
88
|
|
|
89
89
|
## Getting Started
|
|
90
90
|
|
|
91
91
|
### Installation Via CocoaPods:
|
|
92
92
|
1. Install [CocoaPods](https://guides.CocoaPods.org/using/getting-started.html);
|
|
93
|
-
2. Open terminal, `cd` to your project directory, run `pod repo update` to make CocoaPods aware of the latest available MMKV versions;
|
|
93
|
+
2. Open the terminal, `cd` to your project directory, run `pod repo update` to make CocoaPods aware of the latest available MMKV versions;
|
|
94
94
|
3. Edit your Podfile, add `pod 'MMKV'` to your app target;
|
|
95
95
|
4. Run `pod install`;
|
|
96
96
|
5. Open the `.xcworkspace` file generated by CocoaPods;
|
|
@@ -99,7 +99,7 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc
|
|
|
99
99
|
For other installation options, see [iOS/macOS Setup](https://github.com/Tencent/MMKV/wiki/iOS_setup).
|
|
100
100
|
|
|
101
101
|
### Quick Tutorial
|
|
102
|
-
You can use MMKV as you go, no configurations needed. All changes are saved immediately, no `synchronize` calls needed.
|
|
102
|
+
You can use MMKV as you go, no configurations are needed. All changes are saved immediately, no `synchronize` calls are needed.
|
|
103
103
|
Setup MMKV on App startup, in your `-[MyApp application: didFinishLaunchingWithOptions:]`, add these lines:
|
|
104
104
|
|
|
105
105
|
```objective-c
|
|
@@ -139,13 +139,13 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc
|
|
|
139
139
|
|
|
140
140
|
## Features
|
|
141
141
|
|
|
142
|
-
* **Efficient**. MMKV uses mmap to keep memory synced with
|
|
142
|
+
* **Efficient**. MMKV uses mmap to keep memory synced with files, and protobuf to encode/decode values, making the most of Windows to achieve the best performance.
|
|
143
143
|
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
|
144
144
|
|
|
145
|
-
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls needed.
|
|
145
|
+
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls are needed.
|
|
146
146
|
|
|
147
147
|
* **Small**.
|
|
148
|
-
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
|
148
|
+
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics, and nothing more. It's really tidy.
|
|
149
149
|
* **About 10K in binary size**: MMKV adds about 10K on application size, and much less when zipped.
|
|
150
150
|
|
|
151
151
|
|
|
@@ -168,7 +168,7 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc
|
|
|
168
168
|
|
|
169
169
|
note:
|
|
170
170
|
|
|
171
|
-
1. MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or
|
|
171
|
+
1. MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or vice versa.
|
|
172
172
|
2. MMKV is developed with Visual Studio 2017, change the `Platform Toolset` if you use a different version of Visual Studio.
|
|
173
173
|
|
|
174
174
|
For other installation options, see [Win32 Setup](https://github.com/Tencent/MMKV/wiki/windows_setup).
|
|
@@ -210,20 +210,20 @@ MMKV also supports **Multi-Process Access**. Full tutorials can be found here [W
|
|
|
210
210
|
|
|
211
211
|
## Features
|
|
212
212
|
|
|
213
|
-
* **Efficient**. MMKV uses mmap to keep memory synced with
|
|
213
|
+
* **Efficient**. MMKV uses mmap to keep memory synced with files, and protobuf to encode/decode values, making the most of POSIX to achieve the best performance.
|
|
214
214
|
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
|
215
215
|
|
|
216
|
-
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls needed.
|
|
216
|
+
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls are needed.
|
|
217
217
|
|
|
218
218
|
* **Small**.
|
|
219
|
-
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
|
219
|
+
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics, and nothing more. It's really tidy.
|
|
220
220
|
* **About 7K in binary size**: MMKV adds about 7K on application size, and much less when zipped.
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
## Getting Started
|
|
224
224
|
|
|
225
225
|
### Installation Via CMake
|
|
226
|
-
1. Getting source code from git repository:
|
|
226
|
+
1. Getting source code from the git repository:
|
|
227
227
|
|
|
228
228
|
```
|
|
229
229
|
git clone https://github.com/Tencent/MMKV.git
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* **Encryption** support (secure storage)
|
|
30
30
|
* **Multiple instances** support (separate user-data with global data)
|
|
31
31
|
* **Customize storage location**
|
|
32
|
-
* **High performance** because everything is **written in C++**
|
|
32
|
+
* **High performance** because everything is **written in C++**
|
|
33
33
|
* **~30x faster than AsyncStorage**
|
|
34
34
|
* Uses [**JSI**](https://github.com/react-native-community/discussions-and-proposals/issues/91) instead of the "old" Bridge
|
|
35
35
|
* **iOS**, **Android** and **Web** support
|
|
@@ -104,7 +104,7 @@ This creates a new storage instance using a custom MMKV storage ID. By using a c
|
|
|
104
104
|
|
|
105
105
|
The following values can be configured:
|
|
106
106
|
|
|
107
|
-
* `id`: The MMKV instance's ID. If you want to use multiple instances, use different IDs. For example, you can separte the global app's storage and a logged-in user's storage. (
|
|
107
|
+
* `id`: The MMKV instance's ID. If you want to use multiple instances, use different IDs. For example, you can separte the global app's storage and a logged-in user's storage. (required if `path` or `encryptionKey` fields are specified, otherwise defaults to: `'mmkv.default'`)
|
|
108
108
|
* `path`: The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#customize-location) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#customize-location))
|
|
109
109
|
* `encryptionKey`: The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's/Android's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV. (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#encryption) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#encryption))
|
|
110
110
|
|
|
@@ -181,6 +181,10 @@ storage.recrypt(undefined)
|
|
|
181
181
|
|
|
182
182
|
As the library uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use [Flipper](https://fbflipper.com).
|
|
183
183
|
|
|
184
|
+
## Debugging
|
|
185
|
+
|
|
186
|
+
Use [flipper-plugin-react-native-mmkv](https://github.com/muchobien/flipper-plugin-react-native-mmkv) to debug your MMKV storage using Flipper. You can also simply `console.log` an MMKV instance.
|
|
187
|
+
|
|
184
188
|
## Adopting at scale
|
|
185
189
|
|
|
186
190
|
react-native-mmkv is provided _as is_, I work on it in my free time.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#include "MmkvHostObject.h"
|
|
10
10
|
#include <MMKV.h>
|
|
11
11
|
#include <android/log.h>
|
|
12
|
+
#include <string>
|
|
12
13
|
|
|
13
14
|
MmkvHostObject::MmkvHostObject(const std::string& instanceId, std::string path, std::string cryptKey) {
|
|
14
15
|
__android_log_print(ANDROID_LOG_INFO, "RNMMKV", "Creating MMKV instance \"%s\"... (Path: %s, Encryption-Key: %s)",
|
|
@@ -59,21 +60,23 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
59
60
|
const jsi::Value& thisValue,
|
|
60
61
|
const jsi::Value* arguments,
|
|
61
62
|
size_t count) -> jsi::Value {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
if (!arguments[0].isString()) {
|
|
64
|
+
throw jsi::JSError(runtime, "MMKV::set: First argument ('key') has to be of type string!");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
68
|
+
if (arguments[1].isBool()) {
|
|
69
|
+
instance->set(arguments[1].getBool(), keyName);
|
|
70
|
+
} else if (arguments[1].isNumber()) {
|
|
71
|
+
instance->set(arguments[1].getNumber(), keyName);
|
|
72
|
+
} else if (arguments[1].isString()) {
|
|
73
|
+
auto stringValue = arguments[1].getString(runtime).utf8(runtime);
|
|
74
|
+
instance->set(stringValue, keyName);
|
|
75
|
+
} else {
|
|
76
|
+
throw jsi::JSError(runtime, "MMKV::set: 'value' argument is not of type bool, number or string!");
|
|
77
|
+
}
|
|
78
|
+
return jsi::Value::undefined();
|
|
79
|
+
});
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
if (propName == "getBoolean") {
|
|
@@ -85,11 +88,19 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
85
88
|
const jsi::Value& thisValue,
|
|
86
89
|
const jsi::Value* arguments,
|
|
87
90
|
size_t count) -> jsi::Value {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
if (!arguments[0].isString()) {
|
|
92
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
96
|
+
bool hasValue;
|
|
97
|
+
auto value = instance->getBool(keyName, false, &hasValue);
|
|
98
|
+
if (hasValue) {
|
|
99
|
+
return jsi::Value(value);
|
|
100
|
+
} else {
|
|
101
|
+
return jsi::Value::undefined();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
if (propName == "getString") {
|
|
@@ -101,17 +112,19 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
101
112
|
const jsi::Value& thisValue,
|
|
102
113
|
const jsi::Value* arguments,
|
|
103
114
|
size_t count) -> jsi::Value {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
if (!arguments[0].isString()) {
|
|
116
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
117
|
+
}
|
|
107
118
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
120
|
+
std::string result;
|
|
121
|
+
bool hasValue = instance->getString(keyName, result);
|
|
122
|
+
if (hasValue) {
|
|
123
|
+
return jsi::Value(runtime, jsi::String::createFromUtf8(runtime, result));
|
|
124
|
+
} else {
|
|
125
|
+
return jsi::Value::undefined();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
if (propName == "getNumber") {
|
|
@@ -123,12 +136,19 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
123
136
|
const jsi::Value& thisValue,
|
|
124
137
|
const jsi::Value* arguments,
|
|
125
138
|
size_t count) -> jsi::Value {
|
|
126
|
-
|
|
127
|
-
|
|
139
|
+
if (!arguments[0].isString()) {
|
|
140
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
141
|
+
}
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
144
|
+
bool hasValue;
|
|
145
|
+
auto value = instance->getDouble(keyName, 0.0, &hasValue);
|
|
146
|
+
if (hasValue) {
|
|
147
|
+
return jsi::Value(value);
|
|
148
|
+
} else {
|
|
149
|
+
return jsi::Value::undefined();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
132
152
|
}
|
|
133
153
|
|
|
134
154
|
if (propName == "contains") {
|
|
@@ -140,12 +160,14 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
140
160
|
const jsi::Value& thisValue,
|
|
141
161
|
const jsi::Value* arguments,
|
|
142
162
|
size_t count) -> jsi::Value {
|
|
143
|
-
|
|
144
|
-
|
|
163
|
+
if (!arguments[0].isString()) {
|
|
164
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
165
|
+
}
|
|
145
166
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
167
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
168
|
+
bool containsKey = instance->containsKey(keyName);
|
|
169
|
+
return jsi::Value(containsKey);
|
|
170
|
+
});
|
|
149
171
|
}
|
|
150
172
|
|
|
151
173
|
if (propName == "delete") {
|
|
@@ -157,12 +179,14 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
157
179
|
const jsi::Value& thisValue,
|
|
158
180
|
const jsi::Value* arguments,
|
|
159
181
|
size_t count) -> jsi::Value {
|
|
160
|
-
|
|
161
|
-
|
|
182
|
+
if (!arguments[0].isString()) {
|
|
183
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
184
|
+
}
|
|
162
185
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
186
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
187
|
+
instance->removeValueForKey(keyName);
|
|
188
|
+
return jsi::Value::undefined();
|
|
189
|
+
});
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
if (propName == "getAllKeys") {
|
|
@@ -174,13 +198,13 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
174
198
|
const jsi::Value& thisValue,
|
|
175
199
|
const jsi::Value* arguments,
|
|
176
200
|
size_t count) -> jsi::Value {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
201
|
+
auto keys = instance->allKeys();
|
|
202
|
+
auto array = jsi::Array(runtime, keys.size());
|
|
203
|
+
for (int i = 0; i < keys.size(); i++) {
|
|
204
|
+
array.setValueAtIndex(runtime, i, keys[i]);
|
|
205
|
+
}
|
|
206
|
+
return array;
|
|
207
|
+
});
|
|
184
208
|
}
|
|
185
209
|
|
|
186
210
|
if (propName == "clearAll") {
|
|
@@ -192,10 +216,9 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
192
216
|
const jsi::Value& thisValue,
|
|
193
217
|
const jsi::Value* arguments,
|
|
194
218
|
size_t count) -> jsi::Value {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
});
|
|
219
|
+
instance->clearAll();
|
|
220
|
+
return jsi::Value::undefined();
|
|
221
|
+
});
|
|
199
222
|
}
|
|
200
223
|
|
|
201
224
|
if (propName == "recrypt") {
|