From 410c419cc270f7ff9124ded8fc2e47faba694016 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Wed, 4 Jan 2012 22:07:03 -0500 Subject: [PATCH 01/14] Major rebase Signed-off-by: Alexsander Akers --- MKiCloudSync.h | 29 ++++------- MKiCloudSync.m | 137 ++++++++++++++++++++++--------------------------- README.mdown | 57 ++++++++++---------- 3 files changed, 98 insertions(+), 125 deletions(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index db98c7b..1a59075 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -1,20 +1,21 @@ // // MKiCloudSync.h -// iCloud1 // -// Created by Mugunth Kumar (@mugunthkumar) on 20/11/11. +// Created by Mugunth Kumar on 11/20//11. +// Modified by Alexsander Akers on 1/4/12. +// // Copyright (C) 2011-2020 by Steinlogic - +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,23 +24,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// As a side note, you might also consider -// 1) tweeting about this mentioning @mugunthkumar -// 2) A paypal donation to mugunth.kumar@gmail.com - -#ifdef DEBUG -# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); -#else -# define DLog(...) -#endif - -// ALog always displays output regardless of the DEBUG setting -#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); - #import -#define kMKiCloudSyncNotification @"MKiCloudSyncDidUpdateToLatest" @interface MKiCloudSync : NSObject -+(void) start; ++ (BOOL) start; ++ (void) stop; + @end diff --git a/MKiCloudSync.m b/MKiCloudSync.m index b42f9db..cb69f2b 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -1,20 +1,21 @@ // // MKiCloudSync.m -// iCloud1 // -// Created by Mugunth Kumar (@mugunthkumar) on 20/11/11. +// Created by Mugunth Kumar on 11/20//11. +// Modified by Alexsander Akers on 1/4/12. +// // Copyright (C) 2011-2020 by Steinlogic - +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,86 +24,70 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// As a side note, you might also consider -// 1) tweeting about this mentioning @mugunthkumar -// 2) A paypal donation to mugunth.kumar@gmail.com - #import "MKiCloudSync.h" -@implementation MKiCloudSync - -+(void) updateToiCloud:(NSNotification*) notificationObject { - - NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; - - [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - - [[NSUbiquitousKeyValueStore defaultStore] setObject:obj forKey:key]; - }]; - - [[NSUbiquitousKeyValueStore defaultStore] synchronize]; -} - -+(void) updateFromiCloud:(NSNotification*) notificationObject { - - NSUbiquitousKeyValueStore *iCloudStore = [NSUbiquitousKeyValueStore defaultStore]; - NSDictionary *dict = [iCloudStore dictionaryRepresentation]; - - // prevent NSUserDefaultsDidChangeNotification from being posted while we update from iCloud - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSUserDefaultsDidChangeNotification - object:nil]; +@interface MKiCloudSync () - [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - - [[NSUserDefaults standardUserDefaults] setObject:obj forKey:key]; - }]; ++ (void) pushToICloud: (NSNotification *) note; ++ (void) pullFromICloud: (NSNotification *) note; - [[NSUserDefaults standardUserDefaults] synchronize]; +@end - // enable NSUserDefaultsDidChangeNotification notifications again +@implementation MKiCloudSync - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(updateToiCloud:) - name:NSUserDefaultsDidChangeNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMKiCloudSyncNotification object:nil]; ++ (BOOL) start +{ + if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) + { + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: [NSUbiquitousKeyValueStore defaultStore]]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud:) name: NSUserDefaultsDidChangeNotification object: [NSUserDefaults defaultStore]]; + + return YES; + } + + return NO; } - -+(void) start { - - if(NSClassFromString(@"NSUbiquitousKeyValueStore")) { // is iOS 5? - - if([NSUbiquitousKeyValueStore defaultStore]) { // is iCloud enabled - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(updateFromiCloud:) - name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(updateToiCloud:) - name:NSUserDefaultsDidChangeNotification object:nil]; - } else { - DLog(@"iCloud not enabled"); - } - } - else { - DLog(@"Not an iOS 5 device"); - } ++ (void) stop +{ + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + [dnc removeObserver: self name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: nil]; + [dnc removeObserver: self name: NSUserDefaultsDidChangeNotification object: nil]; } -+ (void) dealloc { - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSUserDefaultsDidChangeNotification - object:nil]; ++ (void) pushToICloud: (NSNotification *) note +{ + [self stop]; + + NSString *identifier = [[NSBundle mainBundle] bundleIdentifier]; + NSDictionary *persistentDomain = [[NSUserDefaults standardUserDefaults] persistentDomainForName: identifier]; + + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + [persistentDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [store setObject:obj forKey:key]; + }]; + + [store synchronize]; + + [self start]; +} ++ (void) pullFromICloud: (NSNotification *) note +{ + [self stop]; + + NSUbiquitousKeyValueStore *store = note.object; + + NSArray *changedKeys = [note.userInfo objectForKey: NSUbiquitousKeyValueStoreChangedKeysKey]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [changedKeys enumerateObjectsUsingBlock: ^(NSString *key, BOOL *stop) { + id obj = [store objectForKey: key]; + [userDefaults setObject: obj forKey: key]; + }]; + + [userDefaults synchronize]; + + [self start]; } + @end diff --git a/README.mdown b/README.mdown index 26ccd53..278310c 100644 --- a/README.mdown +++ b/README.mdown @@ -1,34 +1,33 @@ -### What is this? +# MKiCloudSync + +## What is it? A clean and simple class to sync NSUserDefaults to iCloud. -### How to use? -1. Drag the two classes and #import the header file in your Application Delegate -2. Call [MKiCloudSync start]; -3. There is no Step 3. +## How do you use it? +1. Copy *MKiCloudSync.h* and *MKiCloudSync.m* into your Xcode project. +2. Call `[MKiCloudSync start]`. +3. There is no step 3. -Read the [blog post](http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code) for more -###License -// Copyright (C) 2011-2020 by Steinlogic +Read the [blog post](http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code) for more information. -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +## License -// As a side note, you might also consider -// 1) tweeting about this mentioning @mugunthkumar -// 2) A paypal donation to mugunth.kumar@gmail.com - +> Copyright (c) 2011–2012 by Steinlogic and MKiCloudSync Contributors +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. \ No newline at end of file From 0d0953fc5287e1a5336250831c712a3874a25865 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Thu, 5 Jan 2012 12:30:43 -0500 Subject: [PATCH 02/14] Fix little errors Signed-off-by: Alexsander Akers --- MKiCloudSync.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MKiCloudSync.m b/MKiCloudSync.m index cb69f2b..6db1b86 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -41,7 +41,7 @@ + (BOOL) start if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) { [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: [NSUbiquitousKeyValueStore defaultStore]]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud:) name: NSUserDefaultsDidChangeNotification object: [NSUserDefaults defaultStore]]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud:) name: NSUserDefaultsDidChangeNotification object: [NSUserDefaults standardUserDefaults]]; return YES; } @@ -80,7 +80,7 @@ + (void) pullFromICloud: (NSNotification *) note NSArray *changedKeys = [note.userInfo objectForKey: NSUbiquitousKeyValueStoreChangedKeysKey]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [changedKeys enumerateObjectsUsingBlock: ^(NSString *key, BOOL *stop) { + [changedKeys enumerateObjectsUsingBlock: ^(NSString *key, NSUInteger idx, BOOL *stop) { id obj = [store objectForKey: key]; [userDefaults setObject: obj forKey: key]; }]; From 7bd8855bdd2e4df061726802dcd7697f9bb7f936 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Sat, 7 Jan 2012 15:32:32 -0500 Subject: [PATCH 03/14] Add "did push" and "did pull" notifications --- MKiCloudSync.h | 3 +++ MKiCloudSync.m | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index 1a59075..b987c74 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -26,6 +26,9 @@ #import +extern NSString *MKiCloudSyncDidPullFromICloudNotification; +extern NSString *MKiCloudSyncDidPushToICloudNotification; + @interface MKiCloudSync : NSObject + (BOOL) start; diff --git a/MKiCloudSync.m b/MKiCloudSync.m index 6db1b86..fbc2dbd 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -24,9 +24,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - #import "MKiCloudSync.h" +NSString *MKiCloudSyncDidPullFromICloudNotification = @"MKiCloudSyncDidPullFromICloudNotification"; +NSString *MKiCloudSyncDidPushToICloudNotification = @"MKiCloudSyncDidPushToICloudNotification"; + @interface MKiCloudSync () + (void) pushToICloud: (NSNotification *) note; @@ -50,9 +52,7 @@ + (BOOL) start } + (void) stop { - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - [dnc removeObserver: self name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: nil]; - [dnc removeObserver: self name: NSUserDefaultsDidChangeNotification object: nil]; + [[NSNotificationCenter defaultCenter] removeObserver: self]; } + (void) pushToICloud: (NSNotification *) note @@ -64,12 +64,14 @@ + (void) pushToICloud: (NSNotification *) note NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; [persistentDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - [store setObject:obj forKey:key]; + [store setObject: obj forKey: key]; }]; [store synchronize]; [self start]; + + [[NSNotificationCenter defaultCenter] postNotificationName: MKiCloudSyncDidPushToICloudNotification object: self userInfo: note.userInfo]; } + (void) pullFromICloud: (NSNotification *) note { @@ -88,6 +90,8 @@ + (void) pullFromICloud: (NSNotification *) note [userDefaults synchronize]; [self start]; + + [[NSNotificationCenter defaultCenter] postNotificationName: MKiCloudSyncDidPullFromICloudNotification object: self userInfo: note.userInfo]; } @end From db14cb2b7716c9ca1c912872e37f0f86307e410f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20B=C3=A4umle?= Date: Sun, 8 Jan 2012 01:27:13 +0100 Subject: [PATCH 04/14] Solution to three common issues --- MKiCloudSync.h | 5 ++-- MKiCloudSync.m | 79 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index b987c74..c73b429 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -25,13 +25,12 @@ // THE SOFTWARE. #import - -extern NSString *MKiCloudSyncDidPullFromICloudNotification; -extern NSString *MKiCloudSyncDidPushToICloudNotification; +#define kMKiCloudSyncNotification @"MKiCloudSyncDidUpdateToLatest" @interface MKiCloudSync : NSObject + (BOOL) start; + (void) stop; ++ (void) clean; @end diff --git a/MKiCloudSync.m b/MKiCloudSync.m index fbc2dbd..5265800 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -24,15 +24,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import "MKiCloudSync.h" -NSString *MKiCloudSyncDidPullFromICloudNotification = @"MKiCloudSyncDidPullFromICloudNotification"; -NSString *MKiCloudSyncDidPushToICloudNotification = @"MKiCloudSyncDidPushToICloudNotification"; +#import "MKiCloudSync.h" @interface MKiCloudSync () -+ (void) pushToICloud: (NSNotification *) note; ++ (void) pushToICloud; + (void) pullFromICloud: (NSNotification *) note; ++ (void) clean; @end @@ -42,8 +41,28 @@ + (BOOL) start { if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) { - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: [NSUbiquitousKeyValueStore defaultStore]]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud:) name: NSUserDefaultsDidChangeNotification object: [NSUserDefaults standardUserDefaults]]; + // FORCE PUSH + [MKiCloudSync pushToICloud]; + // + + // FORCE PULL + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + + NSDictionary *dict = [store dictionaryRepresentation]; + NSLog(@"!!! UPDATING FROM ICLOUD !!! %@", dict); + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [userDefaults setObject: obj forKey: key]; + }]; + + [userDefaults synchronize]; + + [[NSNotificationCenter defaultCenter] postNotificationName: kMKiCloudSyncNotification object: nil]; + // + + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; return YES; } @@ -55,12 +74,16 @@ + (void) stop [[NSNotificationCenter defaultCenter] removeObserver: self]; } -+ (void) pushToICloud: (NSNotification *) note ++ (void) pushToICloud { - [self stop]; - NSString *identifier = [[NSBundle mainBundle] bundleIdentifier]; - NSDictionary *persistentDomain = [[NSUserDefaults standardUserDefaults] persistentDomainForName: identifier]; + NSMutableDictionary *persistentDomain = [NSMutableDictionary dictionaryWithDictionary: [[NSUserDefaults standardUserDefaults] persistentDomainForName: identifier]]; + + // EXCL. SPECIAL KEYS LIKE DEVICE-SPECIFIC ONES + [persistentDomain removeObjectsForKeys: [NSArray arrayWithObjects: @"iCloudSync", nil]]; + // + + NSLog(@"!!! UPDATING TO ICLOUD !!! %@", persistentDomain); NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; [persistentDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { @@ -68,18 +91,15 @@ + (void) pushToICloud: (NSNotification *) note }]; [store synchronize]; - - [self start]; - - [[NSNotificationCenter defaultCenter] postNotificationName: MKiCloudSyncDidPushToICloudNotification object: self userInfo: note.userInfo]; } + (void) pullFromICloud: (NSNotification *) note { - [self stop]; + [[NSNotificationCenter defaultCenter] removeObserver: self name: NSUserDefaultsDidChangeNotification object: nil]; NSUbiquitousKeyValueStore *store = note.object; NSArray *changedKeys = [note.userInfo objectForKey: NSUbiquitousKeyValueStoreChangedKeysKey]; + NSLog(@"!!! UPDATING FROM ICLOUD !!! %@", changedKeys); NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [changedKeys enumerateObjectsUsingBlock: ^(NSString *key, NSUInteger idx, BOOL *stop) { @@ -89,9 +109,34 @@ + (void) pullFromICloud: (NSNotification *) note [userDefaults synchronize]; - [self start]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; - [[NSNotificationCenter defaultCenter] postNotificationName: MKiCloudSyncDidPullFromICloudNotification object: self userInfo: note.userInfo]; + [[NSNotificationCenter defaultCenter] postNotificationName: kMKiCloudSyncNotification object: nil]; +} + ++ (void) clean { + [self stop]; + + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + + NSDictionary *dict = [store dictionaryRepresentation]; + [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + // NON-NIL TO KEEP KEY + [store setObject: @"" forKey: key]; + }]; + + [store synchronize]; + NSLog(@"!!! CLEANING ICLOUD !!! %@", [store dictionaryRepresentation]); +} + ++ (void)dealloc { + // DOES ANYONE KNOW HOW LONG THIS IS KEPT ALIVE? + // SOMETIMES I FELT LIKE THE CLASS STOPPED WORKING, + // HOWEVER AFTER IMPLEMENTING THIS, + // THE LOG NEVER APPEARED FOR ME. + NSLog(@"!!! FOR DEBUGGING PURPOSES ONLY !!!"); + [super dealloc]; + // } @end From 0d99768a937c8c1f8a6d514eb593bb79f5938362 Mon Sep 17 00:00:00 2001 From: iosdeveloper Date: Sun, 8 Jan 2012 01:49:20 +0100 Subject: [PATCH 05/14] Typo --- MKiCloudSync.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MKiCloudSync.m b/MKiCloudSync.m index 5265800..3943f86 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -121,8 +121,9 @@ + (void) clean { NSDictionary *dict = [store dictionaryRepresentation]; [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - // NON-NIL TO KEEP KEY + // NON-NIL TO KEEP KEY, NIL TO LOOSE KEY [store setObject: @"" forKey: key]; + // }]; [store synchronize]; From 04ad9bd1dc5158ab4859d5519719136d501c6d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20B=C3=A4umle?= Date: Sun, 8 Jan 2012 01:59:21 +0100 Subject: [PATCH 06/14] TO DOs --- TODO | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..1a7e71b --- /dev/null +++ b/TODO @@ -0,0 +1,19 @@ +TO DO: + +- WE HAVE TO BE CLEAR ABOUT THE MEMORY MANAGEMENT AND ALTERNATIVES LIKE A SINGLETON. (iosdeveloper) + +- KEYS TO IGNORE FEATURE NEEDS PUBLIC API (iosdeveloper) + +- SEPARATE LIST OF ALL CONTRIBUTORS (iosdeveloper) + +- MARKDOWN AND PROPER FORMAT FOR TODOS (iosdeveloper) + +DONE: + +- WHAT ABOUT KEYS THAT ARE ALREADY IN THE CLOUD WHEN AN APP IS INSTALLED ON ANOTHER DEVICE OR REINSTALLED? (iosdeveloper) + +- WOULDN'T IT BE GREAT TO HAVE THE OPTION TO IGNORE KEYS ESPECIALLY THE WEBKIT-ONES OR DEVICE-SPECIFIC ONES? (iosdeveloper) + +- CLEAN AWAY ALL KEYS AND VALUES (FOR TESTING) (iosdeveloper) + +ADD AND REMOVE TODOS AS YOU LIKE \ No newline at end of file From 66f8ef5d6b6f97969bfef69eb00de6afd71b5c2f Mon Sep 17 00:00:00 2001 From: iosdeveloper Date: Sun, 8 Jan 2012 02:05:17 +0100 Subject: [PATCH 07/14] Typo --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 1a7e71b..5544571 100644 --- a/TODO +++ b/TODO @@ -16,4 +16,4 @@ DONE: - CLEAN AWAY ALL KEYS AND VALUES (FOR TESTING) (iosdeveloper) -ADD AND REMOVE TODOS AS YOU LIKE \ No newline at end of file +ADD AND MOVE TODOS AS YOU LIKE \ No newline at end of file From 4664100d6ab5924e07b6e6571d69d33de8c805ac Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Sat, 7 Jan 2012 20:37:03 -0500 Subject: [PATCH 08/14] Update project based on @iosdeveloper's changes --- MKiCloudSync.h | 12 ++++- MKiCloudSync.m | 144 ++++++++++++++++++++++++++----------------------- TODO | 19 ------- 3 files changed, 87 insertions(+), 88 deletions(-) delete mode 100644 TODO diff --git a/MKiCloudSync.h b/MKiCloudSync.h index c73b429..4d6b217 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -25,12 +25,20 @@ // THE SOFTWARE. #import -#define kMKiCloudSyncNotification @"MKiCloudSyncDidUpdateToLatest" + +// Change to 1 to enable logging +#define MKiCloudSyncDebug 1 + +// Posted +extern NSString *MKiCloudSyncDidUpdateNotification; @interface MKiCloudSync : NSObject + (BOOL) start; + ++ (NSMutableSet *) ignoredKeys; + ++ (void) cleanUbiquitousStore; + (void) stop; -+ (void) clean; @end diff --git a/MKiCloudSync.m b/MKiCloudSync.m index 3943f86..3729bb2 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -24,14 +24,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +NSString *MKiCloudSyncDidUpdateNotification = @"MKiCloudSyncDidUpdateNotification"; #import "MKiCloudSync.h" @interface MKiCloudSync () -+ (void) pushToICloud; + (void) pullFromICloud: (NSNotification *) note; -+ (void) clean; ++ (void) pushToICloud; @end @@ -41,103 +41,113 @@ + (BOOL) start { if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) { - // FORCE PUSH - [MKiCloudSync pushToICloud]; - // - - // FORCE PULL - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - NSDictionary *dict = [store dictionaryRepresentation]; - NSLog(@"!!! UPDATING FROM ICLOUD !!! %@", dict); - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - [userDefaults setObject: obj forKey: key]; - }]; - - [userDefaults synchronize]; - - [[NSNotificationCenter defaultCenter] postNotificationName: kMKiCloudSyncNotification object: nil]; - // - - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; + // Force push + [MKiCloudSync pushToICloud]; + + // Force pull + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + NSDictionary *dict = [store dictionaryRepresentation]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [userDefaults setObject: obj forKey: key]; + }]; + [userDefaults synchronize]; + + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + + // Post notification + [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: self]; + + // Add self as observer + [dnc addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; + [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Updating from iCloud"); +#endif return YES; } return NO; } -+ (void) stop + ++ (NSMutableSet *) ignoredKeys { - [[NSNotificationCenter defaultCenter] removeObserver: self]; + static NSMutableSet *ignoredKeys; + static dispatch_once_t once; + dispatch_once(&once, ^{ + ignoredKeys = [NSMutableSet new]; + }); + + return ignoredKeys; } -+ (void) pushToICloud ++ (void) cleanUbiquitousStore { - NSString *identifier = [[NSBundle mainBundle] bundleIdentifier]; - NSMutableDictionary *persistentDomain = [NSMutableDictionary dictionaryWithDictionary: [[NSUserDefaults standardUserDefaults] persistentDomainForName: identifier]]; - - // EXCL. SPECIAL KEYS LIKE DEVICE-SPECIFIC ONES - [persistentDomain removeObjectsForKeys: [NSArray arrayWithObjects: @"iCloudSync", nil]]; - // - - NSLog(@"!!! UPDATING TO ICLOUD !!! %@", persistentDomain); + [self stop]; NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - [persistentDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - [store setObject: obj forKey: key]; + NSDictionary *dict = [store dictionaryRepresentation]; + + NSMutableSet *keys = [NSMutableSet setWithArray: [dict allKeys]]; + [keys minusSet: [self ignoredKeys]]; + + [keys enumerateObjectsUsingBlock: ^(NSString *key, BOOL *stop) { + [store removeObjectForKey: key]; }]; [store synchronize]; + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Cleaned ubiquitous store"); +#endif } + (void) pullFromICloud: (NSNotification *) note { - [[NSNotificationCenter defaultCenter] removeObserver: self name: NSUserDefaultsDidChangeNotification object: nil]; + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + [dnc removeObserver: self name: NSUserDefaultsDidChangeNotification object: nil]; NSUbiquitousKeyValueStore *store = note.object; - NSArray *changedKeys = [note.userInfo objectForKey: NSUbiquitousKeyValueStoreChangedKeysKey]; - NSLog(@"!!! UPDATING FROM ICLOUD !!! %@", changedKeys); + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Pulled from iCloud"); +#endif NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [changedKeys enumerateObjectsUsingBlock: ^(NSString *key, NSUInteger idx, BOOL *stop) { id obj = [store objectForKey: key]; [userDefaults setObject: obj forKey: key]; }]; - [userDefaults synchronize]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName: kMKiCloudSyncNotification object: nil]; + [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; + [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: nil]; } - -+ (void) clean { - [self stop]; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - NSDictionary *dict = [store dictionaryRepresentation]; - [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - // NON-NIL TO KEEP KEY, NIL TO LOOSE KEY - [store setObject: @"" forKey: key]; - // ++ (void) pushToICloud +{ + NSString *identifier = [[NSBundle mainBundle] bundleIdentifier]; + + NSMutableDictionary *persistentDomain = [[[NSUserDefaults standardUserDefaults] persistentDomainForName: identifier] mutableCopy]; + + NSArray *ignoredKeys = [[self ignoredKeys] allObjects]; + [persistentDomain removeObjectsForKeys: ignoredKeys]; + + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + [persistentDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [store setObject: obj forKey: key]; }]; - - [store synchronize]; - NSLog(@"!!! CLEANING ICLOUD !!! %@", [store dictionaryRepresentation]); + [store synchronize]; + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Pushed to iCloud"); +#endif } - -+ (void)dealloc { - // DOES ANYONE KNOW HOW LONG THIS IS KEPT ALIVE? - // SOMETIMES I FELT LIKE THE CLASS STOPPED WORKING, - // HOWEVER AFTER IMPLEMENTING THIS, - // THE LOG NEVER APPEARED FOR ME. - NSLog(@"!!! FOR DEBUGGING PURPOSES ONLY !!!"); - [super dealloc]; - // ++ (void) stop +{ + [[NSNotificationCenter defaultCenter] removeObserver: self]; } @end diff --git a/TODO b/TODO deleted file mode 100644 index 5544571..0000000 --- a/TODO +++ /dev/null @@ -1,19 +0,0 @@ -TO DO: - -- WE HAVE TO BE CLEAR ABOUT THE MEMORY MANAGEMENT AND ALTERNATIVES LIKE A SINGLETON. (iosdeveloper) - -- KEYS TO IGNORE FEATURE NEEDS PUBLIC API (iosdeveloper) - -- SEPARATE LIST OF ALL CONTRIBUTORS (iosdeveloper) - -- MARKDOWN AND PROPER FORMAT FOR TODOS (iosdeveloper) - -DONE: - -- WHAT ABOUT KEYS THAT ARE ALREADY IN THE CLOUD WHEN AN APP IS INSTALLED ON ANOTHER DEVICE OR REINSTALLED? (iosdeveloper) - -- WOULDN'T IT BE GREAT TO HAVE THE OPTION TO IGNORE KEYS ESPECIALLY THE WEBKIT-ONES OR DEVICE-SPECIFIC ONES? (iosdeveloper) - -- CLEAN AWAY ALL KEYS AND VALUES (FOR TESTING) (iosdeveloper) - -ADD AND MOVE TODOS AS YOU LIKE \ No newline at end of file From 7be9b26d516c05aae5cbfdc30f49efd04143bf15 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Sat, 11 Feb 2012 13:50:47 -0500 Subject: [PATCH 09/14] Add PodSpec Signed-off-by: Alexsander Akers --- MKiCloudSync.podspec | 13 +++++++++++++ README.mdown | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 MKiCloudSync.podspec diff --git a/MKiCloudSync.podspec b/MKiCloudSync.podspec new file mode 100644 index 0000000..565ed5b --- /dev/null +++ b/MKiCloudSync.podspec @@ -0,0 +1,13 @@ +Pod::Spec.new do |s| + s.name = 'MKiCloudSync' + s.version = '1.0' + s.license = 'MIT' + s.summary = 'Sync your NSUserDefaults to iCloud automatically.' + s.homepage = 'https://github.com/pandamonia/MKiCloudSync' + s.author = { 'Alexsander Akers' => 'a2@pandamonia.us', + 'Mugunth Kumar' => 'contact@mk.sg' } + s.source = { :git => 'https://github.com/pandamonia/MKiCloudSync.git', :tag => 'v1.0' } + s.platform = :ios + s.source_files = 'MKiCloudSync.{h,m}' + s.requires_arc = true +end diff --git a/README.mdown b/README.mdown index 278310c..26f6f2c 100644 --- a/README.mdown +++ b/README.mdown @@ -12,7 +12,7 @@ Read the [blog post](http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-s ## License -> Copyright (c) 2011–2012 by Steinlogic and MKiCloudSync Contributors +> Copyright (c) 2011–2012 by Steinlogic and Alexsander Akers > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal From 2f9ab1fa06a1178761a8e3e63743b6990e150b64 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 20 Feb 2012 14:34:22 +0100 Subject: [PATCH 10/14] Change debug output to be off by default Signed-off-by: Aron Cedercrantz --- MKiCloudSync.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index 4d6b217..047b2ff 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -27,7 +27,7 @@ #import // Change to 1 to enable logging -#define MKiCloudSyncDebug 1 +#define MKiCloudSyncDebug 0 // Posted extern NSString *MKiCloudSyncDidUpdateNotification; From 7e9c803817c65adf5a2d2d323b2281c32a99e425 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Mon, 27 Feb 2012 19:51:13 -0500 Subject: [PATCH 11/14] Tag version 1.0.1 Signed-off-by: Alexsander Akers --- MKiCloudSync.podspec | 4 ++-- README.mdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MKiCloudSync.podspec b/MKiCloudSync.podspec index 565ed5b..d15eb4d 100644 --- a/MKiCloudSync.podspec +++ b/MKiCloudSync.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'MKiCloudSync' - s.version = '1.0' + s.version = '1.0.1' s.license = 'MIT' s.summary = 'Sync your NSUserDefaults to iCloud automatically.' s.homepage = 'https://github.com/pandamonia/MKiCloudSync' s.author = { 'Alexsander Akers' => 'a2@pandamonia.us', 'Mugunth Kumar' => 'contact@mk.sg' } - s.source = { :git => 'https://github.com/pandamonia/MKiCloudSync.git', :tag => 'v1.0' } + s.source = { :git => 'https://github.com/pandamonia/MKiCloudSync.git', :tag => 'v1.0.1' } s.platform = :ios s.source_files = 'MKiCloudSync.{h,m}' s.requires_arc = true diff --git a/README.mdown b/README.mdown index 26f6f2c..278310c 100644 --- a/README.mdown +++ b/README.mdown @@ -12,7 +12,7 @@ Read the [blog post](http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-s ## License -> Copyright (c) 2011–2012 by Steinlogic and Alexsander Akers +> Copyright (c) 2011–2012 by Steinlogic and MKiCloudSync Contributors > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal From e051611c8030599e1ea67b75f8ccba7328acd80b Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Tue, 8 May 2012 20:22:17 +0200 Subject: [PATCH 12/14] Change so that the sync can not be started multiple times. - Without being stopped first that is. Signed-off-by: Aron Cedercrantz --- MKiCloudSync.h | 2 + MKiCloudSync.m | 99 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index 047b2ff..e85f117 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -34,6 +34,8 @@ extern NSString *MKiCloudSyncDidUpdateNotification; @interface MKiCloudSync : NSObject ++ (BOOL) isSyncing; + + (BOOL) start; + (NSMutableSet *) ignoredKeys; diff --git a/MKiCloudSync.m b/MKiCloudSync.m index 3729bb2..7b5700a 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -33,41 +33,82 @@ @interface MKiCloudSync () + (void) pullFromICloud: (NSNotification *) note; + (void) pushToICloud; ++ (BOOL)tryToStartSync; + @end @implementation MKiCloudSync +static dispatch_queue_t _queue; +static BOOL _isSyncing; + ++ (void)initialize +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _queue = dispatch_queue_create("com.mugunthkumarMKiCloudSync", DISPATCH_QUEUE_SERIAL); + _isSyncing = NO; + }); +} + ++ (BOOL) isSyncing +{ + __block BOOL isSyncing = NO; + dispatch_sync(_queue, ^{ + isSyncing = _isSyncing; + }); + return isSyncing; +} + ++ (BOOL)tryToStartSync +{ + __block BOOL didSucceed = NO; + dispatch_sync(_queue, ^{ + if (!_isSyncing) { + _isSyncing = YES; + didSucceed = YES; + } + }); + return didSucceed; +} + + (BOOL) start { if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) { - // Force push - [MKiCloudSync pushToICloud]; - - // Force pull - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - NSDictionary *dict = [store dictionaryRepresentation]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - [userDefaults setObject: obj forKey: key]; - }]; - [userDefaults synchronize]; - - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - - // Post notification - [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: self]; - - // Add self as observer - [dnc addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; - [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; - + if ([self tryToStartSync]) { #if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Updating from iCloud"); + NSLog(@"MKiCloudSync: Will start sync"); #endif - - return YES; + + // Force push + [MKiCloudSync pushToICloud]; + + // Force pull + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + NSDictionary *dict = [store dictionaryRepresentation]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [userDefaults setObject: obj forKey: key]; + }]; + [userDefaults synchronize]; + + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + + // Post notification + [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: self]; + + // Add self as observer + [dnc addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; + [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Did start sync"); + NSLog(@"MKiCloudSync: Updating from iCloud"); +#endif + return YES; + } } return NO; @@ -147,7 +188,13 @@ + (void) pushToICloud } + (void) stop { - [[NSNotificationCenter defaultCenter] removeObserver: self]; +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Stop syncining with iCloud"); +#endif + dispatch_sync(_queue, ^{ + _isSyncing = NO; + [[NSNotificationCenter defaultCenter] removeObserver: self]; + }); } @end From bbf84686d19c9397e46d63b9cb66e5e0c1703b01 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Sun, 8 Jul 2012 10:16:34 -0400 Subject: [PATCH 13/14] Clean up changes from merged pull request Signed-off-by: Alexsander Akers --- MKiCloudSync.h | 3 +- MKiCloudSync.m | 135 ++++++++++++++++++++++++------------------------- 2 files changed, 68 insertions(+), 70 deletions(-) diff --git a/MKiCloudSync.h b/MKiCloudSync.h index e85f117..c8e4eb8 100644 --- a/MKiCloudSync.h +++ b/MKiCloudSync.h @@ -30,12 +30,11 @@ #define MKiCloudSyncDebug 0 // Posted -extern NSString *MKiCloudSyncDidUpdateNotification; +extern NSString *const MKiCloudSyncDidUpdateNotification; @interface MKiCloudSync : NSObject + (BOOL) isSyncing; - + (BOOL) start; + (NSMutableSet *) ignoredKeys; diff --git a/MKiCloudSync.m b/MKiCloudSync.m index 7b5700a..b8a4a98 100644 --- a/MKiCloudSync.m +++ b/MKiCloudSync.m @@ -24,101 +24,92 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -NSString *MKiCloudSyncDidUpdateNotification = @"MKiCloudSyncDidUpdateNotification"; - #import "MKiCloudSync.h" +NSString *const MKiCloudSyncDidUpdateNotification = @"MKiCloudSyncDidUpdateNotification"; + +static BOOL _isSyncing; +static dispatch_queue_t _queue; + @interface MKiCloudSync () ++ (BOOL) tryToStartSync; + + (void) pullFromICloud: (NSNotification *) note; + (void) pushToICloud; -+ (BOOL)tryToStartSync; - @end @implementation MKiCloudSync -static dispatch_queue_t _queue; -static BOOL _isSyncing; - -+ (void)initialize -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - _queue = dispatch_queue_create("com.mugunthkumarMKiCloudSync", DISPATCH_QUEUE_SERIAL); - _isSyncing = NO; - }); -} - + (BOOL) isSyncing { __block BOOL isSyncing = NO; + dispatch_sync(_queue, ^{ isSyncing = _isSyncing; }); - return isSyncing; -} -+ (BOOL)tryToStartSync -{ - __block BOOL didSucceed = NO; - dispatch_sync(_queue, ^{ - if (!_isSyncing) { - _isSyncing = YES; - didSucceed = YES; - } - }); - return didSucceed; + return isSyncing; } - + (BOOL) start { - if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore]) + if ([NSUbiquitousKeyValueStore class] && [NSUbiquitousKeyValueStore defaultStore] && [self tryToStartSync]) { - if ([self tryToStartSync]) { #if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Will start sync"); + NSLog(@"MKiCloudSync: Will start sync"); #endif - - // Force push - [MKiCloudSync pushToICloud]; - - // Force pull - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - NSDictionary *dict = [store dictionaryRepresentation]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { - [userDefaults setObject: obj forKey: key]; - }]; - [userDefaults synchronize]; - - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - - // Post notification - [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: self]; - - // Add self as observer - [dnc addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; - [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; - + + // Force push + [MKiCloudSync pushToICloud]; + + // Force pull + NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; + NSDictionary *dict = [store dictionaryRepresentation]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { + [userDefaults setObject: obj forKey: key]; + }]; + [userDefaults synchronize]; + + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + + // Post notification + [dnc postNotificationName: MKiCloudSyncDidUpdateNotification object: self]; + + // Add self as observer + [dnc addObserver: self selector: @selector(pullFromICloud:) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: store]; + [dnc addObserver: self selector: @selector(pushToICloud) name: NSUserDefaultsDidChangeNotification object: nil]; + #if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Did start sync"); - NSLog(@"MKiCloudSync: Updating from iCloud"); + NSLog(@"MKiCloudSync: Did start sync"); #endif - return YES; - } + return YES; } return NO; } ++ (BOOL) tryToStartSync +{ + __block BOOL didSucceed = NO; + + dispatch_sync(_queue, ^{ + if (!_isSyncing) + { + _isSyncing = YES; + didSucceed = YES; + } + }); + + return didSucceed; +} + (NSMutableSet *) ignoredKeys { static NSMutableSet *ignoredKeys; - static dispatch_once_t once; - dispatch_once(&once, ^{ + static dispatch_once_t token; + dispatch_once(&token, ^{ ignoredKeys = [NSMutableSet new]; }); @@ -138,13 +129,20 @@ + (void) cleanUbiquitousStore [keys enumerateObjectsUsingBlock: ^(NSString *key, BOOL *stop) { [store removeObjectForKey: key]; }]; - [store synchronize]; #if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Cleaned ubiquitous store"); + NSLog(@"MKiCloudSync: Cleaned ubiquitous store"); #endif } ++ (void) initialize +{ + if (self == [MKiCloudSync class]) + { + _isSyncing = NO; + _queue = dispatch_queue_create("com.mugunthkumar.MKiCloudSync", DISPATCH_QUEUE_SERIAL); + } +} + (void) pullFromICloud: (NSNotification *) note { NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; @@ -152,9 +150,9 @@ + (void) pullFromICloud: (NSNotification *) note NSUbiquitousKeyValueStore *store = note.object; NSArray *changedKeys = [note.userInfo objectForKey: NSUbiquitousKeyValueStoreChangedKeysKey]; - + #if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Pulled from iCloud"); + NSLog(@"MKiCloudSync: Pulled from iCloud"); #endif NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; @@ -188,12 +186,13 @@ + (void) pushToICloud } + (void) stop { -#if MKiCloudSyncDebug - NSLog(@"MKiCloudSync: Stop syncining with iCloud"); -#endif dispatch_sync(_queue, ^{ _isSyncing = NO; [[NSNotificationCenter defaultCenter] removeObserver: self]; + +#if MKiCloudSyncDebug + NSLog(@"MKiCloudSync: Stopped syncing with iCloud"); +#endif }); } From 67d416fc9bbcee6756760e3a2f3e39a64da26fa1 Mon Sep 17 00:00:00 2001 From: Alexsander Akers Date: Sun, 8 Jul 2012 10:16:46 -0400 Subject: [PATCH 14/14] Tag version 1.0.2 Signed-off-by: Alexsander Akers --- MKiCloudSync.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MKiCloudSync.podspec b/MKiCloudSync.podspec index d15eb4d..2787003 100644 --- a/MKiCloudSync.podspec +++ b/MKiCloudSync.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'MKiCloudSync' - s.version = '1.0.1' + s.version = '1.0.2' s.license = 'MIT' s.summary = 'Sync your NSUserDefaults to iCloud automatically.' s.homepage = 'https://github.com/pandamonia/MKiCloudSync' s.author = { 'Alexsander Akers' => 'a2@pandamonia.us', 'Mugunth Kumar' => 'contact@mk.sg' } - s.source = { :git => 'https://github.com/pandamonia/MKiCloudSync.git', :tag => 'v1.0.1' } + s.source = { :git => 'https://github.com/pandamonia/MKiCloudSync.git', :tag => 'v1.0.2' } s.platform = :ios s.source_files = 'MKiCloudSync.{h,m}' s.requires_arc = true