├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── RNICloudStore.podspec ├── iCloudStorage.h ├── iCloudStorage.m ├── icloudstorage.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── index.js └── package.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manicakes/react-native-icloudstore/20f20106d5c52adcef68ebb5b8833c5160eb4b50/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Mani Ghasemlou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-icloudstore 📱☁️📱 2 | 3 | [![npm version](https://badge.fury.io/js/react-native-icloudstore.svg)](http://badge.fury.io/js/react-native-icloudstore) 4 | 5 | A drop in replacement for [React Native](https://github.com/facebook/react-native)'s [AsyncStorage](https://facebook.github.io/react-native/docs/asyncstorage.html) API that wraps the [iCloud Ubiquitous Key-Value Store](https://developer.apple.com/library/content/documentation/General/Conceptual/iCloudDesignGuide/Chapters/DesigningForKey-ValueDataIniCloud.html). 6 | 7 | ## Usage 8 | 9 | In your target's "capabilities" tab in Xcode, make sure that iCloud is switched on as well as make sure that the "Key-value storage" option is checked. 10 | 11 | `react-native-icloudstore` mimicks the same promise-based API as [AsyncStorage](https://facebook.github.io/react-native/docs/asyncstorage.html). In addition to all of the `AsyncStorage` methods, there is one additional feature: a native event (`iCloudStoreDidChangeRemotely`) that lets you know when your store changed due to a remote change (i.e. from another device on the same iCloud account). See the example below for a *very* basic way to make use of that in your React Native application. For apps that use [redux](http://redux.js.org), you may want to call an appropriate [action creator](http://redux.js.org/docs/basics/Actions.html) upon receiving the event. 12 | 13 | ```javascript 14 | import { NativeEventEmitter } from 'react-native'; 15 | import iCloudStorage from 'react-native-icloudstore'; 16 | 17 | ... 18 | 19 | componentWillMount() { 20 | this.eventEmitter = new NativeEventEmitter(iCloudStorage); 21 | this.eventEmitter.addListener('iCloudStoreDidChangeRemotely', this.loadData); 22 | } 23 | 24 | componentWillUnmount() { 25 | this.eventEmitter.remove(); 26 | } 27 | 28 | loadData = (userInfo) => { 29 | const changedKeys = userInfo.changedKeys; 30 | if (changedKeys != null && changedKeys.includes('MY_STORAGE_KEY')) { 31 | iCloudStorage.getItem('MY_STORAGE_KEY').then(result => this.setState({ storage: result })); 32 | } 33 | } 34 | 35 | ... 36 | 37 | ``` 38 | 39 | ## Install 40 | 41 | ```shell 42 | npm install --save react-native-icloudstore 43 | ``` 44 | 45 | ## Automatically link 46 | 47 | #### With React Native 0.27+ 48 | 49 | ```shell 50 | react-native link react-native-icloudstore 51 | ``` 52 | 53 | #### With older versions of React Native 54 | 55 | You need [`rnpm`](https://github.com/rnpm/rnpm) (`npm install -g rnpm`) 56 | 57 | ```shell 58 | rnpm link react-native-icloudstore 59 | ``` 60 | 61 | ## Manually link 62 | 63 | ### iOS (via Cocoa Pods) 64 | Add the following line to your build targets in your `Podfile` 65 | 66 | `pod 'RNICloudStore', :path => '../node_modules/react-native-icloudstore'` 67 | 68 | Then run `pod install` 69 | 70 | ### iOS (without Cocoa Pods) 71 | 72 | In XCode, in the project navigator: 73 | - Right click _Libraries_ 74 | - Add Files to _[your project's name]_ 75 | - Go to `node_modules/react-native-icloudstore` 76 | - Add the `.xcodeproj` file 77 | 78 | In XCode, in the project navigator, select your project. 79 | - Add the `libicloudstorage.a` from the _deviceinfo_ project to your project's _Build Phases ➜ Link Binary With Libraries_ 80 | - Click `.xcodeproj` file you added before in the project navigator and go the _Build Settings_ tab. Make sure _All_ is toggled on (instead of _Basic_). 81 | - Look for _Header Search Paths_ and make sure it contains both `$(SRCROOT)/../react-native/React` and `$(SRCROOT)/../../React` 82 | - Mark both as recursive (should be OK by default). 83 | 84 | Run your project (Cmd+R) 85 | 86 | ### Android 87 | 88 | Android isn't supported - importing will simply return `AsyncStorage` so your app should continue to work. 89 | 90 | ## Feedback 91 | 92 | Questions? Comments? Feel free to [email me](mailto:mani.ghasemlou@icloud.com). 93 | 94 | If you have an issue, please create an issue under the "Issues" tab above. Or, feel free to issue a pull request. 🤓 95 | -------------------------------------------------------------------------------- /RNICloudStore.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "RNICloudStore" 3 | s.version = "0.1.0" 4 | s.summary = "AsyncStorage replacement that uses iCloud ubiquitous key store." 5 | 6 | s.homepage = "https://github.com/manicakes/react-native-icloudstore" 7 | 8 | s.license = "MIT" 9 | s.authors = { "Mani Ghasemlou" => "mani.ghasemlou@icloud.com" } 10 | s.platforms = {:ios => '7.0', :tvos => '11.0'} 11 | 12 | s.source = { :git => "https://github.com/manicakes/react-native-icloudstore.git" } 13 | 14 | s.source_files = "*.{h,m}" 15 | 16 | s.dependency 'React' 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /iCloudStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // iCloudStorage.h 3 | // iCloudStorage 4 | // 5 | // Created by Mani Ghasemlou on 12/18/16. 6 | // Copyright © 2016 Mani Ghasemlou. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface iCloudStorage : RCTEventEmitter 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /iCloudStorage.m: -------------------------------------------------------------------------------- 1 | // 2 | // iCloudStorage.m 3 | // iCloudStorage 4 | // 5 | // Created by Mani Ghasemlou on 12/18/16. 6 | // Copyright © 2016 Mani Ghasemlou. All rights reserved. 7 | // 8 | 9 | #import "iCloudStorage.h" 10 | #import 11 | #import 12 | 13 | static NSString* const ICLOUDSTORAGE_PREFIX = @"@com.manicakes.iCloudStorage/"; 14 | static NSString* const ICLOUD_STORE_CHANGED = @"ICLOUD_STORE_CHANGED"; 15 | static NSString* const kStoreChangedEvent = @"iCloudStoreDidChangeRemotely"; 16 | static NSString* const kChangedKeys = @"changedKeys"; 17 | 18 | @implementation iCloudStorage 19 | 20 | + (NSString*)appendPrefixToKey:(NSString*)key { 21 | return [NSString stringWithFormat:@"%@%@", ICLOUDSTORAGE_PREFIX, key]; 22 | } 23 | 24 | + (NSString*)removePrefixFromKey:(NSString*)key { 25 | if (![key hasPrefix:ICLOUDSTORAGE_PREFIX]) { 26 | return nil; 27 | } 28 | return [key substringFromIndex:[ICLOUDSTORAGE_PREFIX length]]; 29 | } 30 | 31 | + (NSDictionary*)storeDictionary { 32 | NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore]; 33 | return [store dictionaryRepresentation]; 34 | } 35 | 36 | + (NSArray*)allKeysInStore { 37 | return [[iCloudStorage storeDictionary] allKeys]; 38 | } 39 | 40 | + (id) getObjectForKey:(NSString*)key { 41 | return [[NSUbiquitousKeyValueStore defaultStore] objectForKey:[iCloudStorage appendPrefixToKey:key]]; 42 | } 43 | 44 | + (void) setValue:(NSString*)value forKey:(NSString*)key { 45 | [[NSUbiquitousKeyValueStore defaultStore] setObject:value forKey:[iCloudStorage appendPrefixToKey:key]]; 46 | [[NSUbiquitousKeyValueStore defaultStore] synchronize]; 47 | } 48 | 49 | + (void) removeKey:(NSString*)key { 50 | [[NSUbiquitousKeyValueStore defaultStore] removeObjectForKey:[iCloudStorage appendPrefixToKey:key]]; 51 | [[NSUbiquitousKeyValueStore defaultStore] synchronize]; 52 | } 53 | 54 | + (NSString*) getMergedItemWithKey:(NSString*)key value:(NSString*)value rejecter:(RCTPromiseRejectBlock)reject { 55 | NSDictionary* storedItem = @{}; 56 | NSDictionary* newItem = @{}; 57 | NSString* storedString = [iCloudStorage getObjectForKey:key]; 58 | 59 | if (storedString != nil) { 60 | NSError* error = nil; 61 | id object = [NSJSONSerialization JSONObjectWithData:[storedString dataUsingEncoding:NSUTF8StringEncoding] 62 | options:0 63 | error:&error]; 64 | if (error != nil) { 65 | reject(@"json_decode_err", @"Error parsing stored value as JSON string.", error); 66 | return nil; 67 | } 68 | 69 | if (![object isKindOfClass:[NSDictionary class]]) { 70 | reject(@"json_not_object_err", @"The stored JSON string does not parse into an object.", nil); 71 | return nil; 72 | } 73 | 74 | if (value != nil) { 75 | id newObject = [NSJSONSerialization JSONObjectWithData:[value dataUsingEncoding:NSUTF8StringEncoding] 76 | options:0 77 | error:&error]; 78 | if (error != nil) { 79 | reject(@"json_decode_err", @"The provided value is not valid JSON.", error); 80 | return nil; 81 | } 82 | 83 | if (![newItem isKindOfClass:[NSDictionary class]]) { 84 | reject(@"json_not_object_err", @"The provided JSON string does not parse into an object.", nil); 85 | return nil; 86 | } 87 | 88 | newItem = newObject; 89 | } 90 | 91 | storedItem = object; 92 | } 93 | 94 | NSMutableDictionary* mergedItem = [NSMutableDictionary dictionaryWithDictionary:storedItem]; 95 | [mergedItem addEntriesFromDictionary:newItem]; 96 | 97 | NSError* error = nil; 98 | NSData* data = [NSJSONSerialization dataWithJSONObject:mergedItem options:0 error:&error]; 99 | if (error != nil) { 100 | reject(@"json_encode_err", @"Error encoding the merged JSON data to string.", error); 101 | return nil; 102 | } 103 | 104 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 105 | } 106 | 107 | - (instancetype)init { 108 | self = [super init]; 109 | 110 | if (self) { 111 | [[NSNotificationCenter defaultCenter] addObserver:self 112 | selector:@selector(ubiquitousStoreUpdated:) 113 | name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification 114 | object:nil]; 115 | [[NSUbiquitousKeyValueStore defaultStore] synchronize]; 116 | } 117 | 118 | return self; 119 | } 120 | 121 | +(BOOL)requiresMainQueueSetup { 122 | return YES; 123 | } 124 | 125 | - (dispatch_queue_t)methodQueue 126 | { 127 | return dispatch_get_main_queue(); 128 | } 129 | 130 | - (NSArray *)supportedEvents { 131 | return @[ kStoreChangedEvent ]; 132 | } 133 | 134 | - (void) ubiquitousStoreUpdated:(NSNotification*)notification { 135 | // if this notification comes in before bridge has initialized, 136 | // don't try to send the event (app crashes if you do). 137 | if (!self.bridge) { 138 | return; 139 | } 140 | 141 | NSArray* changedKeys = [[notification userInfo] objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; 142 | NSMutableArray* reportedChangedKeys = [NSMutableArray array]; 143 | for (NSString* key in changedKeys) { 144 | NSString* reportedKey = [iCloudStorage removePrefixFromKey:key]; 145 | if (reportedKey) { 146 | [reportedChangedKeys addObject:reportedKey]; 147 | } 148 | } 149 | 150 | if ([reportedChangedKeys count]) { 151 | NSDictionary* body = @{ kChangedKeys : reportedChangedKeys }; 152 | [self sendEventWithName:kStoreChangedEvent body:body]; 153 | } 154 | } 155 | 156 | RCT_EXPORT_MODULE(RNICloudStorage) 157 | 158 | 159 | RCT_EXPORT_METHOD(getItem: (NSString*)key resolver:(RCTPromiseResolveBlock)resolve 160 | rejecter:(RCTPromiseRejectBlock)reject) { 161 | resolve([iCloudStorage getObjectForKey:key]); 162 | } 163 | 164 | RCT_EXPORT_METHOD(setItem: (NSString*)key value: (NSString*)value resolver:(RCTPromiseResolveBlock)resolve 165 | rejecter:(RCTPromiseRejectBlock)reject) { 166 | [iCloudStorage setValue:value forKey:key]; 167 | resolve(@{}); 168 | } 169 | 170 | RCT_EXPORT_METHOD(removeItem: (NSString*)key resolver:(RCTPromiseResolveBlock)resolve 171 | rejecter:(RCTPromiseRejectBlock)reject) { 172 | [iCloudStorage removeKey:key]; 173 | resolve(@{}); 174 | } 175 | 176 | RCT_EXPORT_METHOD(mergeItem: (NSString*)key value: (NSString*)value resolver:(RCTPromiseResolveBlock)resolve 177 | rejecter:(RCTPromiseRejectBlock)reject) { 178 | NSString* newValue = [iCloudStorage getMergedItemWithKey:key value:value rejecter:reject]; 179 | if (newValue == nil) { 180 | // we failed and reject block was called. 181 | return; 182 | } 183 | 184 | [iCloudStorage setValue:newValue forKey:key]; 185 | 186 | resolve(@{}); 187 | } 188 | 189 | RCT_REMAP_METHOD(clear, clearResolver:(RCTPromiseResolveBlock)resolve 190 | rejecter:(RCTPromiseRejectBlock)reject) { 191 | for (NSString* key in [iCloudStorage allKeysInStore]) { 192 | if ([key hasPrefix:ICLOUDSTORAGE_PREFIX]) { 193 | [[NSUbiquitousKeyValueStore defaultStore] removeObjectForKey:key]; 194 | } 195 | } 196 | 197 | resolve(@{}); 198 | } 199 | 200 | RCT_REMAP_METHOD(getAllKeys, getAllKeysResolver:(RCTPromiseResolveBlock)resolve 201 | rejecter:(RCTPromiseRejectBlock)reject) { 202 | NSMutableArray* allKeys = [NSMutableArray array]; 203 | 204 | for (NSString* storeKey in [iCloudStorage allKeysInStore]) { 205 | NSString* key = [iCloudStorage removePrefixFromKey:storeKey]; 206 | if (key != nil) { 207 | [allKeys addObject:key]; 208 | } 209 | } 210 | 211 | resolve(allKeys); 212 | } 213 | 214 | RCT_EXPORT_METHOD(multiGet: (NSArray*)keys resolver:(RCTPromiseResolveBlock)resolve 215 | rejecter:(RCTPromiseRejectBlock)reject) { 216 | NSMutableArray *result = [NSMutableArray arrayWithCapacity:[keys count]]; 217 | for (NSString* key in keys) { 218 | NSObject* object = [iCloudStorage getObjectForKey:key]; 219 | if (object == nil) { 220 | object = [NSNull null]; 221 | } 222 | [result addObject:@[key, object]]; 223 | } 224 | 225 | resolve(result); 226 | } 227 | 228 | RCT_EXPORT_METHOD(multiSet: (NSArray *> *)keyValuePairs resolver:(RCTPromiseResolveBlock)resolve 229 | rejecter:(RCTPromiseRejectBlock)reject) { 230 | for (NSArray *entry in keyValuePairs) { 231 | [iCloudStorage setValue:entry[1] forKey:entry[0]]; 232 | } 233 | resolve(@{}); 234 | } 235 | 236 | RCT_EXPORT_METHOD(multiRemove: (NSArray*)keys resolver:(RCTPromiseResolveBlock)resolve 237 | rejecter:(RCTPromiseRejectBlock)reject) { 238 | for (NSString* key in keys) { 239 | [iCloudStorage removeKey:key]; 240 | } 241 | 242 | resolve(@{}); 243 | } 244 | 245 | RCT_EXPORT_METHOD(multiMerge: (NSDictionary*)keyValuePairs resolver:(RCTPromiseResolveBlock)resolve 246 | rejecter:(RCTPromiseRejectBlock)reject) { 247 | NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:[keyValuePairs count]]; 248 | BOOL failed = NO; 249 | for (NSString* key in [keyValuePairs allKeys]) { 250 | NSString* newValue = [iCloudStorage getMergedItemWithKey:key value:[keyValuePairs objectForKey:key] rejecter:reject]; 251 | if (newValue == nil) { 252 | break; 253 | } 254 | } 255 | 256 | if (failed) { 257 | return; 258 | } 259 | 260 | for (NSString* key in [result allKeys]) { 261 | [iCloudStorage setValue:[result objectForKey:key] forKey:key]; 262 | } 263 | 264 | resolve(@{}); 265 | } 266 | 267 | - (NSDictionary *)constantsToExport { 268 | return @{ ICLOUD_STORE_CHANGED : kStoreChangedEvent }; 269 | } 270 | 271 | @end 272 | -------------------------------------------------------------------------------- /icloudstorage.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3C50A1B21E16279100866B37 /* iCloudStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C50A1B11E16279100866B37 /* iCloudStorage.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = "include/$(PRODUCT_NAME)"; 18 | dstSubfolderSpec = 16; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 0; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 134814201AA4EA6300B7C361 /* libicloudstorage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libicloudstorage.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 3C50A1B01E16279100866B37 /* iCloudStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iCloudStorage.h; sourceTree = ""; }; 28 | 3C50A1B11E16279100866B37 /* iCloudStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iCloudStorage.m; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 134814211AA4EA7D00B7C361 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 134814201AA4EA6300B7C361 /* libicloudstorage.a */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 58B511D21A9E6C8500147676 = { 51 | isa = PBXGroup; 52 | children = ( 53 | 3C50A1B01E16279100866B37 /* iCloudStorage.h */, 54 | 3C50A1B11E16279100866B37 /* iCloudStorage.m */, 55 | 134814211AA4EA7D00B7C361 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | /* End PBXGroup section */ 60 | 61 | /* Begin PBXNativeTarget section */ 62 | 58B511DA1A9E6C8500147676 /* icloudstorage */ = { 63 | isa = PBXNativeTarget; 64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "icloudstorage" */; 65 | buildPhases = ( 66 | 58B511D71A9E6C8500147676 /* Sources */, 67 | 58B511D81A9E6C8500147676 /* Frameworks */, 68 | 58B511D91A9E6C8500147676 /* CopyFiles */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = icloudstorage; 75 | productName = RCTDataManager; 76 | productReference = 134814201AA4EA6300B7C361 /* libicloudstorage.a */; 77 | productType = "com.apple.product-type.library.static"; 78 | }; 79 | /* End PBXNativeTarget section */ 80 | 81 | /* Begin PBXProject section */ 82 | 58B511D31A9E6C8500147676 /* Project object */ = { 83 | isa = PBXProject; 84 | attributes = { 85 | LastUpgradeCheck = 0610; 86 | ORGANIZATIONNAME = Facebook; 87 | TargetAttributes = { 88 | 58B511DA1A9E6C8500147676 = { 89 | CreatedOnToolsVersion = 6.1.1; 90 | }; 91 | }; 92 | }; 93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "icloudstorage" */; 94 | compatibilityVersion = "Xcode 3.2"; 95 | developmentRegion = English; 96 | hasScannedForEncodings = 0; 97 | knownRegions = ( 98 | en, 99 | ); 100 | mainGroup = 58B511D21A9E6C8500147676; 101 | productRefGroup = 58B511D21A9E6C8500147676; 102 | projectDirPath = ""; 103 | projectRoot = ""; 104 | targets = ( 105 | 58B511DA1A9E6C8500147676 /* icloudstorage */, 106 | ); 107 | }; 108 | /* End PBXProject section */ 109 | 110 | /* Begin PBXSourcesBuildPhase section */ 111 | 58B511D71A9E6C8500147676 /* Sources */ = { 112 | isa = PBXSourcesBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 3C50A1B21E16279100866B37 /* iCloudStorage.m in Sources */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXSourcesBuildPhase section */ 120 | 121 | /* Begin XCBuildConfiguration section */ 122 | 58B511ED1A9E6C8500147676 /* Debug */ = { 123 | isa = XCBuildConfiguration; 124 | buildSettings = { 125 | ALWAYS_SEARCH_USER_PATHS = NO; 126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 127 | CLANG_CXX_LIBRARY = "libc++"; 128 | CLANG_ENABLE_MODULES = YES; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN_UNREACHABLE_CODE = YES; 138 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 139 | COPY_PHASE_STRIP = NO; 140 | ENABLE_STRICT_OBJC_MSGSEND = YES; 141 | GCC_C_LANGUAGE_STANDARD = gnu99; 142 | GCC_DYNAMIC_NO_PIC = NO; 143 | GCC_OPTIMIZATION_LEVEL = 0; 144 | GCC_PREPROCESSOR_DEFINITIONS = ( 145 | "DEBUG=1", 146 | "$(inherited)", 147 | ); 148 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 149 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 150 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 151 | GCC_WARN_UNDECLARED_SELECTOR = YES; 152 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 153 | GCC_WARN_UNUSED_FUNCTION = YES; 154 | GCC_WARN_UNUSED_VARIABLE = YES; 155 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 156 | MTL_ENABLE_DEBUG_INFO = YES; 157 | ONLY_ACTIVE_ARCH = YES; 158 | SDKROOT = iphoneos; 159 | }; 160 | name = Debug; 161 | }; 162 | 58B511EE1A9E6C8500147676 /* Release */ = { 163 | isa = XCBuildConfiguration; 164 | buildSettings = { 165 | ALWAYS_SEARCH_USER_PATHS = NO; 166 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 167 | CLANG_CXX_LIBRARY = "libc++"; 168 | CLANG_ENABLE_MODULES = YES; 169 | CLANG_ENABLE_OBJC_ARC = YES; 170 | CLANG_WARN_BOOL_CONVERSION = YES; 171 | CLANG_WARN_CONSTANT_CONVERSION = YES; 172 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 173 | CLANG_WARN_EMPTY_BODY = YES; 174 | CLANG_WARN_ENUM_CONVERSION = YES; 175 | CLANG_WARN_INT_CONVERSION = YES; 176 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 177 | CLANG_WARN_UNREACHABLE_CODE = YES; 178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 179 | COPY_PHASE_STRIP = YES; 180 | ENABLE_NS_ASSERTIONS = NO; 181 | ENABLE_STRICT_OBJC_MSGSEND = YES; 182 | GCC_C_LANGUAGE_STANDARD = gnu99; 183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 185 | GCC_WARN_UNDECLARED_SELECTOR = YES; 186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 187 | GCC_WARN_UNUSED_FUNCTION = YES; 188 | GCC_WARN_UNUSED_VARIABLE = YES; 189 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 190 | MTL_ENABLE_DEBUG_INFO = NO; 191 | SDKROOT = iphoneos; 192 | VALIDATE_PRODUCT = YES; 193 | }; 194 | name = Release; 195 | }; 196 | 58B511F01A9E6C8500147676 /* Debug */ = { 197 | isa = XCBuildConfiguration; 198 | buildSettings = { 199 | HEADER_SEARCH_PATHS = ( 200 | "$(inherited)", 201 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 202 | "$(SRCROOT)/../../React/**", 203 | "$(SRCROOT)/../../node_modules/react-native/React/**", 204 | "$(SRCROOT)/../react-native/React", 205 | ); 206 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 207 | OTHER_LDFLAGS = "-ObjC"; 208 | PRODUCT_NAME = icloudstorage; 209 | SKIP_INSTALL = YES; 210 | }; 211 | name = Debug; 212 | }; 213 | 58B511F11A9E6C8500147676 /* Release */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | HEADER_SEARCH_PATHS = ( 217 | "$(inherited)", 218 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 219 | "$(SRCROOT)/../../React/**", 220 | "$(SRCROOT)/../react-native/React", 221 | ); 222 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 223 | OTHER_LDFLAGS = "-ObjC"; 224 | PRODUCT_NAME = icloudstorage; 225 | SKIP_INSTALL = YES; 226 | }; 227 | name = Release; 228 | }; 229 | /* End XCBuildConfiguration section */ 230 | 231 | /* Begin XCConfigurationList section */ 232 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "icloudstorage" */ = { 233 | isa = XCConfigurationList; 234 | buildConfigurations = ( 235 | 58B511ED1A9E6C8500147676 /* Debug */, 236 | 58B511EE1A9E6C8500147676 /* Release */, 237 | ); 238 | defaultConfigurationIsVisible = 0; 239 | defaultConfigurationName = Release; 240 | }; 241 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "icloudstorage" */ = { 242 | isa = XCConfigurationList; 243 | buildConfigurations = ( 244 | 58B511F01A9E6C8500147676 /* Debug */, 245 | 58B511F11A9E6C8500147676 /* Release */, 246 | ); 247 | defaultConfigurationIsVisible = 0; 248 | defaultConfigurationName = Release; 249 | }; 250 | /* End XCConfigurationList section */ 251 | }; 252 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 253 | } 254 | -------------------------------------------------------------------------------- /icloudstorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @providesModule react-native-icloudstore 3 | */ 4 | 5 | import { NativeModules, Platform } from 'react-native'; 6 | import AsyncStorage from "@react-native-async-storage/async-storage"; 7 | 8 | const iCloudStorage = Platform.OS === 'ios' || Platform.isTVOS ? NativeModules.RNICloudStorage : AsyncStorage; 9 | 10 | export default iCloudStorage; 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-icloudstore", 3 | "version": "0.9.0", 4 | "description": "Drop-in replacement for AsyncStorage that uses iCloud ubiquitous key-value store.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/manicakes/react-native-icloudstore.git" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "icloud" 16 | ], 17 | "author": "Mani Ghasemlou ", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/manicakes/react-native-icloudstore/issues" 21 | }, 22 | "homepage": "https://github.com/manicakes/react-native-icloudstore#readme", 23 | "dependencies": { 24 | "@react-native-async-storage/async-storage": "^1.17.0" 25 | } 26 | } 27 | --------------------------------------------------------------------------------