diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/FTASync.podspec b/FTASync.podspec new file mode 100644 index 0000000..3a847cd --- /dev/null +++ b/FTASync.podspec @@ -0,0 +1,24 @@ +# +# Be sure to run `pod spec lint FTASync.podspec' to ensure this is a +# valid spec. +# +# Remove all comments before submitting the spec. Optional attributes are commented. +# +# For details see: https://github.com/CocoaPods/CocoaPods/wiki/The-podspec-format +# +Pod::Spec.new do |s| + s.name = "FTASync" + s.version = "0.0.6" + s.summary = "Allows you to sync CoreData entities with a Parse backend." + s.homepage = "https://github.com/itsniper/FTASync" + + s.license = { :type => 'Custom', :file => 'LICENSE.txt' } + s.author = { "Andy Bennett" => "andy@steamshift.net" } + + s.source = { :git => "https://github.com/akbsteam/FTASync.git" } + s.platform = :ios + + s.source_files = 'Source', 'Source/*.{h,m}' + s.dependency 'Parse', '>= 1.2.8' + s.dependency 'MagicalRecord', '>= 2.1.0' +end diff --git a/FTASyncDemo/FTASyncDemo.xcodeproj/project.pbxproj b/FTASyncDemo/FTASyncDemo.xcodeproj/project.pbxproj index f93426e..6da067c 100644 --- a/FTASyncDemo/FTASyncDemo.xcodeproj/project.pbxproj +++ b/FTASyncDemo/FTASyncDemo.xcodeproj/project.pbxproj @@ -23,35 +23,8 @@ /* Begin PBXBuildFile section */ 496E58F5160ABFFE00BC00B5 /* _AbstractPerson.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E58F2160ABFFE00BC00B5 /* _AbstractPerson.m */; }; 496E58F6160ABFFE00BC00B5 /* AbstractPerson.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E58F4160ABFFE00BC00B5 /* AbstractPerson.m */; }; - 496E5B91160AE7D400BC00B5 /* MagicalImportFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B59160AE7D400BC00B5 /* MagicalImportFunctions.m */; }; - 496E5B92160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B5B160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.m */; }; - 496E5B93160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B5D160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.m */; }; - 496E5B94160AE7D400BC00B5 /* NSNumber+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B5F160AE7D400BC00B5 /* NSNumber+MagicalDataImport.m */; }; - 496E5B95160AE7D400BC00B5 /* NSObject+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B61160AE7D400BC00B5 /* NSObject+MagicalDataImport.m */; }; - 496E5B96160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B63160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.m */; }; - 496E5B97160AE7D400BC00B5 /* NSString+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B65160AE7D400BC00B5 /* NSString+MagicalDataImport.m */; }; - 496E5B98160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B68160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.m */; }; - 496E5B99160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B6A160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.m */; }; - 496E5B9A160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B6C160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.m */; }; - 496E5B9B160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B6E160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.m */; }; - 496E5B9C160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B70160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.m */; }; - 496E5B9D160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B73160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.m */; }; - 496E5B9E160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B75160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.m */; }; - 496E5B9F160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B77160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.m */; }; - 496E5BA0160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B79160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.m */; }; - 496E5BA1160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B7B160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.m */; }; - 496E5BA2160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B7D160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.m */; }; - 496E5BA3160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B7F160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.m */; }; - 496E5BA4160AE7D400BC00B5 /* MagicalRecord+Actions.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B82160AE7D400BC00B5 /* MagicalRecord+Actions.m */; }; - 496E5BA5160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B84160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.m */; }; - 496E5BA6160AE7D400BC00B5 /* MagicalRecord+iCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B86160AE7D400BC00B5 /* MagicalRecord+iCloud.m */; }; - 496E5BA7160AE7D400BC00B5 /* MagicalRecord+Options.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B88160AE7D400BC00B5 /* MagicalRecord+Options.m */; }; - 496E5BA8160AE7D400BC00B5 /* MagicalRecord+Setup.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B8A160AE7D400BC00B5 /* MagicalRecord+Setup.m */; }; - 496E5BA9160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B8C160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.m */; }; - 496E5BAA160AE7D400BC00B5 /* MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 496E5B8E160AE7D400BC00B5 /* MagicalRecord.m */; }; 8B22B7E915C2DFC800F01B27 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B22B7E815C2DFC800F01B27 /* Crashlytics.framework */; }; 8B345364157C2B4200725E14 /* FTASetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B345363157C2B4200725E14 /* FTASetupViewController.m */; }; - 8B5AFC50152D1797000AF428 /* Parse.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B5AFC4F152D1797000AF428 /* Parse.framework */; }; 8B5AFC52152D17C6000AF428 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B5AFC51152D17C6000AF428 /* AudioToolbox.framework */; }; 8B5AFC54152D17D1000AF428 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B5AFC53152D17D1000AF428 /* CFNetwork.framework */; }; 8B5AFC56152D17DD000AF428 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B5AFC55152D17DD000AF428 /* SystemConfiguration.framework */; }; @@ -72,7 +45,7 @@ 8B6D399C15282F1800B296D6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B6D397C15282F1800B296D6 /* UIKit.framework */; }; 8B6D399D15282F1800B296D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B6D397E15282F1800B296D6 /* Foundation.framework */; }; 8B6D39A515282F1800B296D6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8B6D39A315282F1800B296D6 /* InfoPlist.strings */; }; - 8B6D39A815282F1800B296D6 /* FTASyncDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6D39A715282F1800B296D6 /* FTASyncDemoTests.m */; }; + 8B6D39A815282F1800B296D6 /* FTASyncTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6D39A715282F1800B296D6 /* FTASyncTests.m */; }; 8B6D39B21528313900B296D6 /* DefaultPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8B6D39B11528313900B296D6 /* DefaultPrefs.plist */; }; 8B6D39EE1528379F00B296D6 /* FTASyncDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 8B6D39EC1528379F00B296D6 /* FTASyncDemo.xcdatamodeld */; }; 8B6D3A0115283DFC00B296D6 /* _ToDoItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6D39FE15283DFC00B296D6 /* _ToDoItem.m */; }; @@ -93,6 +66,39 @@ 8B7A2644156090C8006FB602 /* FTASelectionTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B7A2643156090C8006FB602 /* FTASelectionTableViewController.m */; }; 8B937B29157AC84C00FA3E39 /* NPReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B937B28157AC84C00FA3E39 /* NPReachability.m */; }; 8B937B2D157BDDF800FA3E39 /* FTASyncParent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B937B2C157BDDF800FA3E39 /* FTASyncParent.m */; }; + B101F1461783B87A00A529C1 /* MagicalImportFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F10E1783B87A00A529C1 /* MagicalImportFunctions.m */; }; + B101F1471783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1101783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.m */; }; + B101F1481783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1121783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.m */; }; + B101F1491783B87A00A529C1 /* NSNumber+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1141783B87A00A529C1 /* NSNumber+MagicalDataImport.m */; }; + B101F14A1783B87A00A529C1 /* NSObject+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1161783B87A00A529C1 /* NSObject+MagicalDataImport.m */; }; + B101F14B1783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1181783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.m */; }; + B101F14C1783B87A00A529C1 /* NSString+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F11A1783B87A00A529C1 /* NSString+MagicalDataImport.m */; }; + B101F14D1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F11D1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.m */; }; + B101F14E1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F11F1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.m */; }; + B101F14F1783B87A00A529C1 /* NSManagedObject+MagicalFinders.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1211783B87A00A529C1 /* NSManagedObject+MagicalFinders.m */; }; + B101F1501783B87A00A529C1 /* NSManagedObject+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1231783B87A00A529C1 /* NSManagedObject+MagicalRecord.m */; }; + B101F1511783B87A00A529C1 /* NSManagedObject+MagicalRequests.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1251783B87A00A529C1 /* NSManagedObject+MagicalRequests.m */; }; + B101F1521783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1281783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.m */; }; + B101F1531783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F12A1783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.m */; }; + B101F1541783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F12C1783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.m */; }; + B101F1551783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F12E1783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.m */; }; + B101F1561783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1301783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.m */; }; + B101F1571783B87A00A529C1 /* NSPersistentStore+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1321783B87A00A529C1 /* NSPersistentStore+MagicalRecord.m */; }; + B101F1581783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1341783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.m */; }; + B101F1591783B87A00A529C1 /* MagicalRecord+Actions.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1371783B87A00A529C1 /* MagicalRecord+Actions.m */; }; + B101F15A1783B87A00A529C1 /* MagicalRecord+ErrorHandling.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1391783B87A00A529C1 /* MagicalRecord+ErrorHandling.m */; }; + B101F15B1783B87A00A529C1 /* MagicalRecord+iCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F13B1783B87A00A529C1 /* MagicalRecord+iCloud.m */; }; + B101F15C1783B87A00A529C1 /* MagicalRecord+Options.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F13D1783B87A00A529C1 /* MagicalRecord+Options.m */; }; + B101F15D1783B87A00A529C1 /* MagicalRecord+Setup.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F13F1783B87A00A529C1 /* MagicalRecord+Setup.m */; }; + B101F15E1783B87A00A529C1 /* MagicalRecord+ShorthandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1411783B87A00A529C1 /* MagicalRecord+ShorthandSupport.m */; }; + B101F15F1783B87A00A529C1 /* MagicalRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B101F1431783B87A00A529C1 /* MagicalRecord.m */; }; + B1C4057B1783F44100339D27 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B6D3A0F1528447800B296D6 /* CoreData.framework */; }; + B1C4058017848AF100339D27 /* Parse.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C4057E17848A7F00339D27 /* Parse.framework */; }; + B1C4058117848B0100339D27 /* Parse.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C4057E17848A7F00339D27 /* Parse.framework */; }; + B1C4058317848B9200339D27 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C4058217848B9100339D27 /* CoreLocation.framework */; }; + C406A7881794107200654391 /* parse_large.png in Resources */ = {isa = PBXBuildFile; fileRef = C406A7851794107200654391 /* parse_large.png */; }; + C406A7891794107200654391 /* parse_medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C406A7861794107200654391 /* parse_medium.png */; }; + C406A78A1794107200654391 /* parse_small.png in Resources */ = {isa = PBXBuildFile; fileRef = C406A7871794107200654391 /* parse_small.png */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -111,64 +117,9 @@ 496E58F2160ABFFE00BC00B5 /* _AbstractPerson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _AbstractPerson.m; sourceTree = ""; }; 496E58F3160ABFFE00BC00B5 /* AbstractPerson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPerson.h; sourceTree = ""; }; 496E58F4160ABFFE00BC00B5 /* AbstractPerson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AbstractPerson.m; sourceTree = ""; }; - 496E5B58160AE7D400BC00B5 /* MagicalImportFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalImportFunctions.h; sourceTree = ""; }; - 496E5B59160AE7D400BC00B5 /* MagicalImportFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MagicalImportFunctions.m; sourceTree = ""; }; - 496E5B5A160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributeDescription+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B5B160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributeDescription+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B5C160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSEntityDescription+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B5D160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSEntityDescription+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B5E160AE7D400BC00B5 /* NSNumber+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B5F160AE7D400BC00B5 /* NSNumber+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNumber+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B60160AE7D400BC00B5 /* NSObject+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B61160AE7D400BC00B5 /* NSObject+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B62160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSRelationshipDescription+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B63160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSRelationshipDescription+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B64160AE7D400BC00B5 /* NSString+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B65160AE7D400BC00B5 /* NSString+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B67160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalAggregation.h"; sourceTree = ""; }; - 496E5B68160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalAggregation.m"; sourceTree = ""; }; - 496E5B69160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalDataImport.h"; sourceTree = ""; }; - 496E5B6A160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalDataImport.m"; sourceTree = ""; }; - 496E5B6B160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalFinders.h"; sourceTree = ""; }; - 496E5B6C160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalFinders.m"; sourceTree = ""; }; - 496E5B6D160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalRecord.h"; sourceTree = ""; }; - 496E5B6E160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalRecord.m"; sourceTree = ""; }; - 496E5B6F160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalRequests.h"; sourceTree = ""; }; - 496E5B70160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalRequests.m"; sourceTree = ""; }; - 496E5B72160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalObserving.h"; sourceTree = ""; }; - 496E5B73160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalObserving.m"; sourceTree = ""; }; - 496E5B74160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalRecord.h"; sourceTree = ""; }; - 496E5B75160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalRecord.m"; sourceTree = ""; }; - 496E5B76160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalSaves.h"; sourceTree = ""; }; - 496E5B77160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalSaves.m"; sourceTree = ""; }; - 496E5B78160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalThreading.h"; sourceTree = ""; }; - 496E5B79160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalThreading.m"; sourceTree = ""; }; - 496E5B7A160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectModel+MagicalRecord.h"; sourceTree = ""; }; - 496E5B7B160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectModel+MagicalRecord.m"; sourceTree = ""; }; - 496E5B7C160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStore+MagicalRecord.h"; sourceTree = ""; }; - 496E5B7D160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPersistentStore+MagicalRecord.m"; sourceTree = ""; }; - 496E5B7E160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStoreCoordinator+MagicalRecord.h"; sourceTree = ""; }; - 496E5B7F160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPersistentStoreCoordinator+MagicalRecord.m"; sourceTree = ""; }; - 496E5B81160AE7D400BC00B5 /* MagicalRecord+Actions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Actions.h"; sourceTree = ""; }; - 496E5B82160AE7D400BC00B5 /* MagicalRecord+Actions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Actions.m"; sourceTree = ""; }; - 496E5B83160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+ErrorHandling.h"; sourceTree = ""; }; - 496E5B84160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+ErrorHandling.m"; sourceTree = ""; }; - 496E5B85160AE7D400BC00B5 /* MagicalRecord+iCloud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+iCloud.h"; sourceTree = ""; }; - 496E5B86160AE7D400BC00B5 /* MagicalRecord+iCloud.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+iCloud.m"; sourceTree = ""; }; - 496E5B87160AE7D400BC00B5 /* MagicalRecord+Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Options.h"; sourceTree = ""; }; - 496E5B88160AE7D400BC00B5 /* MagicalRecord+Options.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Options.m"; sourceTree = ""; }; - 496E5B89160AE7D400BC00B5 /* MagicalRecord+Setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Setup.h"; sourceTree = ""; }; - 496E5B8A160AE7D400BC00B5 /* MagicalRecord+Setup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Setup.m"; sourceTree = ""; }; - 496E5B8B160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+ShorthandSupport.h"; sourceTree = ""; }; - 496E5B8C160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+ShorthandSupport.m"; sourceTree = ""; }; - 496E5B8D160AE7D400BC00B5 /* MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalRecord.h; sourceTree = ""; }; - 496E5B8E160AE7D400BC00B5 /* MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MagicalRecord.m; sourceTree = ""; }; - 496E5B8F160AE7D400BC00B5 /* MagicalRecordShorthand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalRecordShorthand.h; sourceTree = ""; }; - 496E5B90160AE7D400BC00B5 /* CoreData+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CoreData+MagicalRecord.h"; sourceTree = ""; }; 8B22B7E815C2DFC800F01B27 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = ""; }; 8B345362157C2B4200725E14 /* FTASetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FTASetupViewController.h; sourceTree = ""; }; 8B345363157C2B4200725E14 /* FTASetupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FTASetupViewController.m; sourceTree = ""; }; - 8B5AFC4F152D1797000AF428 /* Parse.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Parse.framework; sourceTree = ""; }; 8B5AFC51152D17C6000AF428 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 8B5AFC53152D17D1000AF428 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 8B5AFC55152D17DD000AF428 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; @@ -198,8 +149,8 @@ 8B6D399A15282F1800B296D6 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 8B6D39A215282F1800B296D6 /* FTASyncDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FTASyncDemoTests-Info.plist"; sourceTree = ""; }; 8B6D39A415282F1800B296D6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 8B6D39A615282F1800B296D6 /* FTASyncDemoTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTASyncDemoTests.h; sourceTree = ""; }; - 8B6D39A715282F1800B296D6 /* FTASyncDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTASyncDemoTests.m; sourceTree = ""; }; + 8B6D39A615282F1800B296D6 /* FTASyncTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTASyncTests.h; sourceTree = ""; }; + 8B6D39A715282F1800B296D6 /* FTASyncTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTASyncTests.m; sourceTree = ""; }; 8B6D39B11528313900B296D6 /* DefaultPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DefaultPrefs.plist; sourceTree = ""; }; 8B6D39ED1528379F00B296D6 /* FTASyncDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FTASyncDemo.xcdatamodel; sourceTree = ""; }; 8B6D39FD15283DFC00B296D6 /* _ToDoItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ToDoItem.h; sourceTree = ""; }; @@ -232,7 +183,66 @@ 8B937B28157AC84C00FA3E39 /* NPReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NPReachability.m; sourceTree = ""; }; 8B937B2B157BDDF800FA3E39 /* FTASyncParent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTASyncParent.h; path = ../../../Source/FTASyncParent.h; sourceTree = ""; }; 8B937B2C157BDDF800FA3E39 /* FTASyncParent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTASyncParent.m; path = ../../../Source/FTASyncParent.m; sourceTree = ""; }; - 8B937B2E157BE38000FA3E39 /* ParseKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKeys.h; sourceTree = ""; }; + B101F1091783176E00A529C1 /* ParseKeys.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseKeys.h; sourceTree = ""; }; + B101F10D1783B87A00A529C1 /* MagicalImportFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalImportFunctions.h; sourceTree = ""; }; + B101F10E1783B87A00A529C1 /* MagicalImportFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MagicalImportFunctions.m; sourceTree = ""; }; + B101F10F1783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributeDescription+MagicalDataImport.h"; sourceTree = ""; }; + B101F1101783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributeDescription+MagicalDataImport.m"; sourceTree = ""; }; + B101F1111783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSEntityDescription+MagicalDataImport.h"; sourceTree = ""; }; + B101F1121783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSEntityDescription+MagicalDataImport.m"; sourceTree = ""; }; + B101F1131783B87A00A529C1 /* NSNumber+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+MagicalDataImport.h"; sourceTree = ""; }; + B101F1141783B87A00A529C1 /* NSNumber+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNumber+MagicalDataImport.m"; sourceTree = ""; }; + B101F1151783B87A00A529C1 /* NSObject+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MagicalDataImport.h"; sourceTree = ""; }; + B101F1161783B87A00A529C1 /* NSObject+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MagicalDataImport.m"; sourceTree = ""; }; + B101F1171783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSRelationshipDescription+MagicalDataImport.h"; sourceTree = ""; }; + B101F1181783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSRelationshipDescription+MagicalDataImport.m"; sourceTree = ""; }; + B101F1191783B87A00A529C1 /* NSString+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MagicalDataImport.h"; sourceTree = ""; }; + B101F11A1783B87A00A529C1 /* NSString+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MagicalDataImport.m"; sourceTree = ""; }; + B101F11C1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalAggregation.h"; sourceTree = ""; }; + B101F11D1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalAggregation.m"; sourceTree = ""; }; + B101F11E1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalDataImport.h"; sourceTree = ""; }; + B101F11F1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalDataImport.m"; sourceTree = ""; }; + B101F1201783B87A00A529C1 /* NSManagedObject+MagicalFinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalFinders.h"; sourceTree = ""; }; + B101F1211783B87A00A529C1 /* NSManagedObject+MagicalFinders.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalFinders.m"; sourceTree = ""; }; + B101F1221783B87A00A529C1 /* NSManagedObject+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalRecord.h"; sourceTree = ""; }; + B101F1231783B87A00A529C1 /* NSManagedObject+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalRecord.m"; sourceTree = ""; }; + B101F1241783B87A00A529C1 /* NSManagedObject+MagicalRequests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+MagicalRequests.h"; sourceTree = ""; }; + B101F1251783B87A00A529C1 /* NSManagedObject+MagicalRequests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+MagicalRequests.m"; sourceTree = ""; }; + B101F1271783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalObserving.h"; sourceTree = ""; }; + B101F1281783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalObserving.m"; sourceTree = ""; }; + B101F1291783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalRecord.h"; sourceTree = ""; }; + B101F12A1783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalRecord.m"; sourceTree = ""; }; + B101F12B1783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalSaves.h"; sourceTree = ""; }; + B101F12C1783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalSaves.m"; sourceTree = ""; }; + B101F12D1783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+MagicalThreading.h"; sourceTree = ""; }; + B101F12E1783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+MagicalThreading.m"; sourceTree = ""; }; + B101F12F1783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectModel+MagicalRecord.h"; sourceTree = ""; }; + B101F1301783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectModel+MagicalRecord.m"; sourceTree = ""; }; + B101F1311783B87A00A529C1 /* NSPersistentStore+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStore+MagicalRecord.h"; sourceTree = ""; }; + B101F1321783B87A00A529C1 /* NSPersistentStore+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPersistentStore+MagicalRecord.m"; sourceTree = ""; }; + B101F1331783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStoreCoordinator+MagicalRecord.h"; sourceTree = ""; }; + B101F1341783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPersistentStoreCoordinator+MagicalRecord.m"; sourceTree = ""; }; + B101F1361783B87A00A529C1 /* MagicalRecord+Actions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Actions.h"; sourceTree = ""; }; + B101F1371783B87A00A529C1 /* MagicalRecord+Actions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Actions.m"; sourceTree = ""; }; + B101F1381783B87A00A529C1 /* MagicalRecord+ErrorHandling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+ErrorHandling.h"; sourceTree = ""; }; + B101F1391783B87A00A529C1 /* MagicalRecord+ErrorHandling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+ErrorHandling.m"; sourceTree = ""; }; + B101F13A1783B87A00A529C1 /* MagicalRecord+iCloud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+iCloud.h"; sourceTree = ""; }; + B101F13B1783B87A00A529C1 /* MagicalRecord+iCloud.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+iCloud.m"; sourceTree = ""; }; + B101F13C1783B87A00A529C1 /* MagicalRecord+Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Options.h"; sourceTree = ""; }; + B101F13D1783B87A00A529C1 /* MagicalRecord+Options.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Options.m"; sourceTree = ""; }; + B101F13E1783B87A00A529C1 /* MagicalRecord+Setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+Setup.h"; sourceTree = ""; }; + B101F13F1783B87A00A529C1 /* MagicalRecord+Setup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+Setup.m"; sourceTree = ""; }; + B101F1401783B87A00A529C1 /* MagicalRecord+ShorthandSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MagicalRecord+ShorthandSupport.h"; sourceTree = ""; }; + B101F1411783B87A00A529C1 /* MagicalRecord+ShorthandSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MagicalRecord+ShorthandSupport.m"; sourceTree = ""; }; + B101F1421783B87A00A529C1 /* MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalRecord.h; sourceTree = ""; }; + B101F1431783B87A00A529C1 /* MagicalRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MagicalRecord.m; sourceTree = ""; }; + B101F1441783B87A00A529C1 /* MagicalRecordShorthand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalRecordShorthand.h; sourceTree = ""; }; + B101F1451783B87A00A529C1 /* CoreData+MagicalRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CoreData+MagicalRecord.h"; sourceTree = ""; }; + B1C4057E17848A7F00339D27 /* Parse.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Parse.framework; sourceTree = ""; }; + B1C4058217848B9100339D27 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + C406A7851794107200654391 /* parse_large.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = parse_large.png; sourceTree = ""; }; + C406A7861794107200654391 /* parse_medium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = parse_medium.png; sourceTree = ""; }; + C406A7871794107200654391 /* parse_small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = parse_small.png; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -240,6 +250,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B1C4058317848B9200339D27 /* CoreLocation.framework in Frameworks */, + B1C4058017848AF100339D27 /* Parse.framework in Frameworks */, 8B5AFC5E152D181F000AF428 /* QuartzCore.framework in Frameworks */, 8B5AFC5C152D180D000AF428 /* Security.framework in Frameworks */, 8B5AFC5A152D17FE000AF428 /* libz.1.1.3.dylib in Frameworks */, @@ -251,7 +263,6 @@ 8B6D397D15282F1800B296D6 /* UIKit.framework in Frameworks */, 8B6D397F15282F1800B296D6 /* Foundation.framework in Frameworks */, 8B6D3A101528447800B296D6 /* CoreData.framework in Frameworks */, - 8B5AFC50152D1797000AF428 /* Parse.framework in Frameworks */, 8B22B7E915C2DFC800F01B27 /* Crashlytics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -260,6 +271,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B1C4058117848B0100339D27 /* Parse.framework in Frameworks */, + B1C4057B1783F44100339D27 /* CoreData.framework in Frameworks */, 8B6D399B15282F1800B296D6 /* SenTestingKit.framework in Frameworks */, 8B6D399C15282F1800B296D6 /* UIKit.framework in Frameworks */, 8B6D399D15282F1800B296D6 /* Foundation.framework in Frameworks */, @@ -272,102 +285,12 @@ 496E5B55160AE7D400BC00B5 /* MagicalRecord */ = { isa = PBXGroup; children = ( - 496E5B56160AE7D400BC00B5 /* Categories */, - 496E5B80160AE7D400BC00B5 /* Core */, - 496E5B90160AE7D400BC00B5 /* CoreData+MagicalRecord.h */, + B101F10B1783B87A00A529C1 /* Categories */, + B101F1351783B87A00A529C1 /* Core */, + B101F1451783B87A00A529C1 /* CoreData+MagicalRecord.h */, ); - path = MagicalRecord; - sourceTree = ""; - }; - 496E5B56160AE7D400BC00B5 /* Categories */ = { - isa = PBXGroup; - children = ( - 496E5B57160AE7D400BC00B5 /* DataImport */, - 496E5B66160AE7D400BC00B5 /* NSManagedObject */, - 496E5B71160AE7D400BC00B5 /* NSManagedObjectContext */, - 496E5B7A160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.h */, - 496E5B7B160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.m */, - 496E5B7C160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.h */, - 496E5B7D160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.m */, - 496E5B7E160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.h */, - 496E5B7F160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.m */, - ); - path = Categories; - sourceTree = ""; - }; - 496E5B57160AE7D400BC00B5 /* DataImport */ = { - isa = PBXGroup; - children = ( - 496E5B58160AE7D400BC00B5 /* MagicalImportFunctions.h */, - 496E5B59160AE7D400BC00B5 /* MagicalImportFunctions.m */, - 496E5B5A160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.h */, - 496E5B5B160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.m */, - 496E5B5C160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.h */, - 496E5B5D160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.m */, - 496E5B5E160AE7D400BC00B5 /* NSNumber+MagicalDataImport.h */, - 496E5B5F160AE7D400BC00B5 /* NSNumber+MagicalDataImport.m */, - 496E5B60160AE7D400BC00B5 /* NSObject+MagicalDataImport.h */, - 496E5B61160AE7D400BC00B5 /* NSObject+MagicalDataImport.m */, - 496E5B62160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.h */, - 496E5B63160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.m */, - 496E5B64160AE7D400BC00B5 /* NSString+MagicalDataImport.h */, - 496E5B65160AE7D400BC00B5 /* NSString+MagicalDataImport.m */, - ); - path = DataImport; - sourceTree = ""; - }; - 496E5B66160AE7D400BC00B5 /* NSManagedObject */ = { - isa = PBXGroup; - children = ( - 496E5B67160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.h */, - 496E5B68160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.m */, - 496E5B69160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.h */, - 496E5B6A160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.m */, - 496E5B6B160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.h */, - 496E5B6C160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.m */, - 496E5B6D160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.h */, - 496E5B6E160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.m */, - 496E5B6F160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.h */, - 496E5B70160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.m */, - ); - path = NSManagedObject; - sourceTree = ""; - }; - 496E5B71160AE7D400BC00B5 /* NSManagedObjectContext */ = { - isa = PBXGroup; - children = ( - 496E5B72160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.h */, - 496E5B73160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.m */, - 496E5B74160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.h */, - 496E5B75160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.m */, - 496E5B76160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.h */, - 496E5B77160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.m */, - 496E5B78160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.h */, - 496E5B79160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.m */, - ); - path = NSManagedObjectContext; - sourceTree = ""; - }; - 496E5B80160AE7D400BC00B5 /* Core */ = { - isa = PBXGroup; - children = ( - 496E5B81160AE7D400BC00B5 /* MagicalRecord+Actions.h */, - 496E5B82160AE7D400BC00B5 /* MagicalRecord+Actions.m */, - 496E5B83160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.h */, - 496E5B84160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.m */, - 496E5B85160AE7D400BC00B5 /* MagicalRecord+iCloud.h */, - 496E5B86160AE7D400BC00B5 /* MagicalRecord+iCloud.m */, - 496E5B87160AE7D400BC00B5 /* MagicalRecord+Options.h */, - 496E5B88160AE7D400BC00B5 /* MagicalRecord+Options.m */, - 496E5B89160AE7D400BC00B5 /* MagicalRecord+Setup.h */, - 496E5B8A160AE7D400BC00B5 /* MagicalRecord+Setup.m */, - 496E5B8B160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.h */, - 496E5B8C160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.m */, - 496E5B8D160AE7D400BC00B5 /* MagicalRecord.h */, - 496E5B8E160AE7D400BC00B5 /* MagicalRecord.m */, - 496E5B8F160AE7D400BC00B5 /* MagicalRecordShorthand.h */, - ); - path = Core; + name = MagicalRecord; + path = ../../../MagicalRecord/MagicalRecord; sourceTree = ""; }; 8B5AFC35152D137D000AF428 /* FTASync */ = { @@ -386,6 +309,7 @@ 8B6D396D15282F1700B296D6 = { isa = PBXGroup; children = ( + B1C4058217848B9100339D27 /* CoreLocation.framework */, 8B6D398215282F1800B296D6 /* FTASyncDemo */, 8B6D39A015282F1800B296D6 /* FTASyncDemoTests */, 8B6D397B15282F1700B296D6 /* Frameworks */, @@ -405,6 +329,7 @@ 8B6D397B15282F1700B296D6 /* Frameworks */ = { isa = PBXGroup; children = ( + B1C4057E17848A7F00339D27 /* Parse.framework */, 8B22B7E815C2DFC800F01B27 /* Crashlytics.framework */, 8B5AFC5D152D181F000AF428 /* QuartzCore.framework */, 8B5AFC5B152D180D000AF428 /* Security.framework */, @@ -413,7 +338,6 @@ 8B5AFC55152D17DD000AF428 /* SystemConfiguration.framework */, 8B5AFC53152D17D1000AF428 /* CFNetwork.framework */, 8B5AFC51152D17C6000AF428 /* AudioToolbox.framework */, - 8B5AFC4F152D1797000AF428 /* Parse.framework */, 8B6D3A0F1528447800B296D6 /* CoreData.framework */, 8B6D397C15282F1800B296D6 /* UIKit.framework */, 8B6D397E15282F1800B296D6 /* Foundation.framework */, @@ -459,7 +383,7 @@ 8B6D398815282F1800B296D6 /* main.m */, 8B6D398A15282F1800B296D6 /* FTASyncDemo-Prefix.pch */, 8B6D39B11528313900B296D6 /* DefaultPrefs.plist */, - 8B937B2E157BE38000FA3E39 /* ParseKeys.h */, + B101F1091783176E00A529C1 /* ParseKeys.h */, ); name = "Supporting Files"; sourceTree = ""; @@ -467,8 +391,8 @@ 8B6D39A015282F1800B296D6 /* FTASyncDemoTests */ = { isa = PBXGroup; children = ( - 8B6D39A615282F1800B296D6 /* FTASyncDemoTests.h */, - 8B6D39A715282F1800B296D6 /* FTASyncDemoTests.m */, + 8B6D39A615282F1800B296D6 /* FTASyncTests.h */, + 8B6D39A715282F1800B296D6 /* FTASyncTests.m */, 8B6D39A115282F1800B296D6 /* Supporting Files */, ); path = FTASyncDemoTests; @@ -521,6 +445,9 @@ 8B7A263B15608327006FB602 /* Resources */ = { isa = PBXGroup; children = ( + C406A7851794107200654391 /* parse_large.png */, + C406A7861794107200654391 /* parse_medium.png */, + C406A7871794107200654391 /* parse_small.png */, 8B7A263C15608327006FB602 /* preview.png */, 8B7A263D15608327006FB602 /* setup.png */, 8B7A263E15608327006FB602 /* user.png */, @@ -537,6 +464,97 @@ path = NPReachability; sourceTree = ""; }; + B101F10B1783B87A00A529C1 /* Categories */ = { + isa = PBXGroup; + children = ( + B101F10C1783B87A00A529C1 /* DataImport */, + B101F11B1783B87A00A529C1 /* NSManagedObject */, + B101F1261783B87A00A529C1 /* NSManagedObjectContext */, + B101F12F1783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.h */, + B101F1301783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.m */, + B101F1311783B87A00A529C1 /* NSPersistentStore+MagicalRecord.h */, + B101F1321783B87A00A529C1 /* NSPersistentStore+MagicalRecord.m */, + B101F1331783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.h */, + B101F1341783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.m */, + ); + path = Categories; + sourceTree = ""; + }; + B101F10C1783B87A00A529C1 /* DataImport */ = { + isa = PBXGroup; + children = ( + B101F10D1783B87A00A529C1 /* MagicalImportFunctions.h */, + B101F10E1783B87A00A529C1 /* MagicalImportFunctions.m */, + B101F10F1783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.h */, + B101F1101783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.m */, + B101F1111783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.h */, + B101F1121783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.m */, + B101F1131783B87A00A529C1 /* NSNumber+MagicalDataImport.h */, + B101F1141783B87A00A529C1 /* NSNumber+MagicalDataImport.m */, + B101F1151783B87A00A529C1 /* NSObject+MagicalDataImport.h */, + B101F1161783B87A00A529C1 /* NSObject+MagicalDataImport.m */, + B101F1171783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.h */, + B101F1181783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.m */, + B101F1191783B87A00A529C1 /* NSString+MagicalDataImport.h */, + B101F11A1783B87A00A529C1 /* NSString+MagicalDataImport.m */, + ); + path = DataImport; + sourceTree = ""; + }; + B101F11B1783B87A00A529C1 /* NSManagedObject */ = { + isa = PBXGroup; + children = ( + B101F11C1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.h */, + B101F11D1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.m */, + B101F11E1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.h */, + B101F11F1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.m */, + B101F1201783B87A00A529C1 /* NSManagedObject+MagicalFinders.h */, + B101F1211783B87A00A529C1 /* NSManagedObject+MagicalFinders.m */, + B101F1221783B87A00A529C1 /* NSManagedObject+MagicalRecord.h */, + B101F1231783B87A00A529C1 /* NSManagedObject+MagicalRecord.m */, + B101F1241783B87A00A529C1 /* NSManagedObject+MagicalRequests.h */, + B101F1251783B87A00A529C1 /* NSManagedObject+MagicalRequests.m */, + ); + path = NSManagedObject; + sourceTree = ""; + }; + B101F1261783B87A00A529C1 /* NSManagedObjectContext */ = { + isa = PBXGroup; + children = ( + B101F1271783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.h */, + B101F1281783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.m */, + B101F1291783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.h */, + B101F12A1783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.m */, + B101F12B1783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.h */, + B101F12C1783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.m */, + B101F12D1783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.h */, + B101F12E1783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.m */, + ); + path = NSManagedObjectContext; + sourceTree = ""; + }; + B101F1351783B87A00A529C1 /* Core */ = { + isa = PBXGroup; + children = ( + B101F1361783B87A00A529C1 /* MagicalRecord+Actions.h */, + B101F1371783B87A00A529C1 /* MagicalRecord+Actions.m */, + B101F1381783B87A00A529C1 /* MagicalRecord+ErrorHandling.h */, + B101F1391783B87A00A529C1 /* MagicalRecord+ErrorHandling.m */, + B101F13A1783B87A00A529C1 /* MagicalRecord+iCloud.h */, + B101F13B1783B87A00A529C1 /* MagicalRecord+iCloud.m */, + B101F13C1783B87A00A529C1 /* MagicalRecord+Options.h */, + B101F13D1783B87A00A529C1 /* MagicalRecord+Options.m */, + B101F13E1783B87A00A529C1 /* MagicalRecord+Setup.h */, + B101F13F1783B87A00A529C1 /* MagicalRecord+Setup.m */, + B101F1401783B87A00A529C1 /* MagicalRecord+ShorthandSupport.h */, + B101F1411783B87A00A529C1 /* MagicalRecord+ShorthandSupport.m */, + B101F1421783B87A00A529C1 /* MagicalRecord.h */, + B101F1431783B87A00A529C1 /* MagicalRecord.m */, + B101F1441783B87A00A529C1 /* MagicalRecordShorthand.h */, + ); + path = Core; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -618,6 +636,9 @@ 8B7A263F15608327006FB602 /* preview.png in Resources */, 8B7A264015608327006FB602 /* setup.png in Resources */, 8B7A264115608327006FB602 /* user.png in Resources */, + C406A7881794107200654391 /* parse_large.png in Resources */, + C406A7891794107200654391 /* parse_medium.png in Resources */, + C406A78A1794107200654391 /* parse_small.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -698,32 +719,32 @@ 8B345364157C2B4200725E14 /* FTASetupViewController.m in Sources */, 496E58F5160ABFFE00BC00B5 /* _AbstractPerson.m in Sources */, 496E58F6160ABFFE00BC00B5 /* AbstractPerson.m in Sources */, - 496E5B91160AE7D400BC00B5 /* MagicalImportFunctions.m in Sources */, - 496E5B92160AE7D400BC00B5 /* NSAttributeDescription+MagicalDataImport.m in Sources */, - 496E5B93160AE7D400BC00B5 /* NSEntityDescription+MagicalDataImport.m in Sources */, - 496E5B94160AE7D400BC00B5 /* NSNumber+MagicalDataImport.m in Sources */, - 496E5B95160AE7D400BC00B5 /* NSObject+MagicalDataImport.m in Sources */, - 496E5B96160AE7D400BC00B5 /* NSRelationshipDescription+MagicalDataImport.m in Sources */, - 496E5B97160AE7D400BC00B5 /* NSString+MagicalDataImport.m in Sources */, - 496E5B98160AE7D400BC00B5 /* NSManagedObject+MagicalAggregation.m in Sources */, - 496E5B99160AE7D400BC00B5 /* NSManagedObject+MagicalDataImport.m in Sources */, - 496E5B9A160AE7D400BC00B5 /* NSManagedObject+MagicalFinders.m in Sources */, - 496E5B9B160AE7D400BC00B5 /* NSManagedObject+MagicalRecord.m in Sources */, - 496E5B9C160AE7D400BC00B5 /* NSManagedObject+MagicalRequests.m in Sources */, - 496E5B9D160AE7D400BC00B5 /* NSManagedObjectContext+MagicalObserving.m in Sources */, - 496E5B9E160AE7D400BC00B5 /* NSManagedObjectContext+MagicalRecord.m in Sources */, - 496E5B9F160AE7D400BC00B5 /* NSManagedObjectContext+MagicalSaves.m in Sources */, - 496E5BA0160AE7D400BC00B5 /* NSManagedObjectContext+MagicalThreading.m in Sources */, - 496E5BA1160AE7D400BC00B5 /* NSManagedObjectModel+MagicalRecord.m in Sources */, - 496E5BA2160AE7D400BC00B5 /* NSPersistentStore+MagicalRecord.m in Sources */, - 496E5BA3160AE7D400BC00B5 /* NSPersistentStoreCoordinator+MagicalRecord.m in Sources */, - 496E5BA4160AE7D400BC00B5 /* MagicalRecord+Actions.m in Sources */, - 496E5BA5160AE7D400BC00B5 /* MagicalRecord+ErrorHandling.m in Sources */, - 496E5BA6160AE7D400BC00B5 /* MagicalRecord+iCloud.m in Sources */, - 496E5BA7160AE7D400BC00B5 /* MagicalRecord+Options.m in Sources */, - 496E5BA8160AE7D400BC00B5 /* MagicalRecord+Setup.m in Sources */, - 496E5BA9160AE7D400BC00B5 /* MagicalRecord+ShorthandSupport.m in Sources */, - 496E5BAA160AE7D400BC00B5 /* MagicalRecord.m in Sources */, + B101F1461783B87A00A529C1 /* MagicalImportFunctions.m in Sources */, + B101F1471783B87A00A529C1 /* NSAttributeDescription+MagicalDataImport.m in Sources */, + B101F1481783B87A00A529C1 /* NSEntityDescription+MagicalDataImport.m in Sources */, + B101F1491783B87A00A529C1 /* NSNumber+MagicalDataImport.m in Sources */, + B101F14A1783B87A00A529C1 /* NSObject+MagicalDataImport.m in Sources */, + B101F14B1783B87A00A529C1 /* NSRelationshipDescription+MagicalDataImport.m in Sources */, + B101F14C1783B87A00A529C1 /* NSString+MagicalDataImport.m in Sources */, + B101F14D1783B87A00A529C1 /* NSManagedObject+MagicalAggregation.m in Sources */, + B101F14E1783B87A00A529C1 /* NSManagedObject+MagicalDataImport.m in Sources */, + B101F14F1783B87A00A529C1 /* NSManagedObject+MagicalFinders.m in Sources */, + B101F1501783B87A00A529C1 /* NSManagedObject+MagicalRecord.m in Sources */, + B101F1511783B87A00A529C1 /* NSManagedObject+MagicalRequests.m in Sources */, + B101F1521783B87A00A529C1 /* NSManagedObjectContext+MagicalObserving.m in Sources */, + B101F1531783B87A00A529C1 /* NSManagedObjectContext+MagicalRecord.m in Sources */, + B101F1541783B87A00A529C1 /* NSManagedObjectContext+MagicalSaves.m in Sources */, + B101F1551783B87A00A529C1 /* NSManagedObjectContext+MagicalThreading.m in Sources */, + B101F1561783B87A00A529C1 /* NSManagedObjectModel+MagicalRecord.m in Sources */, + B101F1571783B87A00A529C1 /* NSPersistentStore+MagicalRecord.m in Sources */, + B101F1581783B87A00A529C1 /* NSPersistentStoreCoordinator+MagicalRecord.m in Sources */, + B101F1591783B87A00A529C1 /* MagicalRecord+Actions.m in Sources */, + B101F15A1783B87A00A529C1 /* MagicalRecord+ErrorHandling.m in Sources */, + B101F15B1783B87A00A529C1 /* MagicalRecord+iCloud.m in Sources */, + B101F15C1783B87A00A529C1 /* MagicalRecord+Options.m in Sources */, + B101F15D1783B87A00A529C1 /* MagicalRecord+Setup.m in Sources */, + B101F15E1783B87A00A529C1 /* MagicalRecord+ShorthandSupport.m in Sources */, + B101F15F1783B87A00A529C1 /* MagicalRecord.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -731,7 +752,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8B6D39A815282F1800B296D6 /* FTASyncDemoTests.m in Sources */, + 8B6D39A815282F1800B296D6 /* FTASyncTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -818,6 +839,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", + "\"$(SRCROOT)/../../../../Downloads\"", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FTASyncDemo/FTASyncDemo-Prefix.pch"; @@ -835,6 +857,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", + "\"$(SRCROOT)/../../../../Downloads\"", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FTASyncDemo/FTASyncDemo-Prefix.pch"; @@ -851,6 +874,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(DEVELOPER_LIBRARY_DIR)/Frameworks", + "\"$(SRCROOT)\"", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FTASyncDemo/FTASyncDemo-Prefix.pch"; @@ -868,6 +892,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(DEVELOPER_LIBRARY_DIR)/Frameworks", + "\"$(SRCROOT)\"", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FTASyncDemo/FTASyncDemo-Prefix.pch"; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/FTASyncDemo.xcdatamodeld/FTASyncDemo3.xcdatamodel/contents b/FTASyncDemo/FTASyncDemo/DataClasses/FTASyncDemo.xcdatamodeld/FTASyncDemo3.xcdatamodel/contents index b67c92b..7d43a3a 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/FTASyncDemo.xcdatamodeld/FTASyncDemo3.xcdatamodel/contents +++ b/FTASyncDemo/FTASyncDemo/DataClasses/FTASyncDemo.xcdatamodeld/FTASyncDemo3.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -26,6 +26,7 @@ + @@ -41,9 +42,9 @@ - + - + \ No newline at end of file diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.h b/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.h index 84696dd..9d95185 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.h +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.h @@ -29,7 +29,9 @@ extern const struct AbstractPersonFetchedProperties { -@property (nonatomic, strong) NSString *name; + +@property (nonatomic, strong) NSString* name; + //- (BOOL)validateName:(id*)value_ error:(NSError**)error_; @@ -48,8 +50,8 @@ extern const struct AbstractPersonFetchedProperties { @interface _AbstractPerson (CoreDataGeneratedPrimitiveAccessors) -- (NSString *)primitiveName; -- (void)setPrimitiveName:(NSString *)value; +- (NSString*)primitiveName; +- (void)setPrimitiveName:(NSString*)value; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.m b/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.m index 55bc110..8e980a7 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.m +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_AbstractPerson.m @@ -36,7 +36,7 @@ - (AbstractPersonID*)objectID { return (AbstractPersonID*)[super objectID]; } -+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.h b/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.h index 74c02b9..2569f58 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.h +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.h @@ -5,6 +5,7 @@ extern const struct FTASyncParentAttributes { + __unsafe_unretained NSString *createdAt; __unsafe_unretained NSString *createdHere; __unsafe_unretained NSString *objectId; __unsafe_unretained NSString *syncStatus; @@ -23,6 +24,7 @@ extern const struct FTASyncParentFetchedProperties { + @interface FTASyncParentID : NSManagedObjectID {} @end @@ -35,7 +37,19 @@ extern const struct FTASyncParentFetchedProperties { -@property (nonatomic, strong) NSNumber *createdHere; + +@property (nonatomic, strong) NSDate* createdAt; + + + +//- (BOOL)validateCreatedAt:(id*)value_ error:(NSError**)error_; + + + + + +@property (nonatomic, strong) NSNumber* createdHere; + @property BOOL createdHereValue; @@ -47,7 +61,9 @@ extern const struct FTASyncParentFetchedProperties { -@property (nonatomic, strong) NSString *objectId; + +@property (nonatomic, strong) NSString* objectId; + //- (BOOL)validateObjectId:(id*)value_ error:(NSError**)error_; @@ -55,7 +71,9 @@ extern const struct FTASyncParentFetchedProperties { -@property (nonatomic, strong) NSNumber *syncStatus; + +@property (nonatomic, strong) NSNumber* syncStatus; + @property int16_t syncStatusValue; @@ -67,7 +85,9 @@ extern const struct FTASyncParentFetchedProperties { -@property (nonatomic, strong) NSDate *updatedAt; + +@property (nonatomic, strong) NSDate* updatedAt; + //- (BOOL)validateUpdatedAt:(id*)value_ error:(NSError**)error_; @@ -86,8 +106,14 @@ extern const struct FTASyncParentFetchedProperties { @interface _FTASyncParent (CoreDataGeneratedPrimitiveAccessors) -- (NSNumber *)primitiveCreatedHere; -- (void)setPrimitiveCreatedHere:(NSNumber *)value; +- (NSDate*)primitiveCreatedAt; +- (void)setPrimitiveCreatedAt:(NSDate*)value; + + + + +- (NSNumber*)primitiveCreatedHere; +- (void)setPrimitiveCreatedHere:(NSNumber*)value; - (BOOL)primitiveCreatedHereValue; - (void)setPrimitiveCreatedHereValue:(BOOL)value_; @@ -95,14 +121,14 @@ extern const struct FTASyncParentFetchedProperties { -- (NSString *)primitiveObjectId; -- (void)setPrimitiveObjectId:(NSString *)value; +- (NSString*)primitiveObjectId; +- (void)setPrimitiveObjectId:(NSString*)value; -- (NSNumber *)primitiveSyncStatus; -- (void)setPrimitiveSyncStatus:(NSNumber *)value; +- (NSNumber*)primitiveSyncStatus; +- (void)setPrimitiveSyncStatus:(NSNumber*)value; - (int16_t)primitiveSyncStatusValue; - (void)setPrimitiveSyncStatusValue:(int16_t)value_; @@ -110,8 +136,8 @@ extern const struct FTASyncParentFetchedProperties { -- (NSDate *)primitiveUpdatedAt; -- (void)setPrimitiveUpdatedAt:(NSDate *)value; +- (NSDate*)primitiveUpdatedAt; +- (void)setPrimitiveUpdatedAt:(NSDate*)value; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.m b/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.m index fd3bc1b..6b19b82 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.m +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_FTASyncParent.m @@ -4,6 +4,7 @@ #import "_FTASyncParent.h" const struct FTASyncParentAttributes FTASyncParentAttributes = { + .createdAt = @"createdAt", .createdHere = @"createdHere", .objectId = @"objectId", .syncStatus = @"syncStatus", @@ -39,16 +40,18 @@ - (FTASyncParentID*)objectID { return (FTASyncParentID*)[super objectID]; } -+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"createdHereValue"]) { NSSet *affectingKey = [NSSet setWithObject:@"createdHere"]; keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + return keyPaths; } if ([key isEqualToString:@"syncStatusValue"]) { NSSet *affectingKey = [NSSet setWithObject:@"syncStatus"]; keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + return keyPaths; } return keyPaths; @@ -57,6 +60,13 @@ + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { +@dynamic createdAt; + + + + + + @dynamic createdHere; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_Person.h b/FTASyncDemo/FTASyncDemo/DataClasses/_Person.h index 074c190..3a18f2a 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_Person.h +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_Person.h @@ -31,7 +31,9 @@ extern const struct PersonFetchedProperties { -@property (nonatomic, strong) NSData *photo; + +@property (nonatomic, strong) NSData* photo; + //- (BOOL)validatePhoto:(id*)value_ error:(NSError**)error_; @@ -40,7 +42,7 @@ extern const struct PersonFetchedProperties { -@property (nonatomic, strong) NSSet* toDoItem; +@property (nonatomic, strong) NSSet *toDoItem; - (NSMutableSet*)toDoItemSet; @@ -62,8 +64,8 @@ extern const struct PersonFetchedProperties { @interface _Person (CoreDataGeneratedPrimitiveAccessors) -- (NSData *)primitivePhoto; -- (void)setPrimitivePhoto:(NSData *)value; +- (NSData*)primitivePhoto; +- (void)setPrimitivePhoto:(NSData*)value; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_Person.m b/FTASyncDemo/FTASyncDemo/DataClasses/_Person.m index e073988..876205b 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_Person.m +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_Person.m @@ -37,7 +37,7 @@ - (PersonID*)objectID { return (PersonID*)[super objectID]; } -+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.h b/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.h index 1b959bd..446fd2d 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.h +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.h @@ -33,7 +33,9 @@ extern const struct ToDoItemFetchedProperties { -@property (nonatomic, strong) NSString *name; + +@property (nonatomic, strong) NSString* name; + //- (BOOL)validateName:(id*)value_ error:(NSError**)error_; @@ -41,7 +43,9 @@ extern const struct ToDoItemFetchedProperties { -@property (nonatomic, strong) NSNumber *priority; + +@property (nonatomic, strong) NSNumber* priority; + @property int16_t priorityValue; @@ -54,7 +58,7 @@ extern const struct ToDoItemFetchedProperties { -@property (nonatomic, strong) Person* person; +@property (nonatomic, strong) Person *person; //- (BOOL)validatePerson:(id*)value_ error:(NSError**)error_; @@ -71,14 +75,14 @@ extern const struct ToDoItemFetchedProperties { @interface _ToDoItem (CoreDataGeneratedPrimitiveAccessors) -- (NSString *)primitiveName; -- (void)setPrimitiveName:(NSString *)value; +- (NSString*)primitiveName; +- (void)setPrimitiveName:(NSString*)value; -- (NSNumber *)primitivePriority; -- (void)setPrimitivePriority:(NSNumber *)value; +- (NSNumber*)primitivePriority; +- (void)setPrimitivePriority:(NSNumber*)value; - (int16_t)primitivePriorityValue; - (void)setPrimitivePriorityValue:(int16_t)value_; diff --git a/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.m b/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.m index 0358cff..61242b3 100644 --- a/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.m +++ b/FTASyncDemo/FTASyncDemo/DataClasses/_ToDoItem.m @@ -38,12 +38,13 @@ - (ToDoItemID*)objectID { return (ToDoItemID*)[super objectID]; } -+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"priorityValue"]) { NSSet *affectingKey = [NSSet setWithObject:@"priority"]; keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + return keyPaths; } return keyPaths; diff --git a/FTASyncDemo/FTASyncDemo/FTAPersonTableViewController.m b/FTASyncDemo/FTASyncDemo/FTAPersonTableViewController.m index 0e0f891..4cc2f39 100644 --- a/FTASyncDemo/FTASyncDemo/FTAPersonTableViewController.m +++ b/FTASyncDemo/FTASyncDemo/FTAPersonTableViewController.m @@ -129,7 +129,8 @@ - (void)addPerson { - (void)syncPerson { DCLog(@"SYNCING PERSON"); //[[FTASyncHandler sharedInstance] syncEntity:[NSEntityDescription entityForName:@"Reward" inManagedObjectContext:[NSManagedObjectContext MR_context]]]; - [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^{ + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); DCLog(@"Completion Block Called"); } progressBlock:^(float progress, NSString *message) { DLog(@"PROGRESS UPDATE: %f - %@", progress, message); diff --git a/FTASyncDemo/FTASyncDemo/FTASetupViewController.m b/FTASyncDemo/FTASyncDemo/FTASetupViewController.m index 10ec1b7..d0c846d 100644 --- a/FTASyncDemo/FTASyncDemo/FTASetupViewController.m +++ b/FTASyncDemo/FTASyncDemo/FTASetupViewController.m @@ -129,7 +129,8 @@ - (void)resetData { - (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user { [self.tabBarController dismissModalViewControllerAnimated:YES]; DCLog(@"Login Success!"); - [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^{ + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); DCLog(@"Completion Block Called"); } progressBlock:^(float progress, NSString *message) { DLog(@"PROGRESS UPDATE: %f - %@", progress, message); @@ -150,7 +151,8 @@ - (void)logInViewController:(PFLogInViewController *)logInController didFailToLo - (void)signUpViewController:(PFSignUpViewController *)signUpController didSignUpUser:(PFUser *)user { DCLog(@"Signup Success!"); [self.tabBarController dismissModalViewControllerAnimated:YES]; - [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^{ + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); DCLog(@"Completion Block Called"); } progressBlock:^(float progress, NSString *message) { DLog(@"PROGRESS UPDATE: %f - %@", progress, message); diff --git a/FTASyncDemo/FTASyncDemo/FTAToDoTableViewController.m b/FTASyncDemo/FTASyncDemo/FTAToDoTableViewController.m index 7c37273..5479753 100644 --- a/FTASyncDemo/FTASyncDemo/FTAToDoTableViewController.m +++ b/FTASyncDemo/FTASyncDemo/FTAToDoTableViewController.m @@ -129,7 +129,8 @@ - (void)addToDo { - (void)syncToDo { DCLog(@"SYNCING TODO"); //[[FTASyncHandler sharedInstance] syncEntity:[NSEntityDescription entityForName:@"Reward" inManagedObjectContext:[NSManagedObjectContext MR_context]]]; - [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^{ + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); DCLog(@"Completion Block Called"); } progressBlock:^(float progress, NSString *message) { DLog(@"PROGRESS UPDATE: %f - %@", progress, message); diff --git a/FTASyncDemo/FTASyncDemo/Resources/parse_large.png b/FTASyncDemo/FTASyncDemo/Resources/parse_large.png new file mode 100644 index 0000000..f15bf78 Binary files /dev/null and b/FTASyncDemo/FTASyncDemo/Resources/parse_large.png differ diff --git a/FTASyncDemo/FTASyncDemo/Resources/parse_medium.png b/FTASyncDemo/FTASyncDemo/Resources/parse_medium.png new file mode 100644 index 0000000..e701f70 Binary files /dev/null and b/FTASyncDemo/FTASyncDemo/Resources/parse_medium.png differ diff --git a/FTASyncDemo/FTASyncDemo/Resources/parse_small.png b/FTASyncDemo/FTASyncDemo/Resources/parse_small.png new file mode 100644 index 0000000..704fb45 Binary files /dev/null and b/FTASyncDemo/FTASyncDemo/Resources/parse_small.png differ diff --git a/FTASyncDemo/FTASyncDemoTests/FTASyncDemoTests.m b/FTASyncDemo/FTASyncDemoTests/FTASyncDemoTests.m deleted file mode 100644 index 08c3fba..0000000 --- a/FTASyncDemo/FTASyncDemoTests/FTASyncDemoTests.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// FTASyncDemoTests.m -// FTASyncDemoTests -// -// Created by Justin Bergen on 4/1/12. -// Copyright (c) 2012 Five3 Apps. All rights reserved. -// - -#import "FTASyncDemoTests.h" - -@implementation FTASyncDemoTests - -- (void)setUp -{ - [super setUp]; - - // Set-up code here. -} - -- (void)tearDown -{ - // Tear-down code here. - - [super tearDown]; -} - -- (void)testExample -{ - STFail(@"Unit tests are not implemented yet in FTASyncDemoTests"); -} - -@end diff --git a/FTASyncDemo/FTASyncDemoTests/FTASyncDemoTests.h b/FTASyncDemo/FTASyncDemoTests/FTASyncTests.h similarity index 100% rename from FTASyncDemo/FTASyncDemoTests/FTASyncDemoTests.h rename to FTASyncDemo/FTASyncDemoTests/FTASyncTests.h diff --git a/FTASyncDemo/FTASyncDemoTests/FTASyncTests.m b/FTASyncDemo/FTASyncDemoTests/FTASyncTests.m new file mode 100644 index 0000000..dc2780b --- /dev/null +++ b/FTASyncDemo/FTASyncDemoTests/FTASyncTests.m @@ -0,0 +1,532 @@ +// +// FTASyncDemoTests.m +// FTASyncDemoTests +// +// Created by Justin Bergen on 4/1/12. +// Copyright (c) 2012 Five3 Apps. All rights reserved. +// + +#import "FTASyncTests.h" +#import +#import "CoreData+MagicalRecord.h" +#import +#import "ParseKeys.h" +#import "Person.h" +#import "ToDoItem.h" +#import "FTASyncHandler.h" + +@implementation FTASyncDemoTests { + BOOL _isFinished; +} + +- (void)setUpClass; +{ + [MagicalRecord setupAutoMigratingCoreDataStack]; + + [Parse setApplicationId:kParseAppId + clientKey:kParseClientKey]; + [PFACL setDefaultACL:[PFACL ACL] withAccessForCurrentUser:YES]; + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"]; + NSString *username = [formatter stringFromDate:[NSDate date]]; + PFUser *user = [[PFUser alloc] init]; + user.username = username; + user.password = @"test"; + [user signUp]; + NSLog(@"username: %@ objectId: %@", username, user.objectId); + + [FTASyncHandler sharedInstance]; +} + +- (void)setUp { + //[MagicalRecord setupAutoMigratingCoreDataStack]; + [super setUp]; + [self setUpClass]; + [self deleteAllPerseObjects]; + [self deleteAllLocalObjects]; + _isFinished = NO; +} + +- (void)tearDown { + // wait for using multi thread + do { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; + } while (!_isFinished); + //[MagicalRecord cleanUp]; + [super tearDown]; +} + +- (void)testUploadCreatedLocalObjectToParse { + [self createLocalObjectAndUploadToParse]; + _isFinished = YES; +} + +- (void)testUploadImageDataToParse { + NSArray *imageNames = [NSArray arrayWithObjects:@"parse_small.png", @"parse_medium.png", @"parse_large.png", nil]; + + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + for (NSString *imageName in imageNames) { + Person *person = [Person MR_createInContext:editingContext]; + person.name = imageName; + person.photo = UIImagePNGRepresentation([UIImage imageNamed:imageName]); + } + [editingContext MR_saveToPersistentStoreAndWait]; + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + for (NSString *imageName in imageNames) { + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + [query whereKey:@"name" equalTo:imageName]; + PFObject *remotePerson = [query getFirstObject]; + assert([[[remotePerson objectForKey:@"photo"] getData] isEqualToData:UIImagePNGRepresentation([UIImage imageNamed:imageName])]); + } + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testUploadUpdatedLocalObjectToParse { + [self createLocalObjectAndUploadToParse]; + Person *person = [Person MR_findFirst]; + + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + person = (id)[editingContext existingObjectWithID:[person objectID] error:nil]; + person.name = @"ichiro"; + person.photo = nil; + [person syncUpdate]; + [editingContext MR_saveToPersistentStoreAndWait]; + + NSArray *persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@1]); + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + persons = [query findObjects]; + assert([persons count] == 1); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + NSArray *remote_persons = [query findObjects]; + assert([remote_persons count] == 1); + assert([[remote_persons[0] objectForKey:@"name"] isEqualToString:@"ichiro"]); + assert([remote_persons[0] objectForKey:@"photo"] == [NSNull null]); + + NSArray *local_persons = [Person MR_findAll]; + assert([local_persons count] == 1); + assert([[local_persons[0] syncStatus] isEqualToNumber:@0]); + + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testUploadDeletedLocalObjectToParse { + [self createLocalObjectAndUploadToParse]; + Person *person = [Person MR_findFirst]; + + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + person = (id)[editingContext existingObjectWithID:[person objectID] error:nil]; + [Person MR_truncateAllInContext:editingContext]; + [editingContext MR_saveToPersistentStoreAndWait]; + + NSArray *persons = [Person MR_findAll]; + assert([persons count] == 0); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *remote_persons = [query findObjects]; + assert([remote_persons count] == 1); + assert([[remote_persons[0] objectForKey:@"name"] isEqualToString:@"taro"]); + assert([[remote_persons[0] objectForKey:@"deleted"] isEqualToNumber:@1]); + + NSArray *local_persons = [Person MR_findAll]; + assert([local_persons count] == 0); + + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testStoreCreatedParseObject { + PFObject *person = [PFObject objectWithClassName:@"CDPerson"]; + [person setObject:@"messi" forKey:@"name"]; + [person save]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + assert([persons count] == 1); + assert([[persons[0] objectForKey:@"name"] isEqualToString:@"messi"]); + + persons = [Person MR_findAll]; + assert([persons count] == 0); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + NSArray *remote_persons = [query findObjects]; + assert([remote_persons count] == 1); + assert([[remote_persons[0] objectForKey:@"name"] isEqualToString:@"messi"]); + + NSArray *local_persons = [Person MR_findAll]; + assert([local_persons count] == 1); + assert([[local_persons[0] name] isEqualToString:@"messi"]); + assert([[local_persons[0] syncStatus] isEqualToNumber:@0]); + + NSArray *recievedPFObjects = [[FTASyncHandler sharedInstance] receivedPFObjects:@"CDPerson"]; + NSLog(@"dic: %@", [[FTASyncHandler sharedInstance] receivedPFObjectDictionary]); + assert([recievedPFObjects count] == 1); + assert([[recievedPFObjects[0] objectForKey:@"name"] isEqualToString:@"messi"]); + + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testStoreCreatedParseImageData { + NSArray *imageNames = [NSArray arrayWithObjects:@"parse_small.png", @"parse_medium.png", @"parse_large.png", nil]; + + for (NSString *imageName in imageNames) { + PFObject *person = [PFObject objectWithClassName:@"CDPerson"]; + NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:imageName]); + [person setObject:imageName forKey:@"name"]; + [person setObject:[PFFile fileWithData:imageData] forKey:@"photo"]; + [person save]; + } + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + for (NSString *imageName in imageNames) { + Person *person = [Person MR_findFirstByAttribute:@"name" withValue:imageName]; + assert([[person unarchivePhotoData:@"photo"] isKindOfClass:[NSURL class]]); + NSData *imageData = [NSData dataWithContentsOfURL:[person unarchivePhotoData:@"photo"]]; + assert([imageData isEqualToData:UIImagePNGRepresentation([UIImage imageNamed:imageName])]); + } + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testStoreUpdatedParseObject { + [self createLocalObjectAndUploadToParse]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + PFObject *person = persons[0]; + [person setObject:@"ichiro" forKey:@"name"]; + [person setObject:[NSNull null] forKey:@"photo"]; + [person save]; + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + NSArray *remote_persons = [query findObjects]; + assert([remote_persons count] == 1); + assert([[remote_persons[0] objectForKey:@"name"] isEqualToString:@"ichiro"]); + + NSArray *local_persons = [Person MR_findAll]; + assert([local_persons count] == 1); + assert([[local_persons[0] name] isEqualToString:@"ichiro"]); + assert(![local_persons[0] photo]); + NSLog(@"person: %@", local_persons[0]); + assert([[local_persons[0] syncStatus] isEqualToNumber:@0]); + + NSArray *recievedPFObjects = [[FTASyncHandler sharedInstance] receivedPFObjects:@"CDPerson"]; + NSLog(@"dic: %@", [[FTASyncHandler sharedInstance] receivedPFObjectDictionary]); + assert([recievedPFObjects count] == 1); + assert([[recievedPFObjects[0] objectForKey:@"name"] isEqualToString:@"ichiro"]); + + _isFinished = YES; + } progressBlock:nil]; +} + + +- (void)testStoreDeletedParseObject { + [self createLocalObjectAndUploadToParse]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + PFObject *person = persons[0]; + [person setObject:@1 forKey:@"deleted"]; + assert([person save]); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *remote_persons = [query findObjects]; + assert([remote_persons count] == 1); + assert([[remote_persons[0] objectForKey:@"name"] isEqualToString:@"taro"]); + assert([[remote_persons[0] objectForKey:@"deleted"] isEqualToNumber:@1]); + + NSArray *local_persons = [Person MR_findAll]; + assert([local_persons count] == 0); + + NSArray *recievedPFObjects = [[FTASyncHandler sharedInstance] receivedPFObjects:@"CDPerson"]; + NSLog(@"dic: %@", [[FTASyncHandler sharedInstance] receivedPFObjectDictionary]); + assert([recievedPFObjects count] == 1); + assert([[recievedPFObjects[0] objectForKey:@"name"] isEqualToString:@"taro"]); + assert([[recievedPFObjects[0] objectForKey:@"deleted"] isEqualToNumber:@1]); + + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testIgnoreCompleteDeletedParseObject { + [self createLocalObjectAndUploadToParse]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + PFObject *person = persons[0]; + [person delete]; + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + assert([persons count] == 0); + + persons = [Person MR_findAll]; + assert([persons count] == 1); + + _isFinished = YES; + } progressBlock:nil]; +} + +- (void)testUpdateLocalObjectDeletedInParse { + [self createLocalObjectAndUploadToParse]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + PFObject *person = persons[0]; + [person delete]; + + Person *localPerson = [Person MR_findFirst]; + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + localPerson = (id)[editingContext existingObjectWithID:[localPerson objectID] error:nil]; + localPerson.name = @"ichiro"; + [localPerson syncUpdate]; + [editingContext MR_saveToPersistentStoreAndWait]; + + NSArray *localPersons = [Person MR_findAll]; + assert([localPersons count] == 1); + assert([[localPersons[0] syncStatus] isEqualToNumber:@1]); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + assert([persons count] == 1); + + persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@0]); + + _isFinished = YES; + } progressBlock:nil]; +} + +-(void) testDeleteAllDeletedByRemote { + [self createLocalObjectAndUploadToParse]; + + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + PFObject *person = persons[0]; + assert([person delete]); + + [[FTASyncHandler sharedInstance] deleteAllDeletedByRemote:^(BOOL success, NSError *error) { + assert(success); + + NSArray *localPersons = [Person MR_findAll]; + assert([localPersons count] == 0); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + NSArray *persons = [query findObjects]; + assert([persons count] == 0); + + persons = [Person MR_findAll]; + assert([persons count] == 0); + + _isFinished = YES; + } progressBlock:nil]; + }]; +} + +- (void) testSyncHandlerSomeTimes { + for (NSInteger i = 0; i < 12; ++i) { + PFObject *person = [PFObject objectWithClassName:@"CDPerson"]; + [person setObject:[NSString stringWithFormat:@"remote_person%d", i] forKey:@"name"]; + [person save]; + } + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + Person *person = [Person MR_createInContext:editingContext]; + person.name = @"local_person"; + [editingContext MR_saveToPersistentStoreAndWait]; + + FTASyncHandler *shared = [FTASyncHandler sharedInstance]; + shared.queryLimit = 5; + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + NSArray *persons = [Person MR_findAllSortedBy:@"updatedAt" ascending:NO]; + assert([persons count] == 6); + assert([[persons[0] name] isEqualToString:@"local_person"]); + assert([[persons[1] name] isEqualToString:@"remote_person4"]); + + shared.queryLimit = 5; + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + NSArray *persons = [Person MR_findAllSortedBy:@"updatedAt" ascending:NO]; + assert([persons count] == 11); + assert([[persons[0] name] isEqualToString:@"local_person"]); + assert([[persons[1] name] isEqualToString:@"remote_person9"]); + + shared.queryLimit = 10; + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + NSArray *persons = [Person MR_findAllSortedBy:@"updatedAt" ascending:NO]; + assert([persons count] == 13); + assert([[persons[0] name] isEqualToString:@"local_person"]); + assert([[persons[1] name] isEqualToString:@"remote_person11"]); + + _isFinished = YES; + } progressBlock:nil]; + } progressBlock:nil]; + } progressBlock:nil]; +} + +- (void) testSyncFailWhileAnotherSyncInProgress { + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + Person *person = [Person MR_createInContext:editingContext]; + person.name = @"taro"; + [editingContext MR_saveToPersistentStoreAndWait]; + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + _isFinished = YES; + } progressBlock:nil]; + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(!success); + } progressBlock:nil]; +} + +- (void)testUploadCreatedLocalObjectWithRelationToParse { + [self createLocalObjectWithRelationAndUploadToParse]; + _isFinished = YES; +} + +- (void) deleteAllPerseObjects { + NSArray *entityNames = @[@"CDPerson", @"CDToDoItem"]; + for (NSString *name in entityNames) { + PFQuery *query = [PFQuery queryWithClassName:name]; + query.limit = 1000; + NSArray *persons = [query findObjects]; + for (PFObject *person in persons) { + assert([person delete]); + } + } +} + +-(void) deleteAllLocalObjects { + [[FTASyncHandler sharedInstance] setIgnoreContextSave:YES]; + NSArray *classNames = @[@"Person", @"ToDoItem"]; + for (NSString *className in classNames) { + NSArray *models = [NSClassFromString(className) MR_findAll]; + for (NSManagedObject *model in models) { + [model MR_deleteEntity]; + } + } + + [[NSUserDefaults standardUserDefaults] setObject:[[NSMutableArray alloc] init] forKey:@"FTASyncDeletedCDPerson"]; + [[FTASyncHandler sharedInstance] setIgnoreContextSave:NO]; +} + +-(void) createLocalObjectAndUploadToParse { + _isFinished = NO; + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + Person *person = [Person MR_createInContext:editingContext]; + person.name = @"taro"; + person.photo = UIImagePNGRepresentation([UIImage imageNamed:@"parse_small.png"]); + [editingContext MR_saveToPersistentStoreAndWait]; + + NSArray *persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@2]); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + NSArray *persons = [query findObjects]; + assert([persons count] == 1); + assert([[persons[0] objectForKey:@"name"] isEqualToString:@"taro"]); + assert([[persons[0] objectForKey:@"photo"] isKindOfClass:[PFFile class]]); + + persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@0]); + + _isFinished = YES; + } progressBlock:nil]; + + do { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; + } while (!_isFinished); + + _isFinished = NO; +} + +-(void) createLocalObjectWithRelationAndUploadToParse { + _isFinished = NO; + NSManagedObjectContext *editingContext = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; + Person *person = [Person MR_createInContext:editingContext]; + person.name = @"taro"; + person.photo = UIImagePNGRepresentation([UIImage imageNamed:@"parse_small.png"]); + ToDoItem *item1 = [ToDoItem MR_createInContext:editingContext]; + item1.name = @"todo1"; + item1.priority = @1; + item1.syncStatus = @3; + [person addToDoItemObject:item1]; + ToDoItem *item2 = [ToDoItem MR_createInContext:editingContext]; + item2.name = @"todo2"; + item2.priority = @2; + item2.syncStatus = @3; + [person addToDoItemObject:item2]; + [editingContext MR_saveToPersistentStoreAndWait]; + + NSArray *persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@2]); + NSSet *todoItems = [persons[0] toDoItemSet]; + assert((int)[todoItems count] == 2); + + [[FTASyncHandler sharedInstance] syncWithCompletionBlock:^(BOOL success, NSError *error) { + assert(success); + PFQuery *query = [PFQuery queryWithClassName:@"CDPerson"]; + query.limit = 1000; + NSArray *persons = [query findObjects]; + assert([persons count] == 1); + assert([[persons[0] objectForKey:@"name"] isEqualToString:@"taro"]); + assert([[persons[0] objectForKey:@"photo"] isKindOfClass:[PFFile class]]); + + persons = [Person MR_findAll]; + assert([persons count] == 1); + assert([[persons[0] syncStatus] isEqualToNumber:@0]); + + NSArray *items = [ToDoItem MR_findAll]; + assert([items count] == 2); + assert([[items[0] syncStatus] isEqualToNumber:@0]); + assert([[items[1] syncStatus] isEqualToNumber:@0]); + + _isFinished = YES; + } progressBlock:nil]; + + do { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; + } while (!_isFinished); + + _isFinished = NO; +} + +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBConnect.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBConnect.h deleted file mode 100644 index 424be4a..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBConnect.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2010 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include "PF_Facebook.h" -#include "PF_FBDialog.h" -#include "PF_FBLoginDialog.h" -#include "PF_FBRequest.h" diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBDialog.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBDialog.h deleted file mode 100644 index 62f909a..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBDialog.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2010 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import - -@protocol PF_FBDialogDelegate; -@class PF_FBFrictionlessRequestSettings; - -/** - * Do not use this interface directly, instead, use dialog in Facebook.h - * - * Facebook dialog interface for start the facebook webView UIServer Dialog. - */ - -@interface PF_FBDialog : UIView { - id _delegate; - NSMutableDictionary *_params; - NSString * _serverURL; - NSURL* _loadingURL; - UIWebView* _webView; - UIActivityIndicatorView* _spinner; - UIButton* _closeButton; - UIInterfaceOrientation _orientation; - BOOL _showingKeyboard; - BOOL _isViewInvisible; - PF_FBFrictionlessRequestSettings* _frictionlessSettings; - - // Ensures that UI elements behind the dialog are disabled. - UIView* _modalBackgroundView; -} - -/** - * The delegate. - */ -@property(nonatomic,assign) id delegate; - -/** - * The parameters. - */ -@property(nonatomic, retain) NSMutableDictionary* params; - -- (NSString *) getStringFromUrl: (NSString*) url needle:(NSString *) needle; - -- (id)initWithURL: (NSString *) loadingURL - params: (NSMutableDictionary *) params - isViewInvisible: (BOOL) isViewInvisible - frictionlessSettings: (PF_FBFrictionlessRequestSettings *) frictionlessSettings - delegate: (id ) delegate; - -/** - * Displays the view with an animation. - * - * The view will be added to the top of the current key window. - */ -- (void)show; - -/** - * Displays the first page of the dialog. - * - * Do not ever call this directly. It is intended to be overriden by subclasses. - */ -- (void)load; - -/** - * Displays a URL in the dialog. - */ -- (void)loadURL:(NSString*)url - get:(NSDictionary*)getParams; - -/** - * Hides the view and notifies delegates of success or cancellation. - */ -- (void)dismissWithSuccess:(BOOL)success animated:(BOOL)animated; - -/** - * Hides the view and notifies delegates of an error. - */ -- (void)dismissWithError:(NSError*)error animated:(BOOL)animated; - -/** - * Subclasses may override to perform actions just prior to showing the dialog. - */ -- (void)dialogWillAppear; - -/** - * Subclasses may override to perform actions just after the dialog is hidden. - */ -- (void)dialogWillDisappear; - -/** - * Subclasses should override to process data returned from the server in a 'fbconnect' url. - * - * Implementations must call dismissWithSuccess:YES at some point to hide the dialog. - */ -- (void)dialogDidSucceed:(NSURL *)url; - -/** - * Subclasses should override to process data returned from the server in a 'fbconnect' url. - * - * Implementations must call dismissWithSuccess:YES at some point to hide the dialog. - */ -- (void)dialogDidCancel:(NSURL *)url; -@end - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -/* - *Your application should implement this delegate - */ -@protocol PF_FBDialogDelegate - -@optional - -/** - * Called when the dialog succeeds and is about to be dismissed. - */ -- (void)dialogDidComplete:(PF_FBDialog *)dialog; - -/** - * Called when the dialog succeeds with a returning url. - */ -- (void)dialogCompleteWithUrl:(NSURL *)url; - -/** - * Called when the dialog get canceled by the user. - */ -- (void)dialogDidNotCompleteWithUrl:(NSURL *)url; - -/** - * Called when the dialog is cancelled and is about to be dismissed. - */ -- (void)dialogDidNotComplete:(PF_FBDialog *)dialog; - -/** - * Called when dialog failed to load due to an error. - */ -- (void)dialog:(PF_FBDialog*)dialog didFailWithError:(NSError *)error; - -/** - * Asks if a link touched by a user should be opened in an external browser. - * - * If a user touches a link, the default behavior is to open the link in the Safari browser, - * which will cause your app to quit. You may want to prevent this from happening, open the link - * in your own internal browser, or perhaps warn the user that they are about to leave your app. - * If so, implement this method on your delegate and return NO. If you warn the user, you - * should hold onto the URL and once you have received their acknowledgement open the URL yourself - * using [[UIApplication sharedApplication] openURL:]. - */ -- (BOOL)dialog:(PF_FBDialog*)dialog shouldOpenURLInExternalBrowser:(NSURL *)url; - -@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBFrictionlessRequestSettings.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBFrictionlessRequestSettings.h deleted file mode 100644 index d9fad2f..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBFrictionlessRequestSettings.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class PF_Facebook; - -/** - * Do not use this interface directly, instead, use methods in Facebook.h - * - * Handles frictionless interaction and recipient-caching by the SDK, - * see https://developers.facebook.com/docs/reference/dialogs/requests/ - */ -@interface PF_FBFrictionlessRequestSettings : NSObject { -@private - NSArray* _allowedRecipients; - PF_FBRequest* _activeRequest; - BOOL _enabled; -} - -/** - * BOOL indicating whether frictionless request sending has been enabled - */ -@property(nonatomic, readonly) BOOL enabled; - -/** - * Enable frictionless request sending by the sdk; this means: - * 1. query and cache the current set of frictionless recipients - * 2. flag other facets of the sdk to behave in a frictionless way - */ -- (void)enableWithFacebook:(PF_Facebook*)facebook; - -/** - * Reload recipient cache; called by the sdk to keep the cache fresh; - * method makes graph request: me/apprequestformerrecipients - */ -- (void)reloadRecipientCacheWithFacebook:(PF_Facebook*)facebook; - -/** - * Update the recipient cache; called by the sdk to keep the cache fresh; - */ -- (void)updateRecipientCacheWithRecipients:(NSArray*)ids; - -/** - * Given an fbID for a user, indicates whether user is enabled for - * frictionless calls - */ -- (BOOL)isFrictionlessEnabledForRecipient:(id)fbid; - -/** - * Given an array of user fbIDs, indicates whether they are enabled for - * frictionless calls - */ -- (BOOL)isFrictionlessEnabledForRecipients:(NSArray*)fbids; - -/** - * init the frictionless cache object - */ -- (id)init; - -@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBLoginDialog.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBLoginDialog.h deleted file mode 100644 index e291d07..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBLoginDialog.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#import "PF_FBDialog.h" - -@protocol PF_FBLoginDialogDelegate; - -/** - * Do not use this interface directly, instead, use authorize in Facebook.h - * - * Facebook Login Dialog interface for start the facebook webView login dialog. - * It start pop-ups prompting for credentials and permissions. - */ - -@interface PF_FBLoginDialog : PF_FBDialog { - id _loginDelegate; -} - --(id) initWithURL:(NSString *) loginURL - loginParams:(NSMutableDictionary *) params - delegate:(id ) delegate; -@end - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@protocol PF_FBLoginDialogDelegate - -- (void)fbDialogLogin:(NSString*)token expirationDate:(NSDate*)expirationDate; - -- (void)fbDialogNotLogin:(BOOL)cancelled; - -@end - - diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBRequest.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBRequest.h deleted file mode 100644 index fdaadcd..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_FBRequest.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2010 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import - -@protocol PF_FBRequestDelegate; - -enum { - PF_kFBRequestStateReady, - PF_kFBRequestStateLoading, - PF_kFBRequestStateComplete, - PF_kFBRequestStateError -}; -typedef NSUInteger PF_FBRequestState; - -/** - * Do not use this interface directly, instead, use method in Facebook.h - */ -@interface PF_FBRequest : NSObject { - id _delegate; - NSString* _url; - NSString* _httpMethod; - NSMutableDictionary* _params; - NSURLConnection* _connection; - NSMutableData* _responseText; - PF_FBRequestState _state; - NSError* _error; - BOOL _sessionDidExpire; -} - - -@property(nonatomic,assign) id delegate; - -/** - * The URL which will be contacted to execute the request. - */ -@property(nonatomic,copy) NSString* url; - -/** - * The API method which will be called. - */ -@property(nonatomic,copy) NSString* httpMethod; - -/** - * The dictionary of parameters to pass to the method. - * - * These values in the dictionary will be converted to strings using the - * standard Objective-C object-to-string conversion facilities. - */ -@property(nonatomic,retain) NSMutableDictionary* params; -@property(nonatomic,retain) NSURLConnection* connection; -@property(nonatomic,retain) NSMutableData* responseText; -@property(nonatomic,readonly) PF_FBRequestState state; -@property(nonatomic,readonly) BOOL sessionDidExpire; - -/** - * Error returned by the server in case of request's failure (or nil otherwise). - */ -@property(nonatomic,retain) NSError* error; - - -+ (NSString*)serializeURL:(NSString *)baseUrl - params:(NSDictionary *)params; - -+ (NSString*)serializeURL:(NSString *)baseUrl - params:(NSDictionary *)params - httpMethod:(NSString *)httpMethod; - -+ (PF_FBRequest*)getRequestWithParams:(NSMutableDictionary *) params - httpMethod:(NSString *) httpMethod - delegate:(id)delegate - requestURL:(NSString *) url; -- (BOOL) loading; - -- (void) connect; - -@end - -//////////////////////////////////////////////////////////////////////////////// - -/* - *Your application should implement this delegate - */ -@protocol PF_FBRequestDelegate - -@optional - -/** - * Called just before the request is sent to the server. - */ -- (void)requestLoading:(PF_FBRequest *)request; - -/** - * Called when the Facebook API request has returned a response. - * - * This callback gives you access to the raw response. It's called before - * (void)request:(FBRequest *)request didLoad:(id)result, - * which is passed the parsed response object. - */ -- (void)request:(PF_FBRequest *)request didReceiveResponse:(NSURLResponse *)response; - -/** - * Called when an error prevents the request from completing successfully. - */ -- (void)request:(PF_FBRequest *)request didFailWithError:(NSError *)error; - -/** - * Called when a request returns and its response has been parsed into - * an object. - * - * The resulting object may be a dictionary, an array or a string, depending - * on the format of the API response. If you need access to the raw response, - * use: - * - * (void)request:(FBRequest *)request - * didReceiveResponse:(NSURLResponse *)response - */ -- (void)request:(PF_FBRequest *)request didLoad:(id)result; - -/** - * Called when a request returns a response. - * - * The result object is the raw response from the server of type NSData - */ -- (void)request:(PF_FBRequest *)request didLoadRawResponse:(NSData *)data; - -@end - diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_Facebook.h b/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_Facebook.h deleted file mode 100644 index 4a7310b..0000000 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_Facebook.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2010 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "PF_FBLoginDialog.h" -#import "PF_FBRequest.h" - -@class PF_FBFrictionlessRequestSettings; -@protocol PF_FBSessionDelegate; - -/** - * Main Facebook interface for interacting with the Facebook developer API. - * Provides methods to log in and log out a user, make requests using the REST - * and Graph APIs, and start user interface interactions (such as - * pop-ups promoting for credentials, permissions, stream posts, etc.) - */ -@interface PF_Facebook : NSObject{ - NSString* _accessToken; - NSDate* _expirationDate; - id _sessionDelegate; - NSMutableSet* _requests; - PF_FBDialog* _loginDialog; - PF_FBDialog* _fbDialog; - NSString* _appId; - NSString* _urlSchemeSuffix; - NSArray* _permissions; - BOOL _isExtendingAccessToken; - PF_FBRequest *_requestExtendingAccessToken; - NSDate* _lastAccessTokenUpdate; - PF_FBFrictionlessRequestSettings* _frictionlessRequestSettings; -} - -@property(nonatomic, copy) NSString* accessToken; -@property(nonatomic, copy) NSDate* expirationDate; -@property(nonatomic, assign) id sessionDelegate; -@property(nonatomic, copy) NSString* urlSchemeSuffix; -@property(nonatomic, readonly, getter=isFrictionlessRequestsEnabled) - BOOL isFrictionlessRequestsEnabled; - -- (id)initWithAppId:(NSString *)appId - andDelegate:(id)delegate; - -- (id)initWithAppId:(NSString *)appId - urlSchemeSuffix:(NSString *)urlSchemeSuffix - andDelegate:(id)delegate; - -- (void)authorize:(NSArray *)permissions; - -- (void)extendAccessToken; - -- (void)extendAccessTokenIfNeeded; - -- (BOOL)shouldExtendAccessToken; - -- (BOOL)handleOpenURL:(NSURL *)url; - -- (void)logout; - -- (void)logout:(id)delegate; - -- (PF_FBRequest*)requestWithParams:(NSMutableDictionary *)params - andDelegate:(id )delegate; - -- (PF_FBRequest*)requestWithMethodName:(NSString *)methodName - andParams:(NSMutableDictionary *)params - andHttpMethod:(NSString *)httpMethod - andDelegate:(id )delegate; - -- (PF_FBRequest*)requestWithGraphPath:(NSString *)graphPath - andDelegate:(id )delegate; - -- (PF_FBRequest*)requestWithGraphPath:(NSString *)graphPath - andParams:(NSMutableDictionary *)params - andDelegate:(id )delegate; - -- (PF_FBRequest*)requestWithGraphPath:(NSString *)graphPath - andParams:(NSMutableDictionary *)params - andHttpMethod:(NSString *)httpMethod - andDelegate:(id )delegate; - -- (void)dialog:(NSString *)action - andDelegate:(id)delegate; - -- (void)dialog:(NSString *)action - andParams:(NSMutableDictionary *)params - andDelegate:(id )delegate; - -- (BOOL)isSessionValid; - -- (void)enableFrictionlessRequests; - -- (void)reloadFrictionlessRecipientCache; - -- (BOOL)isFrictionlessEnabledForRecipient:(id)fbid; - -- (BOOL)isFrictionlessEnabledForRecipients:(NSArray*)fbids; - -@end - -//////////////////////////////////////////////////////////////////////////////// - -/** - * Your application should implement this delegate to receive session callbacks. - */ -@protocol PF_FBSessionDelegate - -/** - * Called when the user successfully logged in. - */ -- (void)fbDidLogin; - -/** - * Called when the user dismissed the dialog without logging in. - */ -- (void)fbDidNotLogin:(BOOL)cancelled; - -/** - * Called after the access token was extended. If your application has any - * references to the previous access token (for example, if your application - * stores the previous access token in persistent storage), your application - * should overwrite the old access token with the new one in this method. - * See extendAccessToken for more details. - */ -- (void)fbDidExtendToken:(NSString*)accessToken - expiresAt:(NSDate*)expiresAt; - -/** - * Called when the user logged out. - */ -- (void)fbDidLogout; - -/** - * Called when the current session has expired. This might happen when: - * - the access token expired - * - the app has been disabled - * - the user revoked the app's permissions - * - the user changed his or her password - */ -- (void)fbSessionInvalidated; - -@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Parse b/FTASyncDemo/Parse.framework/Versions/1.0.64/Parse deleted file mode 100644 index cec34b4..0000000 Binary files a/FTASyncDemo/Parse.framework/Versions/1.0.64/Parse and /dev/null differ diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFACL.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFACL.h similarity index 95% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFACL.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFACL.h index 87ef11a..217eb0e 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFACL.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFACL.h @@ -14,13 +14,7 @@ for example, any user could read a particular object but only a particular set of users could write to that object. */ -@interface PFACL : NSObject { -@private - NSMutableDictionary *permissionsById; - BOOL shared; - PFUser *unresolvedUser; - void (^userResolutionListener)(id result, NSError *error); -} +@interface PFACL : NSObject /** @name Creating an ACL */ @@ -152,7 +146,7 @@ read it if a parent role has read access. The role must already be saved on the server and its data must have been fetched in order to use this method. - @param roleName The name of the role. + @param role The name of the role. @return YES if the role has read access. NO otherwise. */ - (BOOL)getReadAccessForRole:(PFRole *)role; @@ -173,7 +167,7 @@ write it if a parent role has write access. The role must already be saved on the server and its data must have been fetched in order to use this method. - @param roleName The name of the role. + @param role The name of the role. @return YES if the role has write access. NO otherwise. */ - (BOOL)getWriteAccessForRole:(PFRole *)role; diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFAnalytics.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFAnalytics.h new file mode 100644 index 0000000..54a4af5 --- /dev/null +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFAnalytics.h @@ -0,0 +1,45 @@ +// +// PFAnalytics.h +// Parse +// +// Created by Christine Yen on 1/29/13. +// Copyright (c) 2013 Parse Inc. All rights reserved. +// + +#import + +/*! + PFAnalytics provides an interface to Parse's logging and analytics backend. + + Methods will return immediately and cache the request (+ timestamp) to be + handled "eventually." That is, the request will be sent immediately if possible + or the next time a network connection is available otherwise. + */ +@interface PFAnalytics : NSObject + +/*! + Tracks this application being launched. If this happened as the result of the + user opening a push notification, this method sends along information to + correlate this open with that push. + + Pass in nil to track a standard "application opened" event. + + @param launchOptions The dictionary indicating the reason the application was + launched, if any. This value can be found as a parameter to various + UIApplicationDelegate methods, and can be empty or nil. + */ ++ (void)trackAppOpenedWithLaunchOptions:(NSDictionary *)launchOptions; + +/*! + Tracks this application being launched. If this happened as the result of the + user opening a push notification, this method sends along information to + correlate this open with that push. + + @param userInfo The Remote Notification payload, if any. This value can be + found either under UIApplicationLaunchOptionsRemoteNotificationKey on + launchOptions, or as a parameter to application:didReceiveRemoteNotification:. + This can be empty or nil. + */ ++ (void)trackAppOpenedWithRemoteNotificationPayload:(NSDictionary *)userInfo; + +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFAnonymousUtils.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFAnonymousUtils.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFAnonymousUtils.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFAnonymousUtils.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFCloud.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFCloud.h new file mode 100644 index 0000000..45f2421 --- /dev/null +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFCloud.h @@ -0,0 +1,47 @@ +// +// PFCloud.h +// Parse +// +// Created by Shyam Jayaraman on 8/20/12. +// Copyright (c) 2012 Parse Inc. All rights reserved. +// + +#import +#import "PFConstants.h" + +@interface PFCloud : NSObject + +/*! + Calls the given cloud function with the parameters passed in. + @param function The function name to call. + @param parameters The parameters to send to the function. + @result The response from the cloud function. + */ ++ (id)callFunction:(NSString *)function withParameters:(NSDictionary *)parameters; + +/*! + Calls the given cloud function with the parameters passed in and sets the error if there is one. + @param function The function name to call. + @param parameters The parameters to send to the function. + @param error Pointer to an NSError that will be set if necessary. + @result The response from the cloud function. This result could be a NSDictionary, an NSArray, NSInteger or NSString. + */ ++ (id)callFunction:(NSString *)function withParameters:(NSDictionary *)parameters error:(NSError **)error; + +/*! + Calls the given cloud function with the parameters provided asynchronously and calls the given block when it is done. + @param function The function name to call. + @param parameters The parameters to send to the function. + @param block The block to execute. The block should have the following argument signature:(id result, NSError *error). + */ ++ (void)callFunctionInBackground:(NSString *)function withParameters:(NSDictionary *)parameters block:(PFIdResultBlock)block; + +/*! + Calls the given cloud function with the parameters provided asynchronously and runs the callback when it is done. + @param function The function name to call. + @param parameters The parameters to send to the function. + @param target The object to call the selector on. + @param selector The selector to call. It should have the following signature: (void)callbackWithResult:(id) result error:(NSError *)error. result will be nil if error is set and vice versa. + */ ++ (void)callFunctionInBackground:(NSString *)function withParameters:(NSDictionary *)parameters target:(id)target selector:(SEL)selector; +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFConstants.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFConstants.h similarity index 90% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFConstants.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFConstants.h index b8cba6a..866b314 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFConstants.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFConstants.h @@ -6,10 +6,25 @@ @class PFUser; // Version -#define PARSE_VERSION @"1.0.64" +#define PARSE_VERSION @"1.2.10" extern NSInteger const PARSE_API_VERSION; +// Platform +#define PARSE_IOS_ONLY (TARGET_OS_IPHONE) +#define PARSE_OSX_ONLY (TARGET_OS_MAC && !(TARGET_OS_IPHONE)) + +extern NSString *const kPFDeviceType; + +#if PARSE_IOS_ONLY +#import +#else +#import +@compatibility_alias UIImage NSImage; +@compatibility_alias UIColor NSColor; +@compatibility_alias UIView NSView; +#endif + // Server extern NSString *const kPFParseServer; @@ -76,11 +91,15 @@ extern NSInteger const kPFErrorDuplicateValue; extern NSInteger const kPFErrorInvalidRoleName; /*! @abstract 140: Exceeded an application quota. Upgrade to resolve. */ extern NSInteger const kPFErrorExceededQuota; +/*! @abstract 141: Cloud Code script had an error. */ +extern NSInteger const kPFScriptError; +/*! @abstract 142: Cloud Code validation failed. */ +extern NSInteger const kPFValidationError; /*! @abstract 143: Product purchase receipt is missing */ extern NSInteger const kPFErrorReceiptMissing; /*! @abstract 144: Product purchase receipt is invalid */ extern NSInteger const kPFErrorInvalidPurchaseReceipt; -/*! @abstract 145: Paymnt is disabled on this device */ +/*! @abstract 145: Payment is disabled on this device */ extern NSInteger const kPFErrorPaymentDisabled; /*! @abstract 146: The product identifier is invalid */ extern NSInteger const kPFErrorInvalidProductIdentifier; @@ -94,6 +113,8 @@ extern NSInteger const kPFErrorProductDownloadFileSystemFailure; extern NSInteger const kPFErrorInvalidImageData; /*! @abstract 151: Unsaved file. */ extern NSInteger const kPFErrorUnsavedFile; +/*! @abstract 153: Fail to delete file. */ +extern NSInteger const kPFErrorFileDeleteFailure; /*! @abstract 200: Username is missing or empty */ extern NSInteger const kPFErrorUsernameMissing; diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFacebookUtils.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFacebookUtils.h similarity index 71% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFacebookUtils.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFacebookUtils.h index 1031d07..78748a1 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFacebookUtils.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFacebookUtils.h @@ -4,35 +4,51 @@ // #import -#import "PF_Facebook.h" +#import + #import "PFUser.h" #import "PFConstants.h" /*! Provides utility functions for working with Facebook in a Parse application. + + This class is currently for iOS only. */ @interface PFFacebookUtils : NSObject /** @name Interacting With Facebook */ /*! - Gets the instance of the Facebook object (from the Facebook SDK) that Parse uses. - @result The Facebook instance. + Gets the Facebook session for the current user. + */ ++ (FBSession *)session; + +/*! + Deprecated. Please call [PFFacebookUtils initializeFacebook] instead. + */ ++ (void)initializeWithApplicationId:(NSString *)appId __attribute__ ((deprecated)); + +/*! + Deprecated. Please call [PFFacebookUtils initializeFacebookWithUrlSchemeSuffix:] instead. */ -+ (PF_Facebook *)facebook; ++ (void)initializeWithApplicationId:(NSString *)appId + urlSchemeSuffix:(NSString *)urlSchemeSuffix __attribute__ ((deprecated)); /*! - Gets the instance of the Facebook object (from the Facebook SDK) that Parse uses. - @param delegate Specify your own delegate for the Facebook object. - @result The Facebook instance + Initializes the Facebook singleton. You must invoke this in order to use the Facebook functionality in Parse. + You must provide your Facebook application ID as the value for FacebookAppID in your bundle's plist file as + described here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/ */ -+ (PF_Facebook *)facebookWithDelegate:(NSObject *)delegate; ++ (void)initializeFacebook; /*! Initializes the Facebook singleton. You must invoke this in order to use the Facebook functionality in Parse. - @param appId The Facebook application id that you are using with your Parse application. + You must provide your Facebook application ID as the value for FacebookAppID in your bundle's plist file as + described here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/ + @param urlSchemeSuffix The URL suffix for this application - used when multiple applications with the same + Facebook application ID may be on the same device. */ -+ (void)initializeWithApplicationId:(NSString *)appId; ++ (void)initializeFacebookWithUrlShemeSuffix:(NSString *)urlSchemeSuffix; /*! Whether the user has their account linked to Facebook. @@ -47,10 +63,10 @@ Logs in a user using Facebook. This method delegates to the Facebook SDK to authenticate the user, and then automatically logs in (or creates, in the case where it is a new user) a PFUser. - @param permissions The permissions required for Facebook log in. This passed to the authorize method on + @param permissions The permissions required for Facebook log in. This passed to the authorize method on the Facebook instance. @param block The block to execute. The block should have the following argument signature: - (PFUser *user, NSError *error) + (PFUser *user, NSError *error) */ + (void)logInWithPermissions:(NSArray *)permissions block:(PFUserResultBlock)block; @@ -58,7 +74,7 @@ Logs in a user using Facebook. This method delegates to the Facebook SDK to authenticate the user, and then automatically logs in (or creates, in the case where it is a new user) a PFUser. The selector for the callback should look like: (PFUser *)user error:(NSError **)error - @param permissions The permissions required for Facebook log in. This passed to the authorize method on + @param permissions The permissions required for Facebook log in. This passed to the authorize method on the Facebook instance. @param target Target object for the selector @param selector The selector that will be called when the asynchronous request is complete. @@ -72,7 +88,7 @@ @param accessToken The access token for the user's session @param expirationDate The expiration date for the access token @param block The block to execute. The block should have the following argument signature: - (PFUser *user, NSError *error) + (PFUser *user, NSError *error) */ + (void)logInWithFacebookId:(NSString *)facebookId accessToken:(NSString *)accessToken @@ -101,7 +117,7 @@ Links Facebook to an existing PFUser. This method delegates to the Facebook SDK to authenticate the user, and then automatically links the account to the PFUser. @param user User to link to Facebook. - @param permissions The permissions required for Facebook log in. This passed to the authorize method on + @param permissions The permissions required for Facebook log in. This passed to the authorize method on the Facebook instance. */ + (void)linkUser:(PFUser *)user permissions:(NSArray *)permissions; @@ -110,10 +126,10 @@ Links Facebook to an existing PFUser. This method delegates to the Facebook SDK to authenticate the user, and then automatically links the account to the PFUser. @param user User to link to Facebook. - @param permissions The permissions required for Facebook log in. This passed to the authorize method on + @param permissions The permissions required for Facebook log in. This passed to the authorize method on the Facebook instance. @param block The block to execute. The block should have the following argument signature: - (BOOL *success, NSError *error) + (BOOL *success, NSError *error) */ + (void)linkUser:(PFUser *)user permissions:(NSArray *)permissions block:(PFBooleanResultBlock)block; @@ -122,7 +138,7 @@ the user, and then automatically links the account to the PFUser. The selector for the callback should look like: (NSNumber *)result error:(NSError *)error @param user User to link to Facebook. - @param permissions The permissions required for Facebook log in. This passed to the authorize method on + @param permissions The permissions required for Facebook log in. This passed to the authorize method on the Facebook instance. @param target Target object for the selector @param selector The selector that will be called when the asynchronous request is complete. @@ -137,7 +153,7 @@ @param accessToken The access token for the user's session @param expirationDate The expiration date for the access token @param block The block to execute. The block should have the following argument signature: - (BOOL *success, NSError *error) + (BOOL *success, NSError *error) */ + (void)linkUser:(PFUser *)user facebookId:(NSString *)facebookId @@ -166,14 +182,14 @@ /** @name Unlinking Users from Facebook */ /*! - Unlinks the PFUser from a Facebook account. + Unlinks the PFUser from a Facebook account. @param user User to unlink from Facebook. @result Returns true if the unlink was successful. */ + (BOOL)unlinkUser:(PFUser *)user; /*! - Unlinks the PFUser from a Facebook account. + Unlinks the PFUser from a Facebook account. @param user User to unlink from Facebook. @param error Error object to set on error. @result Returns true if the unlink was successful. @@ -181,72 +197,55 @@ + (BOOL)unlinkUser:(PFUser *)user error:(NSError **)error; /*! - Makes an asynchronous request to unlink a user from a Facebook account. + Makes an asynchronous request to unlink a user from a Facebook account. @param user User to unlink from Facebook. */ + (void)unlinkUserInBackground:(PFUser *)user; /*! - Makes an asynchronous request to unlink a user from a Facebook account. + Makes an asynchronous request to unlink a user from a Facebook account. @param user User to unlink from Facebook. - @param block The block to execute. The block should have the following argument signature: (BOOL succeeded, NSError *error) + @param block The block to execute. The block should have the following argument signature: (BOOL succeeded, NSError *error) */ + (void)unlinkUserInBackground:(PFUser *)user block:(PFBooleanResultBlock)block; /*! - Makes an asynchronous request to unlink a user from a Facebook account. + Makes an asynchronous request to unlink a user from a Facebook account. @param user User to unlink from Facebook @param target Target object for the selector @param selector The selector that will be called when the asynchronous request is complete. */ + (void)unlinkUserInBackground:(PFUser *)user target:(id)target selector:(SEL)selector; -/** @name Extending Facebook Access Tokens */ +/** @name Obtaining new permissions */ /*! - Whether the user has a Facebook access token that needs to be extended. - @param user User that is linked to Facebook and should be checked for access token extension. - @result True if the access token needs to be extended. + Requests new Facebook publish permissions for the given user. This may prompt the user to + reauthorize the application. The user will be saved as part of this operation. + @param user User to request new permissions for. The user must be linked to Facebook. + @param permissions The new publishing permissions to request. + @param audience The default audience for publishing permissions to request. + @param block The block to execute. The block should have the following argument signature: (BOOL succeeded, NSError *error) */ -+ (BOOL)shouldExtendAccessTokenForUser:(PFUser *)user; ++ (void)reauthorizeUser:(PFUser *)user + withPublishPermissions:(NSArray *)permissions + audience:(FBSessionDefaultAudience)audience + block:(PFBooleanResultBlock)block; /*! - Extends the access token for a user using Facebook, and saves the refreshed access token back to the PFUser. - The selector for the callback should look like: (NSNumber *)result error:(NSError *)error - @param user User whose access token should be extended + Requests new Facebook publish permissions for the given user. This may prompt the user to + reauthorize the application. The user will be saved as part of this operation. + @param user User to request new permissions for. The user must be linked to Facebook. + @param permissions The new publishing permissions to request. + @param audience The default audience for publishing permissions to request. @param target Target object for the selector @param selector The selector that will be called when the asynchronous request is complete. */ -+ (void)extendAccessTokenForUser:(PFUser *)user target:(id)target selector:(SEL)selector; - -/*! - Extends the access token for a user using Facebook, and saves the refreshed access token back to the PFUser. - @param user User whose access token should be extended - @param block The block to execute. The block should have the following argument signature: - (BOOL success, NSError *error) - */ -+ (void)extendAccessTokenForUser:(PFUser *)user block:(PFBooleanResultBlock)block; - -/*! - If necessary, extends the access token for a user using Facebook, and saves the refreshed - access token back to the PFUser. We recommend invoking this from applicationDidBecomeActive: in your AppDelegate. - The selector for the callback should look like: (NSNumber *)result error:(NSError *)error - @param user User whose access token should be extended - @param target Target object for the selector - @param selector The selector that will be called when the asynchronous request is complete. - @result True if the access token needed to be extended. - */ -+ (BOOL)extendAccessTokenIfNeededForUser:(PFUser *)user target:(id)target selector:(SEL)selector; - -/*! - If necessary, extends the access token for a user using Facebook, and saves the refreshed - access token back to the PFUser. We recommend invoking this from applicationDidBecomeActive: in your AppDelegate. - @param user User whose access token should be extended - @param block The block to execute. The block should have the following argument signature: - (BOOL success, NSError *error) - @result True if the access token needed to be extended. - */ -+ (BOOL)extendAccessTokenIfNeededForUser:(PFUser *)user block:(PFBooleanResultBlock)block; ++ (void)reauthorizeUser:(PFUser *)user + withPublishPermissions:(NSArray *)permissions + audience:(FBSessionDefaultAudience)audience + target:(id)target + selector:(SEL)selector; /** @name Delegating URL Actions */ diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFile.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFile.h similarity index 95% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFile.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFile.h index b0dff40..c63e19d 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFFile.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFFile.h @@ -13,10 +13,7 @@ A file of binary data stored on the Parse servers. This can be a image, video, or anything else that an application needs to reference in a non-relational way. */ -@interface PFFile : NSObject { - NSString *name; - NSString *url; -} +@interface PFFile : NSObject /** @name Creating a PFFile */ @@ -46,12 +43,12 @@ /*! The name of the file. */ -@property (readonly) NSString *name; +@property (assign, readonly) NSString *name; /*! The url of the file. */ -@property (readonly) NSString *url; +@property (assign, readonly) NSString *url; /** @name Storing Data with Parse */ @@ -75,7 +72,6 @@ The name of the file. /*! Saves the file asynchronously. - @result Returns whether the save succeeded. */ - (void)saveInBackground; @@ -161,7 +157,7 @@ The name of the file. Asynchronously gets the data from cache if available or fetches its contents from the Parse servers. Executes the resultBlock upon completion or error. Executes the progressBlock periodically with the percent progress. progressBlock will get called with 100 before resultBlock is called. - @param block The block should have the following argument signature: (NSData *result, NSError *error) + @param resultBlock The block should have the following argument signature: (NSData *result, NSError *error) @param progressBlock The block should have the following argument signature: (int percentDone) */ - (void)getDataInBackgroundWithBlock:(PFDataResultBlock)resultBlock @@ -192,4 +188,4 @@ The name of the file. */ - (void)cancel; -@end \ No newline at end of file +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFGeoPoint.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFGeoPoint.h similarity index 74% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFGeoPoint.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFGeoPoint.h index 7a5605d..f3ed279 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFGeoPoint.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFGeoPoint.h @@ -7,6 +7,7 @@ // #import +#import /*! Object which may be used to embed a latitude / longitude point as the value for a key in a PFObject. @@ -17,10 +18,7 @@ Currently, object classes may only have one key associated with a GeoPoint type. */ -@interface PFGeoPoint : NSObject { - double latitude; - double longitude; -} +@interface PFGeoPoint : NSObject /** @name Creating a PFGeoPoint */ /*! @@ -29,6 +27,14 @@ */ + (PFGeoPoint *)geoPoint; +/*! + Creates a new PFGeoPoint object for the given CLLocation, set to the location's + coordinates. + @param location CLLocation object, with set latitude and longitude. + @result Returns a new PFGeoPoint at specified location. + */ ++ (PFGeoPoint *)geoPointWithLocation:(CLLocation *)location; + /*! Creates a new PFGeoPoint object with the specified latitude and longitude. @param latitude Latitude of point in degrees. @@ -37,6 +43,14 @@ */ + (PFGeoPoint *)geoPointWithLatitude:(double)latitude longitude:(double)longitude; +/*! + Fetches the user's current location and returns a new PFGeoPoint object via the + provided block. + @param geoPointHandler A block which takes the newly created PFGeoPoint as an + argument. + */ ++ (void)geoPointForCurrentLocationInBackground:(void(^)(PFGeoPoint *geoPoint, NSError *error))geoPointHandler; + /** @name Controlling Position */ /// Latitude of point in degrees. Valid range (-90.0, 90.0). diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFImageView.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFImageView.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFImageView.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFImageView.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFInstallation.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFInstallation.h similarity index 77% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFInstallation.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFInstallation.h index 096d0d4..0726222 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFInstallation.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFInstallation.h @@ -8,7 +8,7 @@ #import #import "PFObject.h" -#import "PFQuery.h" +#import "PFSubclassing.h" /*! A Parse Framework Installation Object that is a local representation of an @@ -26,10 +26,25 @@ PFInstallation objects which have a valid deviceToken and are saved to the Parse cloud can be used to target push notifications. + + This class is currently for iOS only. There is no PFInstallation for Parse + applications running on OS X, because they cannot receive push notifications. */ -@interface PFInstallation : PFObject { -} +@interface PFInstallation : PFObject + +/*! The name of the Installation class in the REST API. This is a required + * PFSubclassing method */ ++ (NSString *)parseClassName; + +/** @name Targeting Installations */ + +/*! + Creates a query for PFInstallation objects. The resulting query can only + be used for targeting a PFPush. Calling find methods on the resulting query + will raise an exception. + */ ++ (PFQuery *)query; /** @name Accessing the Current Installation */ @@ -37,23 +52,18 @@ Gets the currently-running installation from disk and returns an instance of it. If this installation is not stored on disk, returns a PFInstallation with deviceType and installationId fields set to those of the - current installation, and a deviceToken field set to the value stored by - [PFPush storeDeviceToken:]. In the latter case, if this installation matches - one in the Parse cloud, then calling save will fill in this installation's - objectId instead of creating a new installation. + current installation. @result Returns a PFInstallation that represents the currently-running installation. */ -+ (PFInstallation *)currentInstallation; - -/** @name Targeting Installations */ ++ (instancetype)currentInstallation; /*! - Creates a query for PFInstallation objects. The resulting query can only - be used for targeting a PFPush. Calling find methods on the resulting query - will raise an exception. + Sets the device token string property from an NSData-encoded token. */ -+ (PFQuery *)query; +- (void)setDeviceTokenFromData:(NSData *)deviceTokenData; + +/** @name Properties */ /// The device type for the PFInstallation. @property (nonatomic, readonly, retain) NSString *deviceType; @@ -62,10 +72,10 @@ @property (nonatomic, readonly, retain) NSString *installationId; /// The device token for the PFInstallation. -@property (nonatomic, readonly, retain) NSString *deviceToken; +@property (nonatomic, retain) NSString *deviceToken; /// The badge for the PFInstallation. -@property (nonatomic, readonly, retain) NSNumber *badge; +@property (nonatomic, assign) NSInteger badge; /// The timeZone for the PFInstallation. @property (nonatomic, readonly, retain) NSString *timeZone; diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFLogInView.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFLogInView.h similarity index 89% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFLogInView.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFLogInView.h index a4deebf..17a33e3 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFLogInView.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFLogInView.h @@ -67,6 +67,12 @@ typedef enum { /// The dismiss button. It is nil if the element is not enabled. @property (nonatomic, readonly, retain) UIButton *dismissButton; +/// The facebook/twitter login label. It is only shown if the external login is enabled. +@property (nonatomic, readonly, retain) UILabel *externalLogInLabel; + +/// The sign up label. It is only shown if sign up button is enabled. +@property (nonatomic, readonly, retain) UILabel *signUpLabel; + @end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFLogInViewController.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFLogInViewController.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFLogInViewController.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFLogInViewController.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject+Subclass.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject+Subclass.h new file mode 100644 index 0000000..6b99490 --- /dev/null +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject+Subclass.h @@ -0,0 +1,85 @@ +// +// PFObject+Subclass.h +// Parse +// +// Created by Thomas Bouldin on 2/17/13. +// Copyright (c) 2013 Parse Inc. All rights reserved. +// + +#import "PFObject.h" + +@class PFQuery; + +/*! +

Subclassing Notes

+ + Developers can subclass PFObject for a more native object-oriented class structure. Strongly-typed subclasses of PFObject must conform to the PFSubclassing protocol and must call registerSubclass to be returned by PFQuery and other PFObject factories. All methods in PFSubclassing except for [PFSubclassing parseClassName] are already implemented in the PFObject(Subclass) category. Inculding PFObject+Subclass.h in your implementation file provides these implementations automatically. + + Subclasses support simpler initializers, query syntax, and dynamic synthesizers. The following shows an example subclass: + + @interface MYGame : PFObject< PFSubclassing > + // Accessing this property is the same as objectForKey:@"title" + @property (retain) NSString *title; + + (NSString *)parseClassName; + @end + + @implementation MYGame + @dynamic title; + + (NSString *)parseClassName { + return @"Game"; + } + @end + + MYGame *game = [[MYGame alloc] init]; + game.title = @"Bughouse"; + [game saveInBackground]; + + */ +@interface PFObject(Subclass) + +/*! @name Methods for Subclasses */ + +/*! + Designated initializer for subclasses. + This method can only be called on subclasses which conform to PFSubclassing. + This method should not be overridden. + */ +- (id)init; + +/*! + Creates an instance of the registered subclass with this class's parseClassName. + This helps a subclass ensure that it can be subclassed itself. For example, [PFUser object] will + return a MyUser object if MyUser is a registered subclass of PFUser. For this reason, [MyClass object] is + preferred to [[MyClass alloc] init]. + This method can only be called on subclasses which conform to PFSubclassing. + A default implementation is provided by PFObject which should always be sufficient. + */ ++ (instancetype)object; + +/*! + Creates a reference to an existing PFObject for use in creating associations between PFObjects. Calling isDataAvailable on this + object will return NO until fetchIfNeeded or refresh has been called. No network request will be made. + This method can only be called on subclasses which conform to PFSubclassing. + A default implementation is provided by PFObject which should always be sufficient. + @param objectId The object id for the referenced object. + @result A PFObject without data. + */ ++ (id)objectWithoutDataWithObjectId:(NSString *)objectId; + +/*! + Registers an Objective-C class for Parse to use for representing a given Parse class. + Once this is called on a PFObject subclass, any PFObject Parse creates with a class + name matching [self parseClassName] will be an instance of subclass. + This method can only be called on subclasses which conform to PFSubclassing. + A default implementation is provided by PFObject which should always be sufficient. + */ ++ (void)registerSubclass; + +/*! + Returns a query for objects of type +parseClassName. + This method can only be called on subclasses which conform to PFSubclassing. + A default implementation is provided by PFObject which should always be sufficient. + */ ++ (PFQuery *)query; + +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFObject.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject.h similarity index 90% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFObject.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject.h index 780ff8a..67daaf2 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFObject.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFObject.h @@ -5,38 +5,31 @@ #import "PFACL.h" #import "PFConstants.h" +@protocol PFSubclassing; + /*! - A Parse Framework Object that is a local representation of data persisted to the Parse cloud. This is the - main class that is used to interact with objects in your app. + A Parse Framework Object that is a local representation of data persisted to the Parse cloud. + This is the main class that is used to interact with objects in your app. */ -@class PFOperation; @class PFRelation; +@class PFTask; +NS_REQUIRES_PROPERTY_DEFINITIONS @interface PFObject : NSObject { BOOL dirty; - BOOL hasBeenFetched; - - PFOperation *currentOperation; - - NSString *objectId; - NSString *className; - - NSMutableDictionary *dataAvailability; - - NSMutableDictionary *data; - NSMutableDictionary *operations; - - // A dictionary that maps id (objects) => PFJSONCache - NSMutableDictionary *hashedObjectsCache; - - // A set of dirty keys (strings) - NSMutableSet *dirtyKeys; - - NSDate *updatedAt; - NSDate *createdAt; - - // Whether there is a save in progress. - BOOL isSaving; + + // An array of NSDictionary of NSString -> PFFieldOperation. + // Each dictionary has a subset of the object's keys as keys, and the + // changes to the value for that key as its value. + // There is always at least one dictionary of pending operations. + // Every time a save is started, a new dictionary is added to the end. + // Whenever a save completes, the new data is put into fetchedData, and + // a dictionary is removed from the start. + NSMutableArray *operationSetQueue; + + // Our best estimate as to what the current data is, based on + // the last fetch from the server, and the set of pending operations. + NSMutableDictionary *estimatedData; } #pragma mark Constructors @@ -48,7 +41,7 @@ @param className A class name can be any alphanumeric string that begins with a letter. It represents an object in your app, like a User of a Document. @result Returns the object that is instantiated with the given class name. */ -+ (PFObject *)objectWithClassName:(NSString *)className; ++ (instancetype)objectWithClassName:(NSString *)className; /*! Creates a reference to an existing PFObject for use in creating associations between PFObjects. Calling isDataAvailable on this @@ -58,8 +51,16 @@ @param objectId The object id for the referenced object. @result A PFObject without data. */ -+ (PFObject *)objectWithoutDataWithClassName:(NSString *)className - objectId:(NSString *)objectId; ++ (instancetype)objectWithoutDataWithClassName:(NSString *)className + objectId:(NSString *)objectId; + +/*! + Creates a new PFObject with a class name, initialized with data constructed from the specified set of objects and keys. + @param className The object's class. + @param dictionary An NSDictionary of keys and objects to set on the new PFObject. + @result A PFObject with the given class name and set with the given data. + */ ++ (PFObject *)objectWithClassName:(NSString *)className dictionary:(NSDictionary *)dictionary; /*! Initializes a new PFObject with a class name. @@ -73,6 +74,11 @@ /*! @name Managing Object Properties */ +/*! + The class name of the object. + */ +@property (readonly) NSString *parseClassName; + /*! The id of the object. */ @@ -81,17 +87,12 @@ /*! When the object was last updated. */ -@property (readonly) NSDate *updatedAt; +@property (nonatomic, retain, readonly) NSDate *updatedAt; /*! When the object was created. */ -@property (readonly) NSDate *createdAt; - -/*! - The class name of the object. - */ -@property (readonly) NSString *className; +@property (nonatomic, retain, readonly) NSDate *createdAt; /*! The ACL for this object. @@ -325,6 +326,9 @@ */ - (BOOL)isDataAvailable; +#if PARSE_IOS_ONLY +// Deprecated and intentionally not available on the new OS X SDK + /*! Refreshes the PFObject with the current data from the server. */ @@ -338,7 +342,7 @@ /*! Refreshes the PFObject asynchronously and executes the given callback block. - @param block The block to execute. The block should have the following argument signature: (PFObject *object, NSError *error) + @param block The block to execute. The block should have the following argument signature: (PFObject *object, NSError *error) */ - (void)refreshInBackgroundWithBlock:(PFObjectResultBlock)block; @@ -348,6 +352,7 @@ @param selector The selector to call. It should have the following signature: (void)callbackWithResult:(PFObject *)refreshedObject error:(NSError *)error. error will be nil on success and set if there was an error. refreshedObject will be the PFObject with the refreshed data. */ - (void)refreshInBackgroundWithTarget:(id)target selector:(SEL)selector; +#endif /*! Fetches the PFObject with the current data from the server. diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFProduct.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFProduct.h similarity index 85% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFProduct.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFProduct.h index 83eb858..a74cded 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFProduct.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFProduct.h @@ -7,6 +7,7 @@ // #import "PFObject.h" +#import "PFSubclassing.h" #import "PFFile.h" /*! @@ -14,8 +15,14 @@ By default, products can only be created via the data browser; saving a PFProduct will result in error. However, the products' metadata information can be queried and viewed. + + This class is currently for iOS only. */ -@interface PFProduct : PFObject +@interface PFProduct : PFObject + +/*! The name of the Product class in the REST API. This is a required + * PFSubclassing method */ ++ (NSString *)parseClassName; /** @name Querying for Products */ /*! diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFProductTableViewController.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFProductTableViewController.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFProductTableViewController.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFProductTableViewController.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPurchase.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPurchase.h similarity index 96% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPurchase.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPurchase.h index 399ff4f..5397a09 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPurchase.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPurchase.h @@ -12,6 +12,8 @@ /*! PFPurchase provides a set of APIs for working with in-app purchases. + + This class is currently for iOS only. */ @interface PFPurchase : NSObject @@ -35,7 +37,7 @@ /*! Asynchronously download the purchased asset, which is stored on Parse's server. - Parse verifies the receipt with Apple and delivers the content only if the receipt is invalid. + Parse verifies the receipt with Apple and delivers the content only if the receipt is valid. @param transaction the transaction, which contains the receipt. @param completion the completion block. */ @@ -43,7 +45,7 @@ /*! Asynchronously download the purchased asset, which is stored on Parse's server. - Parse verifies the receipt with Apple and delivers the content only if the receipt is invalid. + Parse verifies the receipt with Apple and delivers the content only if the receipt is valid. @param transaction the transaction, which contains the receipt. @param completion the completion block. @param progress the progress block, which is called multiple times to reveal progress of the download. diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPurchaseTableViewCell.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPurchaseTableViewCell.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPurchaseTableViewCell.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPurchaseTableViewCell.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPush.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPush.h similarity index 80% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPush.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPush.h index 991a97c..d124a42 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFPush.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFPush.h @@ -17,9 +17,17 @@ The preferred way of modifying or retrieving channel subscriptions is to use the PFInstallation class, instead of the class methods in PFPush. + + This class is currently for iOS only. Parse does not handle Push Notifications + to Parse applications running on OS X. Push Notifications can be sent from OS X + applications via Cloud Code or the REST API to push-enabled devices (e.g. iOS + or Android). */ @interface PFPush : NSObject +/*! @name Creating a Push Notification */ ++ (PFPush *)push; + /*! @name Configuring a Push Notification */ /*! @@ -61,14 +69,14 @@ - (void)setData:(NSDictionary *)data; /*! - Sets whether this push will go to Android devices. Defaults to true. + Deprecated. Please use a PFInstallation.query with a constraint on deviceType. */ -- (void)setPushToAndroid:(BOOL)pushToAndroid; +- (void)setPushToAndroid:(BOOL)pushToAndroid __attribute__ ((deprecated)); /*! - Sets whether this push will go to iOS devices. Defaults to true. + Deprecated. Please use a PFInstallation.query with a constraint on deviceType. */ -- (void)setPushToIOS:(BOOL)pushToIOS; +- (void)setPushToIOS:(BOOL)pushToIOS __attribute__ ((deprecated)); /*! Sets the expiration time for this notification. The notification will be @@ -144,6 +152,38 @@ target:(id)target selector:(SEL)selector; +/*! + Send a push message to a query. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param message The message to send. + @param error Pointer to an NSError that will be set if necessary. + @result Returns whether the send succeeded. + */ ++ (BOOL)sendPushMessageToQuery:(PFQuery *)query + withMessage:(NSString *)message + error:(NSError **)error; + +/*! + Asynchronously send a push message to a query. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param message The message to send. + */ ++ (void)sendPushMessageToQueryInBackground:(PFQuery *)query + withMessage:(NSString *)message; + +/*! + Asynchronously sends a push message to a query and calls the given block. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param message The message to send. + @param block The block to execute. The block should have the following argument signature: (BOOL succeeded, NSError *error) + */ ++ (void)sendPushMessageToQueryInBackground:(PFQuery *)query + withMessage:(NSString *)message + block:(PFBooleanResultBlock)block; + /*! Send this push message. @param error Pointer to an NSError that will be set if necessary. @@ -214,6 +254,38 @@ target:(id)target selector:(SEL)selector; +/*! + Send a push message with arbitrary data to a query. See the guide for information about the dictionary structure. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param data The data to send. + @param error Pointer to an NSError that will be set if necessary. + @result Returns whether the send succeeded. + */ ++ (BOOL)sendPushDataToQuery:(PFQuery *)query + withData:(NSDictionary *)data + error:(NSError **)error; + +/*! + Asynchronously send a push message with arbitrary data to a query. See the guide for information about the dictionary structure. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param data The data to send. + */ ++ (void)sendPushDataToQueryInBackground:(PFQuery *)query + withData:(NSDictionary *)data; + +/*! + Asynchronously sends a push message with arbitrary data to a query and calls the given block. See the guide for information about the dictionary structure. + @param query The query to send to. The query must be a PFInstallation query + created with [PFInstallation query]. + @param data The data to send. + @param block The block to execute. The block should have the following argument signature: (BOOL succeeded, NSError *error) + */ ++ (void)sendPushDataToQueryInBackground:(PFQuery *)query + withData:(NSDictionary *)data + block:(PFBooleanResultBlock)block; + /*! @name Handling Notifications */ /*! diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQuery.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQuery.h similarity index 87% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQuery.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQuery.h index a6ce3b0..b18fe16 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQuery.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQuery.h @@ -9,22 +9,7 @@ /*! A class that defines a query that is used to query for PFObjects. */ -@class PFOperation; -@interface PFQuery : NSObject { - PFOperation *currentOperation; - - NSString *className; - NSMutableDictionary *where; - NSMutableArray *include; - NSInteger limit; - NSInteger skip; - NSString *order; - PFCachePolicy cachePolicy; - BOOL trace; - NSDate *queryStart; - NSDate *querySent; - NSDate *queryReceived; -} +@interface PFQuery : NSObject #pragma mark Query options @@ -37,6 +22,26 @@ */ + (PFQuery *)queryWithClassName:(NSString *)className; +/*! + Creates a PFQuery with the constraints given by predicate. + + The following types of predicates are supported: + * Simple comparisons such as =, !=, <, >, <=, >=, and BETWEEN with a key and a constant. + * Containment predicates, such as "x IN {1, 2, 3}". + * Key-existence predicates, such as "x IN SELF". + * BEGINSWITH expressions. + * Compound predicates with AND, OR, and NOT. + * SubQueries with "key IN %@", subquery. + + The following types of predicates are NOT supported: + * Aggregate operations, such as ANY, SOME, ALL, or NONE. + * Regular expressions, such as LIKE, MATCHES, CONTAINS, or ENDSWITH. + * Predicates comparing one key to another. + * Complex predicates with many ORed clauses. + + */ ++ (PFQuery *)queryWithClassName:(NSString *)className predicate:(NSPredicate *)predicate; + /*! Initializes the query with a class name. @param newClassName The class name. @@ -46,7 +51,7 @@ /*! The class name to query for */ -@property (nonatomic, retain) NSString *className; +@property (nonatomic, retain) NSString *parseClassName; /** @name Adding Basic Constraints */ @@ -58,6 +63,13 @@ */ - (void)includeKey:(NSString *)key; +/*! + Make the query restrict the fields of the returned PFObjects to include only the provided keys. + If this is called multiple times, then all of the keys specified in each of the calls will be included. + @param keys The keys to include in the result. + */ +- (void)selectKeys:(NSArray *)keys; + /*! Add a constraint that requires a particular key exists. @param key The key that should exist. @@ -126,6 +138,13 @@ */ - (void)whereKey:(NSString *)key notContainedIn:(NSArray *)array; +/*! + Add a constraint to the query that requires a particular key's array contains every element of the provided array. + @param key The key to be constrained. + @param array The array of values to search for. + */ +- (void)whereKey:(NSString *)key containsAllObjectsInArray:(NSArray *)array; + /** @name Adding Location Constraints */ /*! @@ -237,6 +256,15 @@ */ - (void)whereKey:(NSString *)key matchesKey:(NSString *)otherKey inQuery:(PFQuery *)query; +/*! + Adds a constraint that requires that a key's value NOT match a value in another key + in objects returned by a sub query. + @param key The key that the value is stored + @param otherKey The key in objects in the returned by the sub query whose value should match + @param query The query to run. + */ +- (void)whereKey:(NSString *)key doesNotMatchKey:(NSString *)otherKey inQuery:(PFQuery *)query; + /*! Add a constraint that requires that a key's value matches a PFQuery constraint. This only works where the key's values are PFObjects or arrays of PFObjects. @@ -252,6 +280,7 @@ @param query The query the value should not match */ - (void)whereKey:(NSString *)key doesNotMatchQuery:(PFQuery *)query; + #pragma mark - #pragma mark Sorting @@ -282,6 +311,18 @@ */ - (void)addDescendingOrder:(NSString *)key; +/*! + Sort the results in descending order with the given descriptor. + @param sortDescriptor The NSSortDescriptor to order by. + */ +- (void)orderBySortDescriptor:(NSSortDescriptor *)sortDescriptor; + +/*! + Sort the results in descending order with the given descriptors. + @param sortDescriptors An NSArray of NSSortDescriptor instances to order by. + */ +- (void)orderBySortDescriptors:(NSArray *)sortDescriptors; + #pragma mark - #pragma mark Get methods @@ -490,7 +531,10 @@ /** @name Paginating Results */ /*! - A limit on the number of objects to return. Note: If you are calling findObject with limit=1, you may find it easier to use getFirst instead. + A limit on the number of objects to return. The default limit is 100, with a + maximum of 1000 results being returned at a time. + + Note: If you are calling findObject with limit=1, you may find it easier to use getFirst instead. */ @property (nonatomic) NSInteger limit; @@ -530,7 +574,7 @@ */ + (void)clearAllCachedResults; -#pragma mark - +#pragma mark - Advanced Settings /** @name Advanced Settings */ diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQueryTableViewController.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQueryTableViewController.h similarity index 84% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQueryTableViewController.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQueryTableViewController.h index a00e53d..956b97c 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFQueryTableViewController.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFQueryTableViewController.h @@ -7,21 +7,14 @@ // #import -#import "Parse.h" -#import "PF_EGORefreshTableHeaderView.h" +#import "PFQuery.h" #import "PFTableViewCell.h" +#import "PF_EGORefreshTableHeaderView.h" -@interface PFQueryTableViewController : UIViewController +@interface PFQueryTableViewController : UITableViewController /*! @name Creating a PFQueryTableViewController */ -/*! - Initializes a query table view controller with the given style. - @param style The UITableViewStyle for the table - @result The initialized PFQueryTableViewController - */ -- (id)initWithStyle:(UITableViewStyle)otherStyle; - /*! The designated initializer. Initializes with a class name of the PFObjects that will be associated with this table. @@ -40,11 +33,8 @@ /*! @name Configuring Behavior */ -/// The table view managed by the controller object -@property (nonatomic, retain) UITableView *tableView; - /// The class of the PFObject this table will use as a datasource -@property (nonatomic, retain) NSString *className; +@property (nonatomic, retain) NSString *parseClassName; /// The key to use to display for the cell text label. This won't apply if you override tableView:cellForRowAtIndexPath:object: @property (nonatomic, retain) NSString *textKey; @@ -70,15 +60,6 @@ /// Whether the table is actively loading new data from the server @property (nonatomic, assign) BOOL isLoading; -/** - A Boolean value indicating if the controller clears the selection when the table appears. - - The default value of this property is YES. When YES, the table view controller clears the table's - current selection when it receives a viewWillAppear: message. Setting this property to `NO` - preserves the selection. - */ -@property (nonatomic) BOOL clearsSelectionOnViewWillAppear; - /*! @name Responding to Events */ /*! @@ -106,7 +87,7 @@ @param indexPath The indexPath @result The object at the specified index */ -- (PFObject *)objectAtIndex:(NSIndexPath *)indexPath; +- (PFObject *)objectAtIndexPath:(NSIndexPath *)indexPath; /*! @name Querying */ diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRelation.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRelation.h similarity index 79% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRelation.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRelation.h index 8b77804..7850026 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRelation.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRelation.h @@ -14,17 +14,9 @@ A class that is used to access all of the children of a many-to-many relationship. Each instance of PFRelation is associated with a particular parent object and key. */ -@interface PFRelation : NSObject { - PFObject *parent; - NSString *key; - NSString *targetClass; - NSMutableSet *relationsToAdd; - NSMutableSet *relationsToRemove; -} +@interface PFRelation : NSObject @property (nonatomic, retain) NSString *targetClass; -@property (nonatomic, retain, readonly) NSString *key; - #pragma mark Accessing objects diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRole.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRole.h similarity index 88% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRole.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRole.h index 7ae5c13..c6b3cad 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFRole.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFRole.h @@ -7,9 +7,9 @@ // #import -#import "PFObject.h" -@class PFQuery; +#import "PFObject.h" +#import "PFSubclassing.h" /*! Represents a Role on the Parse server. PFRoles represent groupings @@ -21,7 +21,7 @@ Roles must have a name (which cannot be changed after creation of the role), and must specify an ACL. */ -@interface PFRole : PFObject +@interface PFRole : PFObject #pragma mark Creating a New Role @@ -49,7 +49,7 @@ @param name The name of the Role to create. */ -+ (PFRole *)roleWithName:(NSString *)name; ++ (instancetype)roleWithName:(NSString *)name; /*! Constructs a new PFRole with the given name. @@ -57,7 +57,7 @@ @param name The name of the Role to create. @param acl The ACL for this role. Roles must have an ACL. */ -+ (PFRole *)roleWithName:(NSString *)name acl:(PFACL *)acl; ++ (instancetype)roleWithName:(NSString *)name acl:(PFACL *)acl; #pragma mark - #pragma mark Role-specific Properties @@ -78,20 +78,16 @@ These users are granted any privileges that this role has been granted (e.g. read or write access through ACLs). You can add or remove users from the role through this relation. - - @return the relation for the users belonging to this role. */ -- (PFRelation *)users; +@property (nonatomic, readonly, retain) PFRelation *users; /*! Gets the PFRelation for the PFRoles that are direct children of this role. These roles' users are granted any privileges that this role has been granted (e.g. read or write access through ACLs). You can add or remove child roles from this role through this relation. - - @return the relation for the roles belonging to this role. */ -- (PFRelation *)roles; +@property (nonatomic, readonly, retain) PFRelation *roles; #pragma mark - #pragma mark Querying for Roles diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFSignUpView.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSignUpView.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFSignUpView.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSignUpView.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFSignUpViewController.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSignUpViewController.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFSignUpViewController.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSignUpViewController.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSubclassing.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSubclassing.h new file mode 100644 index 0000000..09404c8 --- /dev/null +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFSubclassing.h @@ -0,0 +1,54 @@ +// +// PFSubclassing.h +// Parse +// +// Created by Thomas Bouldin on 3/11/13. +// Copyright (c) 2013 Parse Inc. All rights reserved. +// + +#import + +@class PFQuery; + +/*! + If a subclass of PFObject conforms to PFSubclassing and calls registerSubclass, Parse will be able to use that class as the native class for a Parse cloud object. + + Classes conforming to this protocol should subclass PFObject and include PFObject+Subclass.h in their implementation file. This ensures the methods in the Subclass category of PFObject are exposed in its subclasses only. + */ +@protocol PFSubclassing + +/*! + Constructs an object of the most specific class known to implement parseClassName. + This method takes care to help PFObject subclasses be subclassed themselves. + For example, [PFUser object] returns a PFUser by default but will return an + object of a registered subclass instead if one is known. + A default implementation is provided by PFObject which should always be sufficient. + @result Returns the object that is instantiated. + */ ++ (id)object; + +/*! + Creates a reference to an existing PFObject for use in creating associations between PFObjects. Calling isDataAvailable on this + object will return NO until fetchIfNeeded or refresh has been called. No network request will be made. + A default implementation is provided by PFObject which should always be sufficient. + @param objectId The object id for the referenced object. + @result A PFObject without data. + */ ++ (id)objectWithoutDataWithObjectId:(NSString *)objectId; + +/*! The name of the class as seen in the REST API. */ ++ (NSString *)parseClassName; + +/*! + Create a query which returns objects of this type. + A default implementation is provided by PFObject which should always be sufficient. + */ ++ (PFQuery *)query; + +/*! + Lets Parse know this class should be used to instantiate all objects with class type parseClassName. + This method must be called before [Parse setApplicationId:clientKey:] + */ ++ (void)registerSubclass; + +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFTableViewCell.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFTableViewCell.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFTableViewCell.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFTableViewCell.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFTwitterUtils.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFTwitterUtils.h similarity index 99% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFTwitterUtils.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFTwitterUtils.h index b66255a..096581c 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFTwitterUtils.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFTwitterUtils.h @@ -10,6 +10,8 @@ /*! Provides utility functions for working with Twitter in a Parse application. + + This class is currently for iOS only. */ @interface PFTwitterUtils : NSObject diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFUser.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFUser.h similarity index 78% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFUser.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFUser.h index 97b7264..5af8397 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PFUser.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PFUser.h @@ -2,8 +2,9 @@ // Copyright 2011 Parse, Inc. All rights reserved. #import +#import "PFConstants.h" #import "PFObject.h" -#import "PF_Facebook.h" +#import "PFSubclassing.h" @class PFQuery; @@ -16,12 +17,11 @@ A Parse Framework User Object that is a local representation of a user persisted utilities for each social network. See PFFacebookUtils and PFTwitterUtils for more information. */ +@interface PFUser : PFObject -@interface PFUser : PFObject { - NSString *password; - NSString *sessionToken; - BOOL isNew; -} +/*! The name of the PFUser class in the REST API. This is a required + * PFSubclassing method */ ++ (NSString *)parseClassName; /** @name Accessing the Current User */ @@ -29,12 +29,12 @@ A Parse Framework User Object that is a local representation of a user persisted Gets the currently logged in user from disk and returns an instance of it. @result Returns a PFUser that is the currently logged in user. If there is none, returns nil. */ -+ (PFUser *)currentUser; ++ (instancetype)currentUser; /// The session token for the PFUser. This is set by the server upon successful authentication. @property (nonatomic, retain) NSString *sessionToken; -/// Whether the PFUser was just created from a request. This is only set after a Facebook login. +/// Whether the PFUser was just created from a request. This is only set after a Facebook or Twitter login. @property (readonly, assign) BOOL isNew; /*! @@ -114,8 +114,8 @@ A Parse Framework User Object that is a local representation of a user persisted @param password The password of the user. @result Returns an instance of the PFUser on success. If login failed for either wrong password or wrong username, returns nil. */ -+ (PFUser *)logInWithUsername:(NSString *)username - password:(NSString *)password; ++ (instancetype)logInWithUsername:(NSString *)username + password:(NSString *)password; /*! Makes a request to login a user with specified credentials. Returns an @@ -126,9 +126,9 @@ A Parse Framework User Object that is a local representation of a user persisted @param error The error object to set on error. @result Returns an instance of the PFUser on success. If login failed for either wrong password or wrong username, returns nil. */ -+ (PFUser *)logInWithUsername:(NSString *)username - password:(NSString *)password - error:(NSError **)error; ++ (instancetype)logInWithUsername:(NSString *)username + password:(NSString *)password + error:(NSError **)error; /*! Makes an asynchronous request to login a user with specified credentials. @@ -232,80 +232,5 @@ A Parse Framework User Object that is a local representation of a user persisted */ + (PFQuery *)query; -/** @name Deprecated */ - -/*! - Deprecated. Please see [PFFacebookUtils facebook]. - */ -+ (PF_Facebook *)facebook __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils facebookWithDelegate:]. - */ -+ (PF_Facebook *)facebookWithDelegate:(id)delegate __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils logInWithPermissions:block:]. - */ -+ (void)logInWithFacebook:(NSArray *)permissions block:(PFUserResultBlock)block __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils logInWithPermissions:target:selector:]. - */ -+ (void)logInWithFacebook:(NSArray *)permissions target:(id)target selector:(SEL)selector __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils isLinkedWithUser:] - */ -- (BOOL)hasFacebook __attribute__ ((deprecated)); - -/*! - Deprecated. Please see PF_Facebook.accessToken - */ -- (NSString *)facebookAccessToken __attribute__ ((deprecated)); - -/*! - Deprecated. Please see PF_Facebook.expirationDate - */ -- (NSDate *)facebookExpirationDate __attribute__ ((deprecated)); - -/*! - Deprecated. Please use PF_Facebook to make a graph call to "me" - */ -- (NSString *)facebookId __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils linkUser:permissions:block:]. - */ -- (void)linkToFacebook:(NSArray *)permissions - block:(PFBooleanResultBlock)block __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils linkUser:permissions:target:selector:]. - */ -- (void)linkToFacebook:(NSArray *)permissions - target:(id)target - selector:(SEL)selector __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils unlinkUser:]. - */ -- (BOOL)unlinkFromFacebook __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils unlinkUser:error:]. - */ -- (BOOL)unlinkFromFacebookWithError:(NSError **)error __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils unlinkUserInBackground:block:]. - */ -- (void)unlinkFromFacebookWithBlock:(PFBooleanResultBlock)block __attribute__ ((deprecated)); - -/*! - Deprecated. Please see [PFFacebookUtils unlinkUserInBackground:target:selector:]. - */ -- (void)unlinkFromFacebookInBackgroundWithTarget:(id)target - selector:(SEL)selector __attribute__ ((deprecated)); @end diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_EGORefreshTableHeaderView.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_EGORefreshTableHeaderView.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_EGORefreshTableHeaderView.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_EGORefreshTableHeaderView.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_MBProgressHUD.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_MBProgressHUD.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_MBProgressHUD.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_MBProgressHUD.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_Twitter.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_Twitter.h similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/PF_Twitter.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/PF_Twitter.h diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/Parse.h b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/Parse.h similarity index 68% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/Parse.h rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/Parse.h index b986ce2..24b0a38 100644 --- a/FTASyncDemo/Parse.framework/Versions/1.0.64/Headers/Parse.h +++ b/FTASyncDemo/Parse.framework/Versions/1.2.10/Headers/Parse.h @@ -8,27 +8,42 @@ #import #import "PFACL.h" +#import "PFAnalytics.h" #import "PFAnonymousUtils.h" +#import "PFCloud.h" #import "PFConstants.h" -#import "PFFacebookUtils.h" #import "PFFile.h" #import "PFGeoPoint.h" +#import "PFObject.h" +#import "PFQuery.h" +#import "PFRelation.h" +#import "PFRole.h" +#import "PFSubclassing.h" +#import "PFUser.h" + +#if PARSE_IOS_ONLY #import "PFImageView.h" +#import "PFInstallation.h" #import "PFLogInViewController.h" -#import "PFObject.h" #import "PFProduct.h" -#import "PFPush.h" +#import "PFProductTableViewController.h" #import "PFPurchase.h" -#import "PFQuery.h" +#import "PFPush.h" #import "PFQueryTableViewController.h" -#import "PFInstallation.h" -#import "PFRelation.h" -#import "PFRole.h" #import "PFSignUpViewController.h" #import "PFTableViewCell.h" #import "PFTwitterUtils.h" -#import "PFUser.h" -#import "PF_FBConnect.h" + +#if defined(__has_include) +#if __has_include() +#import +#import "PFFacebookUtils.h" +#else +#define PFFacebookUtils Please_add_the_Facebook_SDK_to_your_project +#endif +#endif + +#endif @interface Parse : NSObject @@ -36,25 +51,14 @@ /*! Sets the applicationId and clientKey of your application. - @param applicationId The applicaiton id for your Parse application. - @param applicationId The client key for your Parse application. + @param applicationId The application id for your Parse application. + @param clientKey The client key for your Parse application. */ + (void)setApplicationId:(NSString *)applicationId clientKey:(NSString *)clientKey; ++ (NSString *)getApplicationId; ++ (NSString *)getClientKey; -/** @name Configuring Facebook Settings */ - -/*! - Sets the Facebook application id that you are using with your Parse application. You must set this in - order to use the Facebook functionality in Parse. - @param applicationId The Facebook application id that you are using with your Parse application. - */ -+ (void)setFacebookApplicationId:(NSString *)applicationId __attribute__ ((deprecated)); - -/*! - Whether the Facebook application id has been set. - */ -+ (BOOL)hasFacebookApplicationId __attribute__ ((deprecated)); - +#if PARSE_IOS_ONLY /** @name Configuring UI Settings */ /*! @@ -70,9 +74,6 @@ @param enabled Whether a UIAlert should be shown when a Parse error occurs. */ + (void)errorMessagesEnabled:(BOOL)enabled; +#endif -+ (NSString *)getApplicationId; -+ (NSString *)getClientKey; -+ (NSString *)getFacebookApplicationId __attribute__ ((deprecated)); - -@end \ No newline at end of file +@end diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Parse b/FTASyncDemo/Parse.framework/Versions/1.2.10/Parse new file mode 100644 index 0000000..a4cb988 Binary files /dev/null and b/FTASyncDemo/Parse.framework/Versions/1.2.10/Parse differ diff --git a/FTASyncDemo/Parse.framework/Versions/1.0.64/Resources/Info.plist b/FTASyncDemo/Parse.framework/Versions/1.2.10/Resources/Info.plist similarity index 100% rename from FTASyncDemo/Parse.framework/Versions/1.0.64/Resources/Info.plist rename to FTASyncDemo/Parse.framework/Versions/1.2.10/Resources/Info.plist diff --git a/FTASyncDemo/Parse.framework/Versions/1.2.10/Resources/Localizable.strings b/FTASyncDemo/Parse.framework/Versions/1.2.10/Resources/Localizable.strings new file mode 100644 index 0000000..e950d1b Binary files /dev/null and b/FTASyncDemo/Parse.framework/Versions/1.2.10/Resources/Localizable.strings differ diff --git a/FTASyncDemo/Parse.framework/Versions/Current b/FTASyncDemo/Parse.framework/Versions/Current index ef3b2e2..732aa7d 120000 --- a/FTASyncDemo/Parse.framework/Versions/Current +++ b/FTASyncDemo/Parse.framework/Versions/Current @@ -1 +1 @@ -1.0.64 \ No newline at end of file +1.2.10 \ No newline at end of file diff --git a/FTASyncDemo/Parse.framework/third_party_licenses.txt b/FTASyncDemo/Parse.framework/third_party_licenses.txt new file mode 100644 index 0000000..1e564e9 --- /dev/null +++ b/FTASyncDemo/Parse.framework/third_party_licenses.txt @@ -0,0 +1,79 @@ +THE FOLLOWING SETS FORTH ATTRIBUTION NOTICES FOR THIRD PARTY SOFTWARE THAT MAY BE CONTAINED IN PORTIONS OF THE PARSE PRODUCT. + +----- + +The following software may be included in this product: AFNetworking. This software contains the following license and notice below: + +Copyright (c) 2011 Gowalla (http://gowalla.com/) + +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. + +----- + +The following software may be included in this product: EGOTableViewPullRefresh. This software contains the following license and notice below: + +// +// EGORefreshTableHeaderView.h +// Demo +// +// Created by Devin Doty on 10/14/09October14. +// Copyright 2009 enormego. All rights reserved. +// +// 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. +// + +----- + +The following software may be included in this product: MBProgressHUD. This software contains the following license and notice below: + +Copyright (c) 2013 Matej Bukovinski + +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 diff --git a/README.mdown b/README.mdown index e018541..6de9fc1 100644 --- a/README.mdown +++ b/README.mdown @@ -10,7 +10,7 @@ Because sync and conflict resolution is very complex, there is bunch of debug lo It is assumed that you have already installed and setup these: -* [Magical Record](https://github.com/magicalpanda/MagicalRecord) - Easier handling of the CoreData stuff. (Note: FTASync uses MR 2.0 and will not work with earlier versions) +* [Magical Record](https://github.com/magicalpanda/MagicalRecord) - Easier handling of the CoreData stuff. (Note: This fork of FTASync uses MR 2.1 and will not work with earlier versions) * [mogenerator] (https://github.com/rentzsch/mogenerator) - If you've never used it you should. * [NPReachability] (https://github.com/Abizern/NPReachability) - Used to check for network connectivity pre-sync. * [Parse SDK](https://www.parse.com/apps/quickstart) @@ -19,15 +19,31 @@ It is assumed that you have already installed and setup these: # Installation 1. Add a new data model version. -2. Add a new *abstract* entity to the data model and name it (and it's class name) FTASyncParent. Add the following attributes: +2. Add a new *abstract* entity to the data model and name it ***(and it's class name)*** FTASyncParent. Add the following attributes: * BOOL createdHere (Default: YES) * BOOL deleted (Default: NO) * String objectId * Int16 syncStatus (Default: 2) * Date updatedAt -3. For each entity that should sync, set the parent entity field to FTASyncParent. +3. For each entity that should sync, set the parent entity field to FTASyncParent. Also, set the class name of each object to it's entity name. 4. Run mogenerator to generate your entity class files. -5. Add all the .h and .m files from the *Source* folder into your project. (FTASyncParent.h/m will replace the mogenerator generated files) + +Some mogenerator quirks: + +If mogenerator does not seem to create the data model for you, try running it from the command line (from your project directory): + +mogenerator --template-var arc=true -m PROJECT_NAME.xcdatamodeld/PROJECT_NAME.xcdatamodel/ + +If you get an error from the command line that says "Illegal Instruction: 4", try installing from brew. This recompiles the code for your updated OS X. + +$ brew update && brew upgrade mogenerator to install not the DMG + +5. Add all the .h and .m files from the *Source* folder into your project. + +Be sure that you do this after you generate your data model using mogenerator. + +FTASyncParent.h/m will replace the mogenerator generated files. + 6. Add *FTASync.h* to your AppDelegate file. 7. Create a file with the name *ParseKeys.h* with these two lines: * `#define kParseAppId @""` @@ -36,8 +52,15 @@ It is assumed that you have already installed and setup these: 8. Add `[FTASyncHandler sharedInstance];` to the `- (BOOL)application:didFinishLaunchingWithOptions:` method in your AppDelegate. 9. Add `[PFACL setDefaultACL:[PFACL ACL] withAccessForCurrentUser:YES];` to the `- (BOOL)application:didFinishLaunchingWithOptions:` method in your AppDelegate. You can also setup some other ACL if you wish. 10. (Optional) Uncomment out `//[Crashlytics startWithAPIKey:kCrashlyticsKey];` in the `- (BOOL)application:didFinishLaunchingWithOptions:` method in your AppDelegate. +11. Add `[MagicalRecord setupAutoMigratingCoreDataStack];` in the `- (BOOL)application:didFinishLaunchingWithOptions:` method in your AppDelegate. This initializes your managed object context for CoreData. + +#Other Setup Notes: +If you get an error regarding FTASyncParent duplicate definition, fix other errors and warnings and this will often go away. + +It is assumed that you will handle user sign up and login on your own. You must have a user signed in to Parse in order to sync. -It is assumed that you will handle user sign up and login on your own. +You can test your sync with an anonymous user: +Add `[PFUser enableAutomaticUser];` to your `- (BOOL)application:didFinishLaunchingWithOptions:` to get an anonymous user. # Usage diff --git a/Source/FTAParseSync.h b/Source/FTAParseSync.h old mode 100644 new mode 100755 index 08a2bf9..4b22933 --- a/Source/FTAParseSync.h +++ b/Source/FTAParseSync.h @@ -17,6 +17,7 @@ - (BOOL)canSync; +- (NSArray *)getObjectsOfClass:(NSString *)className updatedSince:(NSDate *)lastUpdate error:(NSError **)error; - (NSArray *)getObjectsOfClass:(NSString *)className updatedSince:(NSDate *)lastUpdate; - (BOOL)putUpdatedObjects:(NSArray *)updatedObjects forClass:(NSEntityDescription *)entityDesc error:(NSError **)error; diff --git a/Source/FTAParseSync.m b/Source/FTAParseSync.m old mode 100644 new mode 100755 index 24608a8..7881aae --- a/Source/FTAParseSync.m +++ b/Source/FTAParseSync.m @@ -27,6 +27,8 @@ - (BOOL)canSync { return NO; } + + /* if (![PFUser currentUser]) { //This can be enabled if you wish to alert the user that they are not signed in // UIAlertView *noLogin = [[UIAlertView alloc] initWithTitle:@"Cannot Sync" @@ -38,32 +40,54 @@ - (BOOL)canSync { FSCLog(@"No Parse user is logged in"); return NO; } + */ return YES; } -- (NSArray *)getObjectsOfClass:(NSString *)className updatedSince:(NSDate *)lastUpdate { +- (NSArray *)getObjectsOfClass:(NSString *)className updatedSince:(NSDate *)lastUpdate error:(NSError **)error { PFQuery *query = [PFQuery queryWithClassName:className]; - query.limit = 1000; + query.limit = [[FTASyncHandler sharedInstance] queryLimit]; //Cache the query in case we need one of the objects for merging later query.cachePolicy = kPFCachePolicyNetworkOnly; if (lastUpdate) { [query whereKey:@"updatedAt" greaterThan:lastUpdate]; } - - NSArray *returnObjects = [query findObjects]; - + [query orderBySortDescriptor:[NSSortDescriptor sortDescriptorWithKey:@"updatedAt" ascending:YES]]; + + NSArray *returnObjects = [query findObjects:error]; + NSLog(@"returnObjects: %@ %@", returnObjects, className); + if (!*error) { + [[FTASyncHandler sharedInstance] setReceivedPFObjects:returnObjects entityName:className]; + } + return returnObjects; } +- (NSArray *)getObjectsOfClass:(NSString *)className updatedSince:(NSDate *)lastUpdate { + return [self getObjectsOfClass:className updatedSince:lastUpdate error:nil]; +} + - (BOOL)putUpdatedObjects:(NSArray *)updatedObjects forClass:(NSEntityDescription *)entityDesc error:(NSError **)error { NSMutableArray *updatedParseObjects = [[NSMutableArray alloc] initWithCapacity:[updatedObjects count]]; //Get parse objects for all updated objects for (FTASyncParent *localObject in updatedObjects) { - PFObject *parseObject = localObject.remoteObject; - [updatedParseObjects addObject:parseObject]; + PFObject *parseObject = [PFQuery getObjectOfClass:[entityDesc name] objectId:localObject.remoteObject.objectId]; + if (!parseObject && localObject.remoteObject.objectId) { + localObject.objectId = NULL; + NSMutableDictionary *dic = [@{} mutableCopy]; + for (NSString *key in localObject.remoteObject.allKeys) { + if ([@[@"createdAt"] containsObject:key]) continue; + dic[key] = [localObject.remoteObject objectForKey:key]; + } + localObject.remoteObject = [PFObject objectWithClassName:[entityDesc name] dictionary:dic]; + } + if (!localObject.remoteObject.objectId) { + [localObject.remoteObject setObject:[PFUser currentUser] forKey:@"user"]; + } + [updatedParseObjects addObject:localObject.remoteObject]; } NSUInteger updateCount = [updatedParseObjects count]; @@ -72,11 +96,12 @@ - (BOOL)putUpdatedObjects:(NSArray *)updatedObjects forClass:(NSEntityDescriptio NSArray *deletedLocalObjects = [[NSUserDefaults standardUserDefaults] objectForKey:defaultsKey]; FSLog(@"Preparing to create PFObjects for deletion: %@", deletedLocalObjects); for (NSString *objectId in deletedLocalObjects) { - PFObject *parseObject = [PFObject objectWithClassName:[entityDesc name]]; - parseObject.objectId = objectId; - [parseObject setObject:[NSNumber numberWithInt:1] forKey:@"deleted"]; - [updatedParseObjects addObject:parseObject]; - FSLog(@"Deleting PFObject: %@", parseObject); + PFObject *parseObject = [PFQuery getObjectOfClass:[entityDesc name] objectId:objectId]; + if (parseObject) { + [parseObject setObject:[NSNumber numberWithInt:1] forKey:@"deleted"]; + [updatedParseObjects addObject:parseObject]; + FSLog(@"Deleting PFObject: %@", parseObject); + } } NSUInteger deleteCount = [updatedParseObjects count] - updateCount; diff --git a/Source/FTASync.h b/Source/FTASync.h old mode 100644 new mode 100755 diff --git a/Source/FTASyncHandler.h b/Source/FTASyncHandler.h old mode 100644 new mode 100755 index ce9dd36..3fe76b4 --- a/Source/FTASyncHandler.h +++ b/Source/FTASyncHandler.h @@ -25,14 +25,23 @@ typedef void (^FTABoolCompletionBlock)(BOOL success, NSError* error); @property (atomic, getter = isSyncInProgress) BOOL syncInProgress; @property (nonatomic, getter = isIgnoreContextSave) BOOL ignoreContextSave; +@property (atomic) NSInteger queryLimit; +@property (strong, atomic) NSDictionary *receivedPFObjectDictionary; + (FTASyncHandler *)sharedInstance; + (NSString *)getMetadataForKey:(NSString *)key forEntity:(NSString *)entityName inContext:(NSManagedObjectContext *)context; + (void)setMetadataValue:(id)value forKey:(NSString *)key forEntity:(NSString *)entityName inContext:(NSManagedObjectContext *)context; -- (void)syncWithCompletionBlock:(FTACompletionBlock)completion progressBlock:(FTASyncProgressBlock)progress; +- (NSArray *) receivedPFObjects:(NSString *) entityName; +- (void) setReceivedPFObjects:(NSArray *)receivedPFObjects entityName:(NSString *) entityName; + +- (void)syncWithCompletionBlock:(FTABoolCompletionBlock)completion progressBlock:(FTASyncProgressBlock)progress; - (void)resetAllSyncStatusAndDeleteRemote:(BOOL)delete withCompletionBlock:(FTABoolCompletionBlock)completion progressBlock:(FTASyncProgressBlock)progress; +-(void)deleteAllDeletedByRemote:(FTABoolCompletionBlock)completion; + + + @end diff --git a/Source/FTASyncHandler.m b/Source/FTASyncHandler.m old mode 100644 new mode 100755 index 8555fdb..fe2588b --- a/Source/FTASyncHandler.m +++ b/Source/FTASyncHandler.m @@ -27,8 +27,6 @@ @interface FTASyncHandler () - (void)contextWasSaved:(NSNotification *)notification; - (NSArray *)entitiesToSync; -- (void)syncEntity:(NSEntityDescription *)entityName; -- (void)syncAll; - (BOOL)resetAllSyncStatusAndDeleteRemote:(BOOL)delete inContext:(NSManagedObjectContext *)context; @@ -50,12 +48,14 @@ @implementation FTASyncHandler + (FTASyncHandler *)sharedInstance { static dispatch_once_t pred; static FTASyncHandler *shared = nil; - + dispatch_once(&pred, ^{ shared = [[FTASyncHandler alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:shared selector:@selector(contextWasSaved:) name:NSManagedObjectContextDidSaveNotification object:[NSManagedObjectContext MR_defaultContext]]; + shared.queryLimit = 10; + shared.receivedPFObjectDictionary = @{}; }); - + return shared; } @@ -65,43 +65,53 @@ - (FTAParseSync *)remoteInterface { if (!_remoteInterface) { _remoteInterface = [[FTAParseSync alloc] init]; } - + return _remoteInterface; } +- (NSArray *) receivedPFObjects:(NSString *) entityName { + return self.receivedPFObjectDictionary[entityName]; +} + +- (void) setReceivedPFObjects:(NSArray *)receivedPFObjects entityName:(NSString *) entityName { + NSMutableDictionary *dic = [self.receivedPFObjectDictionary mutableCopy]; + dic[entityName] = receivedPFObjects; + self.receivedPFObjectDictionary = dic; +} + #pragma mark - CoreData Maintenance -- (void)contextWasSaved:(NSNotification *)notification { +- (void)contextWasSaved:(NSNotification *)notification { if (![NSThread isMainThread]) { //If this is not on a main thread it is a sync save return; } - + if (self.isIgnoreContextSave) { FSLog(@"%@", @"ignoreContextSave == YES"); return; } - + NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey]; NSSet *deletedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey]; - - for (NSManagedObject *updatedObject in updatedObjects) { + + for (NSManagedObject *updatedObject in updatedObjects) { if ([[updatedObject class] isSubclassOfClass:[FTASyncParent class]] && [updatedObject valueForKey:@"syncStatus"] == [NSNumber numberWithInt:0]) { [updatedObject setValue:[NSNumber numberWithInt:1] forKey:@"syncStatus"]; FSLog(@"Updated Object: %@", updatedObject); } } self.ignoreContextSave = YES; - [[NSManagedObjectContext MR_defaultContext] MR_save]; + [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait]; self.ignoreContextSave = NO; for (NSManagedObject *deletedObject in deletedObjects) { - FSLog(@"Object was deleted from MOC: %@", deletedObject); + FSLog(@"Object was deleted from MOC: %@", deletedObject); if ([[deletedObject class] isSubclassOfClass:[FTASyncParent class]] && [deletedObject valueForKey:@"objectId"] != nil) { NSString *defaultsKey = [NSString stringWithFormat:@"FTASyncDeleted%@", [[deletedObject entity] name]]; NSArray *deletedFromDefaults = [[NSUserDefaults standardUserDefaults] objectForKey:defaultsKey]; NSMutableArray *localDeletedObjects = [[NSMutableArray alloc] initWithArray:deletedFromDefaults]; - + [localDeletedObjects addObject:[deletedObject valueForKey:@"objectId"]]; [[NSUserDefaults standardUserDefaults] setObject:localDeletedObjects forKey:defaultsKey]; FSLog(@"Deleted Object: %@", deletedObject); @@ -117,16 +127,16 @@ + (id)getMetadataForKey:(NSString *)key forEntity:(NSString *)entityName inConte NSPersistentStoreCoordinator *coordinator = [context persistentStoreCoordinator]; id store = [coordinator persistentStoreForURL:[NSPersistentStore MR_urlForStoreName:[MagicalRecord defaultStoreName]]]; NSDictionary *metadata = [coordinator metadataForPersistentStore:store]; - + NSDictionary *entityMetadata = [metadata objectForKey:entityName]; if (!entityMetadata) { return nil; } - + if (!key) { return entityMetadata; } - + return [entityMetadata objectForKey:key]; } @@ -134,19 +144,19 @@ + (void)setMetadataValue:(id)value forKey:(NSString *)key forEntity:(NSString *) NSPersistentStoreCoordinator *coordinator = [context persistentStoreCoordinator]; id store = [coordinator persistentStoreForURL:[NSPersistentStore MR_urlForStoreName:[MagicalRecord defaultStoreName]]]; NSMutableDictionary *metadata = [[coordinator metadataForPersistentStore:store] mutableCopy]; - + if (!key) { [metadata setValue:value forKey:entityName]; [coordinator setMetadata:metadata forPersistentStore:store]; return; } - + NSMutableDictionary *entityMetadata = [[metadata valueForKey:entityName] mutableCopy]; if (!entityMetadata) { entityMetadata = [NSMutableDictionary dictionary]; [metadata setObject:entityMetadata forKey:entityName]; } - + [entityMetadata setValue:value forKey:key]; [metadata setObject:entityMetadata forKey:entityName]; [coordinator setMetadata:metadata forPersistentStore:store]; @@ -159,122 +169,154 @@ + (void)setMetadataValue:(id)value forKey:(NSString *)key forEntity:(NSString *) - (NSArray *)entitiesToSync { - return [FTASyncParent allDescedents]; + return [FTASyncParent allDescendants]; } -- (void)syncEntity:(NSEntityDescription *)entityDesc { +- (BOOL)syncEntity:(NSEntityDescription *)entityDesc { if ([NSThread isMainThread]) { FSALog(@"%@", @"This should NEVER be run on the main thread!!"); - return; + return NO; } - + if (![FTASyncParent isParentOfEntity:entityDesc]) { FSALog(@"Requested a sync for an entity (%@) that does not inherit from FTASyncParent!", [entityDesc name]); - return; + return NO; } + Class managedObjectClass = NSClassFromString([entityDesc managedObjectClassName]); + NSMutableArray *objectsToSync = [[NSMutableArray alloc] initWithCapacity:1]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:entityDesc]; - //Get the time of the most recently sync'd object - NSDate *lastUpdate = [FTASyncParent FTA_lastUpdateForClass:entityDesc]; - FSLog(@"Last update: %@", lastUpdate); - - //Add new local objects - [request setPredicate:[NSPredicate predicateWithFormat:@"syncStatus = nil OR syncStatus = 2 OR syncStatus = 3"]]; - NSArray *newLocalObjects = [NSManagedObject MR_executeFetchRequest:request]; - FSLog(@"Number of new local objects: %i", [newLocalObjects count]); + if (![managedObjectClass readOnly]) { + //Add new local objects + [request setPredicate:[NSPredicate predicateWithFormat:@"syncStatus = nil OR syncStatus = 2 OR syncStatus = 3"]]; + NSArray *newLocalObjects = [NSManagedObject MR_executeFetchRequest:request inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; + FSLog(@"Number of new local objects: %i %@", [newLocalObjects count], newLocalObjects); + #ifdef DEBUG - for (FTASyncParent *object in newLocalObjects) { - if (object.syncStatusValue == 3) { - FSLog(@"!!!!!!!OBJECT WITH SYNC STATUS 3!!!!!! %@", object); + for (FTASyncParent *object in newLocalObjects) { + if (object.syncStatusValue == 3) { + FSLog(@"!!!!!!!OBJECT WITH SYNC STATUS 3!!!!!! %@", object); + } } - } #endif - if ([newLocalObjects count] > 0) { - [objectsToSync addObjectsFromArray:newLocalObjects]; + + if ([newLocalObjects count] > 0) { + [objectsToSync addObjectsFromArray:newLocalObjects]; + } + + } - + + //Get the time of the most recently sync'd object + NSDate *lastUpdate = [FTASyncParent FTA_lastUpdateForClass:entityDesc]; + FSLog(@"Last update: %@", lastUpdate); + //Get updated remote objects - NSMutableArray *remoteObjectsForSync = [NSMutableArray arrayWithArray:[self.remoteInterface getObjectsOfClass:[entityDesc name] updatedSince:lastUpdate]]; - FSLog(@"Number of remote objects: %i", [remoteObjectsForSync count]); + NSError *error = nil; + NSMutableArray *remoteObjectsForSync = [[self.remoteInterface getObjectsOfClass:[entityDesc name] + updatedSince:lastUpdate + error:&error] mutableCopy]; + + if (error) { + FSALog(@"Cannot get objects from parse server (error: %@)", [error description]); + return NO; + } + + NSDate *lastFetched = [[remoteObjectsForSync lastObject] updatedAt]; + + FSLog(@"Number of remote objects: %i %@", [remoteObjectsForSync count], remoteObjectsForSync); #ifdef DEBUG for (PFObject *object in remoteObjectsForSync) { FSLog(@"%@", object.updatedAt); - } + } #endif - - //Remove objects deleted locally from remote sync array (push to remote done in FTAParseSync) - NSString *defaultsKey = [NSString stringWithFormat:@"FTASyncDeleted%@", [entityDesc name]]; - NSArray *deletedLocalObjects = [[NSUserDefaults standardUserDefaults] objectForKey:defaultsKey]; - FSLog(@"Deleted objects from prefs: %@", deletedLocalObjects); - NSPredicate *deletedLocalInRemotePredicate = [NSPredicate predicateWithFormat: @"NOT (objectId IN %@)", deletedLocalObjects]; - [remoteObjectsForSync filterUsingPredicate:deletedLocalInRemotePredicate]; - + + NSArray *deletedLocalObjects; + if (![managedObjectClass readOnly]) { + //Remove objects deleted locally from remote sync array (push to remote done in FTAParseSync) + NSString *defaultsKey = [NSString stringWithFormat:@"FTASyncDeleted%@", [entityDesc name]]; + deletedLocalObjects = [[NSUserDefaults standardUserDefaults] objectForKey:defaultsKey]; + FSLog(@"Deleted objects from prefs: %@", deletedLocalObjects); + NSPredicate *deletedLocalInRemotePredicate = [NSPredicate predicateWithFormat: @"NOT (objectId IN %@)", deletedLocalObjects]; + [remoteObjectsForSync filterUsingPredicate:deletedLocalInRemotePredicate]; + } + //Add new remote objects NSPredicate *newRemotePredicate = nil; if (lastUpdate) { newRemotePredicate = [NSPredicate predicateWithFormat:@"createdAt > %@ AND (deleted = NO OR deleted = nil)", lastUpdate]; - } - else { - newRemotePredicate = [NSPredicate predicateWithFormat:@"deleted = NO OR deleted = nil", lastUpdate]; + } else { + newRemotePredicate = [NSPredicate predicateWithFormat:@"deleted = NO OR deleted = nil"]; } NSArray *newRemoteObjects = [remoteObjectsForSync filteredArrayUsingPredicate:newRemotePredicate]; - FSLog(@"Number of new remote objects: %i", [newRemoteObjects count]); + FSLog(@"Number of new remote objects: %i %@", [newRemoteObjects count], newRemoteObjects); [remoteObjectsForSync removeObjectsInArray:newRemoteObjects]; [FTASyncParent FTA_newObjectsForClass:entityDesc withRemoteObjects:newRemoteObjects]; - + //Remove objects removed on remote NSPredicate *deletedRemotePredicate = [NSPredicate predicateWithFormat:@"deleted = YES"]; NSArray *deletedRemoteObjects = [remoteObjectsForSync filteredArrayUsingPredicate:deletedRemotePredicate]; [remoteObjectsForSync removeObjectsInArray:deletedRemoteObjects]; - FSLog(@"Number of deleted remote objects: %i", [deletedRemoteObjects count]); + FSLog(@"Number of deleted remote objects: %i %@", [deletedRemoteObjects count], deletedRemoteObjects); [FTASyncParent FTA_deleteObjectsForClass:entityDesc withRemoteObjects:deletedRemoteObjects]; - + + NSMutableArray *remoteObjectsWithACL = [@[] mutableCopy]; + for (PFObject *remoteObject in remoteObjectsForSync) { + if (remoteObject.ACL != nil){ + [remoteObjectsWithACL addObject:remoteObject]; + } + } + remoteObjectsForSync = remoteObjectsWithACL; + //Sync objects changed on remote FSLog(@"Number of updated remote objects: %i", [remoteObjectsForSync count]); [FTASyncParent FTA_updateObjectsForClass:entityDesc withRemoteObjects:remoteObjectsForSync]; - + if ([NSManagedObjectContext MR_contextForCurrentThread] == [NSManagedObjectContext MR_defaultContext]) { FSALog(@"%@", @"Should not be working with the main context!"); } - [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveErrorHandler:^(NSError *error){ - [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; - self.syncInProgress = NO; - self.progressBlock = nil; - self.progress = 0; - - [self handleError:error]; - return; + + [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { + if (!success && error) { + [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; + self.syncInProgress = NO; + self.progressBlock = nil; + self.progress = 0; + + [self handleError:error]; + return; + } }]; - //Sync objects changed locally - [request setPredicate:[NSPredicate predicateWithFormat:@"syncStatus = 1"]]; - NSArray *updatedLocalObjects = [NSManagedObject MR_executeFetchRequest:request]; - FSLog(@"Number of updated local objects: %i", [updatedLocalObjects count]); - [objectsToSync addObjectsFromArray:updatedLocalObjects]; - - if ([objectsToSync count] < 1 && [deletedLocalObjects count] < 1) { - FSLog(@"NO OBJECTS TO SYNC"); - if ([deletedRemoteObjects count] > 0) { - [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveErrorHandler:^(NSError *error){ - [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; - self.syncInProgress = NO; - self.progressBlock = nil; - self.progress = 0; - - [self handleError:error]; - return; - }]; - } + if (![managedObjectClass readOnly]) { + [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait]; + self.ignoreContextSave = NO; - return; + //Sync objects changed locally + [request setPredicate:[NSPredicate predicateWithFormat:@"syncStatus = 1"]]; + NSArray *updatedLocalObjects = [NSManagedObject MR_executeFetchRequest:request inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; + FSLog(@"Number of updated local objects: %i", [updatedLocalObjects count]); + [objectsToSync addObjectsFromArray:updatedLocalObjects]; + + if ([objectsToSync count] < 1 && [deletedLocalObjects count] < 1) { + FSLog(@"NO OBJECTS TO SYNC"); + if ([deletedRemoteObjects count] > 0) { + self.ignoreContextSave = YES; + [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait]; + self.ignoreContextSave = NO; + } + + [FTASyncParent FTA_setLastUpdate:lastFetched forClass:entityDesc]; + return YES; + } } - + //Push changes to remote server and update local object's metadata FSLog(@"Total number of objects to sync: %i", [objectsToSync count]); - NSError *error = nil; + error = nil; BOOL success = [self.remoteInterface putUpdatedObjects:objectsToSync forClass:entityDesc error:&error]; if (!success) { [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; @@ -283,85 +325,87 @@ - (void)syncEntity:(NSEntityDescription *)entityDesc { self.progress = 0; [self handleError:error]; - return; - } - else { - [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveErrorHandler:^(NSError *error){ - [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; - self.syncInProgress = NO; - self.progressBlock = nil; - self.progress = 0; - - [self handleError:error]; - return; - }]; + return NO; + } else { + self.ignoreContextSave = YES; + [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait]; + self.ignoreContextSave = NO; + [FTASyncParent FTA_setLastUpdate:lastFetched forClass:entityDesc]; + return YES; } } -- (void)syncAll { +- (BOOL)syncAll { if ([NSThread isMainThread]) { FSALog(@"%@", @"This should NEVER be run on the main thread!!"); - return; + return NO; } - + NSArray *entitiesToSync = [self entitiesToSync]; - + FSLog(@"Syncing %i entities", [entitiesToSync count]); float increment = 0.8 / (float)[entitiesToSync count]; self.progress = 0.1; if (self.progressBlock) { self.progressBlock(self.progress, @"Starting sync..."); } - + for (NSEntityDescription *anEntity in entitiesToSync) { FSLog(@"Requesting sync for entity: %@", anEntity); - [self syncEntity:anEntity]; - + BOOL success = [self syncEntity:anEntity]; + if (!success) { + return NO; + } + if (!self.syncInProgress) { //Sync had an issue somewhere, so halt - return; + return NO; } - + self.progress += increment; if (self.progressBlock) self.progressBlock(self.progress, [NSString stringWithFormat:@"Finished sync of %@", [anEntity name]]); } - + //Since there is no rollback on the metadata this must not be cleared out until we know a full sync was successful for (NSEntityDescription *anEntity in entitiesToSync) { [FTASyncHandler setMetadataValue:[NSMutableDictionary dictionary] forKey:nil forEntity:[anEntity name] inContext:[NSManagedObjectContext MR_defaultContext]]; } - + #ifdef DEBUG NSPersistentStoreCoordinator *coordinator = [[NSManagedObjectContext MR_defaultContext] persistentStoreCoordinator]; id store = [coordinator persistentStoreForURL:[NSPersistentStore MR_urlForStoreName:[MagicalRecord defaultStoreName]]]; + NSDictionary *metadata = [coordinator metadataForPersistentStore:store]; FSLog(@"METADATA after clear: %@", metadata); +#pragma unused (metadata) #endif + + return YES; } -- (void)syncWithCompletionBlock:(FTACompletionBlock)completion progressBlock:(FTASyncProgressBlock)progress { +- (void)syncWithCompletionBlock:(FTABoolCompletionBlock)completion progressBlock:(FTASyncProgressBlock)progress { //Quick sanity check to fail early if a sync is in progress, or cannot be completed if (![self.remoteInterface canSync] || self.syncInProgress) { if (completion) - completion(); - + completion(NO, nil); + return; } - + self.syncInProgress = YES; self.progressBlock = progress; self.progress = 0.0; if (self.progressBlock) { self.progressBlock(self.progress, @"Initializing..."); } - + //Setup background process tags so we can complete on app exit __block UIBackgroundTaskIdentifier bgTask = 0; if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Create a background task identifier and specify the exception handler bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - NSLog(@"Background sync on exit failed to complete in time limit"); + MRLog(@"Background sync on exit failed to complete in time limit"); //TODO: This is the wrong context since this code will be running on main thread. Is there a way to get // access to the context running [self syncAll] below?? [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; @@ -372,79 +416,84 @@ - (void)syncWithCompletionBlock:(FTACompletionBlock)completion progressBlock:(FT bgTask = UIBackgroundTaskInvalid; }]; }; - - [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *context) { + + __block BOOL syncAllResult = NO; + [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { //TODO: Is there any user setup needed?? - [self syncAll]; - }completion:^{ + syncAllResult = [self syncAll]; + } completion:^(BOOL success, NSError *error) { + if (!syncAllResult) { + completion(NO, nil); + } + if (self.progressBlock) self.progressBlock(1.0, @"Complete"); - + if (![NSThread isMainThread]) { FSALog(@"%@", @"Completion block must be called on main thread"); } - + //Use this notification and user defaults key to update an "Last Updated" message in the UI [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"FTASyncLastSyncDate"]; [[NSUserDefaults standardUserDefaults] synchronize]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"FTASyncDidSync" object:nil]; + if (completion) + completion(YES, nil); }); - - if (completion) - completion(); - + self.syncInProgress = NO; self.progressBlock = nil; self.progress = 0; - + //End background task if ([[UIDevice currentDevice] isMultitaskingSupported]) { FSCLog(@"Completed sync."); [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } + }]; } - (BOOL)resetAllSyncStatusAndDeleteRemote:(BOOL)delete inContext:(NSManagedObjectContext *)context { NSArray *entitiesToSync = [[FTASyncParent entityInManagedObjectContext:context] subentities]; - + FSLog(@"Resetting %i entities", [entitiesToSync count]); float increment = 0.8 / (float)[entitiesToSync count]; self.progress = 0.1; if (self.progressBlock) { self.progressBlock(self.progress, @"Starting data reset..."); } - + for (NSEntityDescription *anEntity in entitiesToSync) { NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:anEntity]; NSArray *allLocalObjects = [NSManagedObject MR_executeFetchRequest:request inContext:context]; - + for (FTASyncParent *object in allLocalObjects) { object.createdHereValue = YES; object.objectId = nil; object.syncStatusValue = 2; object.updatedAt = nil; } - + //Clear out any deleted objects in User Defaults NSString *defaultsKey = [NSString stringWithFormat:@"FTASyncDeleted%@", [anEntity name]]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:defaultsKey]; - + if (!delete) { self.progress += increment; if (self.progressBlock) self.progressBlock(self.progress, [NSString stringWithFormat:@"Finished reset of %@", [anEntity name]]); continue; } - + PFQuery *query = [PFQuery queryWithClassName:anEntity.name]; NSError *error = nil; NSArray *allRemoteObjects = [query findObjects:&error]; if (error) { - NSLog(@"Query for all remote objects failed with: %@", error); + MRLog(@"Query for all remote objects failed with: %@", error); [context rollback]; self.syncInProgress = NO; self.progressBlock = nil; @@ -452,11 +501,11 @@ - (BOOL)resetAllSyncStatusAndDeleteRemote:(BOOL)delete inContext:(NSManagedObjec [self handleError:error]; return NO; } - + for (PFObject *object in allRemoteObjects) { BOOL success = [object delete:&error]; if (!success) { - NSLog(@"Deletion of object with ID %@ failed with: %@", object.objectId, error); + MRLog(@"Deletion of object with ID %@ failed with: %@", object.objectId, error); [context rollback]; self.syncInProgress = NO; self.progressBlock = nil; @@ -465,24 +514,26 @@ - (BOOL)resetAllSyncStatusAndDeleteRemote:(BOOL)delete inContext:(NSManagedObjec return NO; } } - + self.progress += increment; if (self.progressBlock) self.progressBlock(self.progress, [NSString stringWithFormat:@"Finished reset of %@", [anEntity name]]); } - + //Since there is no rollback on the metadata this must not be cleared out until we know a full sync was successful for (NSEntityDescription *anEntity in entitiesToSync) { [FTASyncHandler setMetadataValue:[NSMutableDictionary dictionary] forKey:nil forEntity:[anEntity name] inContext:context]; } - + #ifdef DEBUG NSPersistentStoreCoordinator *coordinator = [context persistentStoreCoordinator]; id store = [coordinator persistentStoreForURL:[NSPersistentStore MR_urlForStoreName:[MagicalRecord defaultStoreName]]]; + NSDictionary *metadata = [coordinator metadataForPersistentStore:store]; FSLog(@"METADATA after clear: %@", metadata); +#pragma unused (metadata) #endif - + return YES; } @@ -490,23 +541,23 @@ - (void)resetAllSyncStatusAndDeleteRemote:(BOOL)delete withCompletionBlock:(FTAB if (![self.remoteInterface canSync] || self.syncInProgress) { if (completion) completion(NO, nil); - + return; } - + self.syncInProgress = YES; self.progressBlock = progress; self.progress = 0.0; if (self.progressBlock) { self.progressBlock(self.progress, @"Initializing..."); } - + //Setup background process tags so we can complete on app exit __block UIBackgroundTaskIdentifier bgTask = 0; if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Create a background task identifier and specify the exception handler bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - NSLog(@"Background data reset on exit failed to complete in time limit"); + MRLog(@"Background data reset on exit failed to complete in time limit"); //TODO: This is the wrong context since this code will be running on main thread. Is there a way to get // access to the context running in performSaveData... below?? [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; @@ -517,27 +568,28 @@ - (void)resetAllSyncStatusAndDeleteRemote:(BOOL)delete withCompletionBlock:(FTAB bgTask = UIBackgroundTaskInvalid; }]; }; - + __block BOOL didFail = NO; - [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *context) { - didFail = ![self resetAllSyncStatusAndDeleteRemote:delete inContext:context]; - }completion:^{ + + [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { + didFail = ![self resetAllSyncStatusAndDeleteRemote:delete inContext:localContext]; + } completion:^(BOOL success, NSError *error) { if (self.progressBlock) self.progressBlock(1.0, @"Complete"); - + if (![NSThread isMainThread]) { FSALog(@"%@", @"Completion block must be called on main thread"); } - + if (completion && !didFail) completion(YES, nil); else if (completion && didFail) completion(NO, nil); - + self.syncInProgress = NO; self.progressBlock = nil; self.progress = 0; - + //End background task if ([[UIDevice currentDevice] isMultitaskingSupported]) { FSCLog(@"Completed data reset sync."); @@ -547,6 +599,86 @@ - (void)resetAllSyncStatusAndDeleteRemote:(BOOL)delete withCompletionBlock:(FTAB }]; } +-(void)deleteEntityDeletedByRemote:(NSEntityDescription *) entityDesc inContext:(NSManagedObjectContext *)context { + if ([NSThread isMainThread]) { + FSALog(@"%@", @"This should NEVER be run on the main thread!!"); + return; + } + + NSFetchRequest *request = [[NSFetchRequest alloc] init]; + [request setEntity:entityDesc]; + + NSArray *localObjects = [NSManagedObject MR_executeFetchRequest:request inContext:context]; + + NSMutableArray *objectIds = [@[] mutableCopy]; + for (FTASyncParent *object in localObjects) { + [objectIds addObject:object.objectId]; + } + + PFQuery *query = [PFQuery queryWithClassName:[entityDesc name]]; + [query whereKey:@"objectId" containedIn:objectIds]; + NSArray *parseObjects = [query findObjects]; + + NSMutableArray *existingObjectIds = [@[] mutableCopy]; + for (PFObject *parseObject in parseObjects) { + [existingObjectIds addObject:parseObject.objectId]; + } + + for (FTASyncParent *object in localObjects) { + if (![existingObjectIds containsObject:object.objectId]) { + [object MR_deleteInContext:context]; + } + } +} + +-(void)deleteAllDeletedByRemote:(FTABoolCompletionBlock)completion { + if (![self.remoteInterface canSync] || self.syncInProgress) { + if (completion) + completion(NO, nil); + return; + } + + self.syncInProgress = YES; + + //Setup background process tags so we can complete on app exit + __block UIBackgroundTaskIdentifier bgTask = 0; + if ([[UIDevice currentDevice] isMultitaskingSupported]) { + //Create a background task identifier and specify the exception handler + bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + NSLog(@"Background sync on exit failed to complete in time limit"); + //TODO: This is the wrong context since this code will be running on main thread. Is there a way to get + // access to the context running [self syncAll] below?? + [[NSManagedObjectContext MR_contextForCurrentThread] rollback]; + self.syncInProgress = NO; + [[UIApplication sharedApplication] endBackgroundTask:bgTask]; + bgTask = UIBackgroundTaskInvalid; + }]; + }; + + [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { + NSArray *entitiesToSync = [[FTASyncParent entityInManagedObjectContext:localContext] subentities]; + for (NSEntityDescription *anEntity in entitiesToSync) { + [self deleteEntityDeletedByRemote: anEntity inContext:localContext]; + } + } completion:^(BOOL success, NSError *error) { + if (![NSThread isMainThread]) { + FSALog(@"%@", @"Completion block must be called on main thread"); + } + + self.syncInProgress = NO; + + if (completion) + completion(YES, nil); + + //End background task + if ([[UIDevice currentDevice] isMultitaskingSupported]) { + FSCLog(@"Completed sync."); + [[UIApplication sharedApplication] endBackgroundTask:bgTask]; + bgTask = UIBackgroundTaskInvalid; + } + }]; +} + #pragma mark - Error Handling -(void)handleError:(NSError *)error { @@ -559,22 +691,22 @@ -(void)handleError:(NSError *)error { { if ([e respondsToSelector:@selector(userInfo)]) { - NSLog(@"Error Details: %@", [e userInfo]); + MRLog(@"Error Details: %@", [e userInfo]); } else { - NSLog(@"Error Details: %@", e); + MRLog(@"Error Details: %@", e); } } } else { - NSLog(@"Error: %@", detailedError); + MRLog(@"Error: %@", detailedError); } } - NSLog(@"Error Message: %@", [error localizedDescription]); - NSLog(@"Error Domain: %@", [error domain]); - NSLog(@"Recovery Suggestion: %@", [error localizedRecoverySuggestion]); + MRLog(@"Error Message: %@", [error localizedDescription]); + MRLog(@"Error Domain: %@", [error domain]); + MRLog(@"Recovery Suggestion: %@", [error localizedRecoverySuggestion]); } @end diff --git a/Source/FTASyncParent.h b/Source/FTASyncParent.h old mode 100644 new mode 100755 index 56cb16c..cbf709b --- a/Source/FTASyncParent.h +++ b/Source/FTASyncParent.h @@ -19,15 +19,23 @@ @property (strong, nonatomic) PFObject *remoteObject; ++ (BOOL)readOnly; + + (FTASyncParent *)FTA_localObjectForClass:(NSEntityDescription *)entityDesc WithRemoteId:(NSString *)objectId; ++ (FTASyncParent *)FTA_localObjectForClass:(NSEntityDescription *)entityDesc WithRemoteId:(NSString *)objectId WithContext:(NSManagedObjectContext *) context; + (NSArray *)FTA_localObjectsForClass:(NSEntityDescription *)entityDesc WithRemoteIds:(NSArray *)objectIds; + (NSDate *)FTA_lastUpdateForClass:(NSEntityDescription *)entityDesc; ++ (void)FTA_setLastUpdate:(NSDate *)date forClass:(NSEntityDescription *)entityDesc; -+ (NSArray *)allDescedents; ++ (NSArray *)allDescendants; + (BOOL)isParentOfEntity:(NSEntityDescription *)entityDesc; + (FTASyncParent *)FTA_newObjectForClass:(NSEntityDescription *)entityDesc WithRemoteObject:(PFObject *)parseObject; - (void)FTA_updateObjectMetadataWithRemoteObject:(PFObject *)parseObject andResetSyncStatus:(BOOL)resetStatus; +- (void)syncUpdate; +- (id) unarchivePhotoData:(NSString *) propertyName; +- (void)updateObjectWithRemoteObject:(PFObject *)parseObject; +- (void)updateObjectWithRemoteObject:(PFObject *)parseObject WithContext:(NSManagedObjectContext *) context; + (void)FTA_newObjectsForClass:(NSEntityDescription *)entityDesc withRemoteObjects:(NSArray *)parseObjects; + (void)FTA_updateObjectsForClass:(NSEntityDescription *)entityDesc withRemoteObjects:(NSArray *)parseObjects; diff --git a/Source/FTASyncParent.m b/Source/FTASyncParent.m old mode 100644 new mode 100755 index 9fafb30..b345f56 --- a/Source/FTASyncParent.m +++ b/Source/FTASyncParent.m @@ -14,7 +14,6 @@ #import "FTASync.h" - @interface FTASyncParent () @property (nonatomic, getter = isTraversing) BOOL traversing; @@ -80,9 +79,39 @@ - (PFObject *)remoteObject { self.traversing = NO; } + if (![[self class] readOnly]) + [_remoteObject setValue:[PFUser currentUser] forKey:@"user"]; + return _remoteObject; } ++ (BOOL)readOnly +{ + return NO; +} + +- (void)syncUpdate { + if (![self.syncStatus isEqualToNumber:@2]) { + self.syncStatus = @1; + } +} + +- (id) unarchivePhotoData:(NSString *) propertyName { + id unarchiveObject; + @try { + unarchiveObject = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)[self valueForKey:propertyName]]; + }@catch (NSException *exception) { + // if nsdata is uiimage, exception occurred. + unarchiveObject = nil; + NSLog(@"unarchive exception name :%@",exception.name); + NSLog(@"unarchive exception reason:%@",exception.reason); + } + if ([[unarchiveObject class] isSubclassOfClass:[NSURL class]]) { + return unarchiveObject; + } + return [UIImage imageWithData: [self valueForKey:propertyName]]; +} + #pragma mark - KVO - (void)setupRelationshipObservation { @@ -99,9 +128,9 @@ - (void)teardownRelationshipObservation { } } -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change context:(void *)context { if (![NSThread isMainThread] || [[FTASyncHandler sharedInstance] isSyncInProgress]) { //If this is not on a main thread it is a sync save @@ -113,7 +142,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath } //TODO: A temporary solution. Why does the ignoreContextSave not work?? if (![self managedObjectContext]) { - FSCLog(@"Missing context, likly an ignoreContextSave"); + FSCLog(@"Missing context, likely an ignoreContextSave"); return; } @@ -177,13 +206,18 @@ - (NSString *)localEntityName { } + (FTASyncParent *)FTA_localObjectForClass:(NSEntityDescription *)entityDesc WithRemoteId:(NSString *)objectId { - NSFetchRequest *request = [[NSFetchRequest alloc] init]; - [request setEntity:entityDesc]; - - [request setPredicate:[NSPredicate predicateWithFormat:@"objectId = %@", objectId]]; - FTASyncParent *localObject = [NSManagedObject MR_executeFetchRequestAndReturnFirstObject:request]; - - return localObject; + return [self FTA_localObjectForClass:entityDesc WithRemoteId:objectId WithContext:[NSManagedObjectContext MR_contextForCurrentThread]]; +} + ++ (FTASyncParent *)FTA_localObjectForClass:(NSEntityDescription *)entityDesc WithRemoteId:(NSString *)objectId WithContext:(NSManagedObjectContext *) context{ + + NSFetchRequest *request = [[NSFetchRequest alloc] init]; + [request setEntity:entityDesc]; + + [request setPredicate:[NSPredicate predicateWithFormat:@"objectId = %@", objectId]]; + FTASyncParent *localObject = [self MR_executeFetchRequestAndReturnFirstObject:request inContext:context]; + + return localObject; } + (NSArray *)FTA_localObjectsForClass:(NSEntityDescription *)entityDesc WithRemoteIds:(NSArray *)objectIds { @@ -197,16 +231,19 @@ + (NSArray *)FTA_localObjectsForClass:(NSEntityDescription *)entityDesc WithRemo } + (NSDate *)FTA_lastUpdateForClass:(NSEntityDescription *)entityDesc { - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:entityDesc]; - [fetchRequest setSortDescriptors:[NSManagedObject MR_descendingSortDescriptors:[NSArray arrayWithObject:@"updatedAt"]]]; - - NSArray *results = [self MR_executeFetchRequest:fetchRequest]; - if([results count] == 0) { - return nil; + return [[[NSUserDefaults standardUserDefaults] objectForKey:@"FTASyncLastUpdates"] objectForKey:entityDesc.name]; +} + ++ (void)FTA_setLastUpdate:(NSDate *)date forClass:(NSEntityDescription *)entityDesc { + if (date) { + NSMutableDictionary *lastParseFetchedDates = [[[NSUserDefaults standardUserDefaults] objectForKey:@"FTASyncLastUpdates"] mutableCopy]; + if (!lastParseFetchedDates) { + lastParseFetchedDates = [NSMutableDictionary dictionary]; } - - return [[results objectAtIndex:0] valueForKey:@"updatedAt"]; + [lastParseFetchedDates setObject:date forKey:entityDesc.name]; + [[NSUserDefaults standardUserDefaults] setObject:lastParseFetchedDates forKey:@"FTASyncLastUpdates"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } } - (BOOL)shouldUseRemoteObject:(PFObject *)remoteObject @@ -215,9 +252,9 @@ - (BOOL)shouldUseRemoteObject:(PFObject *)remoteObject relationship:(NSString *)relationship { FSLog(@"Should use remote: %@ or local: %@ for relationship: %@", remoteObject.objectId, localObject.objectId, relationship); //BOOL if we are checking a to-one relationship, or NSArray if it is a to-many relationship - id localChanges = [FTASyncHandler getMetadataForKey:[NSString stringWithFormat:@"%@.%@", self.objectId, relationship] - forEntity:[self localEntityName] - inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; + id localChanges = [FTASyncHandler getMetadataForKey:[NSString stringWithFormat:@"%@.%@", self.objectId, relationship] + forEntity:[self localEntityName] + inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; FSLog(@"Local changes: %@", localChanges); if (self.syncStatusValue == 2 || self.syncStatusValue == 3) { @@ -269,12 +306,22 @@ - (BOOL)shouldUseRemoteObject:(PFObject *)remoteObject #pragma mark - Ancestry -+ (NSArray *)allDescedents { ++ (NSArray *)allDescendants { NSMutableArray *children = [NSMutableArray array]; NSEntityDescription *parentEntity = [self entityInManagedObjectContext:[NSManagedObjectContext MR_contextForCurrentThread]]; [children addObjectsFromArray:[FTASyncParent allDecendentsOfEntity:parentEntity]]; - return children; + NSMutableArray *childrenToo = [NSMutableArray array]; + for (NSEntityDescription *obj in children) { + Class myClass = NSClassFromString([obj managedObjectClassName]); + + if (![PFUser currentUser] && ![myClass readOnly]) + continue; + + [childrenToo addObject:obj]; + } + + return childrenToo; } + (NSArray *)allDecendentsOfEntity:(NSEntityDescription *)entity { @@ -297,19 +344,23 @@ + (BOOL)isParentOfEntity:(NSEntityDescription *)entityDesc { #pragma mark - Object Conversion + (FTASyncParent *)FTA_newObjectForClass:(NSEntityDescription *)entityDesc WithRemoteObject:(PFObject *)parseObject { - //Make sure a local object doesn't already exist from traversing a relationship - FTASyncParent *localObject = [FTASyncParent FTA_localObjectForClass:entityDesc WithRemoteId:parseObject.objectId]; - if (localObject) { - return localObject; - } - - FTASyncParent *newObject = [NSEntityDescription insertNewObjectForEntityForName:[entityDesc name] inManagedObjectContext:[NSManagedObjectContext MR_contextForCurrentThread]]; - [newObject setValue:[NSNumber numberWithBool:NO] forKey:@"createdHere"]; - - //Make sure objectId is set - newObject.objectId = parseObject.objectId; - - return newObject; + return [self FTA_newObjectForClass:entityDesc WithRemoteObject:parseObject WithContext:[NSManagedObjectContext MR_contextForCurrentThread]]; +} + ++ (FTASyncParent *)FTA_newObjectForClass:(NSEntityDescription *)entityDesc WithRemoteObject:(PFObject *)parseObject WithContext:(NSManagedObjectContext *) context { + //Make sure a local object doesn't already exist from traversing a relationship + FTASyncParent *localObject = [FTASyncParent FTA_localObjectForClass:entityDesc WithRemoteId:parseObject.objectId WithContext:context]; + if (localObject) { + return localObject; + } + + FTASyncParent *newObject = [NSEntityDescription insertNewObjectForEntityForName:[entityDesc name] inManagedObjectContext:context]; + [newObject setValue:[NSNumber numberWithBool:NO] forKey:@"createdHere"]; + + //Make sure objectId is set + newObject.objectId = parseObject.objectId; + + return newObject; } - (void)updateRemoteObject:(PFObject *)parseObject { @@ -329,12 +380,26 @@ - (void)updateRemoteObject:(PFObject *)parseObject { //If attribute is NSData, need to convert this to a PFFile if ([value isKindOfClass:[NSData class]]) { + // Upload array column (rei kubonaga) + id unarchiveObject; + @try { + unarchiveObject = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)value]; + }@catch (NSException *exception) { + // if nsdata is uiimage, exception occurred. + unarchiveObject = nil; + NSLog(@"unarchive exception name :%@",exception.name); + NSLog(@"unarchive exception reason:%@",exception.reason); + } + if ([unarchiveObject isKindOfClass:[NSArray class]]){ + [parseObject setObject:unarchiveObject forKey:attribute]; + continue; + } NSString *fileName = nil; if (parseObject.objectId) { - fileName = [NSString stringWithFormat:@"%@-%@.png", parseObject.objectId, attribute]; + fileName = [NSString stringWithFormat:@"%@-%@", parseObject.objectId, attribute]; } else { - fileName = [NSString stringWithFormat:@"newObj-%@.png", attribute]; + fileName = [NSString stringWithFormat:@"newObj-%@", attribute]; } PFFile *file = [PFFile fileWithName:fileName data:(NSData *)value]; @@ -344,8 +409,12 @@ - (void)updateRemoteObject:(PFObject *)parseObject { continue; } - if (value != nil && ![attribute isEqualToString:@"createdHere"] && ![attribute isEqualToString:@"updatedAt"] && ![attribute isEqualToString:@"syncStatus"] && ![attribute isEqualToString:@"objectId"]) { - [parseObject setObject:value forKey:attribute]; + if (![attribute isEqualToString:@"createdHere"] && ![attribute isEqualToString:@"createdAt"] && ![attribute isEqualToString:@"updatedAt"] && ![attribute isEqualToString:@"syncStatus"] && ![attribute isEqualToString:@"objectId"]) { + if (value) { + [parseObject setObject:value forKey:attribute]; + } else { + [parseObject setObject:[NSNull null] forKey:attribute]; + } } } @@ -359,29 +428,58 @@ - (void)updateRemoteObject:(PFObject *)parseObject { for (NSString *relationship in relationships) { NSObject *value = [self valueForKey:relationship]; - if ([[relationships objectForKey:relationship] isToMany]) { - //To-many relationship + NSRelationshipDescription *relationshipDescription = [relationships objectForKey:relationship]; + + if ([relationshipDescription isToMany]) { + // To-many relationship + NSSet *relatedObjects = (NSSet *)value; - NSMutableArray *objectArray = [[NSMutableArray alloc] initWithCapacity:[relatedObjects count]]; - //Build an array of PFObject pointers or new PFObjects - for (FTASyncParent *relatedObject in relatedObjects) { - //TODO: Update Parse SDK and use the new PFRelation - PFObject *relatedRemoteObject = nil; - if (!relatedObject.objectId) { - relatedObject.fromRelationship = YES; - relatedRemoteObject = relatedObject.remoteObject; - relatedObject.fromRelationship = NO; - relatedObject.syncStatusValue = 3; + // AKB: add mechanism for using PFRelation if n:n + // many-to-many relationship + if ([[relationshipDescription inverseRelationship] isToMany]) { + + PFRelation *relation = [parseObject relationforKey:relationship]; // AKB: add + + //Build an array of PFObject pointers or new PFObjects + for (FTASyncParent *relatedObject in relatedObjects) { + //TODO: Update Parse SDK and use the new PFRelation + PFObject *relatedRemoteObject = nil; + if (!relatedObject.objectId) { + relatedObject.fromRelationship = YES; + relatedRemoteObject = relatedObject.remoteObject; + relatedObject.fromRelationship = NO; + relatedObject.syncStatusValue = 3; + } + else { + relatedRemoteObject = [PFObject objectWithoutDataWithClassName:[relatedObject parseClassname] objectId:relatedObject.objectId]; + } + + [relation addObject:relatedRemoteObject]; // AKB: add } - else { - relatedRemoteObject = [PFObject objectWithoutDataWithClassName:[relatedObject parseClassname] objectId:relatedObject.objectId]; + + } else { + NSMutableArray *objectArray = [[NSMutableArray alloc] initWithCapacity:[relatedObjects count]]; + + //Build an array of PFObject pointers or new PFObjects + for (FTASyncParent *relatedObject in relatedObjects) { + //TODO: Update Parse SDK and use the new PFRelation + PFObject *relatedRemoteObject = nil; + if (!relatedObject.objectId) { + relatedObject.fromRelationship = YES; + relatedRemoteObject = relatedObject.remoteObject; + relatedObject.fromRelationship = NO; + relatedObject.syncStatusValue = 3; + } + else { + relatedRemoteObject = [PFObject objectWithoutDataWithClassName:[relatedObject parseClassname] objectId:relatedObject.objectId]; + } + + [objectArray addObject:relatedRemoteObject]; } - [objectArray addObject:relatedRemoteObject]; + [parseObject setObject:objectArray forKey:relationship]; } - - [parseObject setObject:objectArray forKey:relationship]; } else { //To-one relationship @@ -400,12 +498,17 @@ - (void)updateRemoteObject:(PFObject *)parseObject { else { relatedRemoteObject = [PFObject objectWithoutDataWithClassName:[relatedObject parseClassname] objectId:relatedObject.objectId]; } + [parseObject setObject:relatedRemoteObject forKey:relationship]; } } } - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { + [self updateObjectWithRemoteObject:parseObject WithContext:[NSManagedObjectContext MR_contextForCurrentThread]]; +} + +- (void)updateObjectWithRemoteObject:(PFObject *)parseObject WithContext:(NSManagedObjectContext *) context { NSDictionary *attributes = [[self entity] attributesByName]; NSDictionary *relationships = [[self entity] relationshipsByName]; @@ -413,16 +516,31 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { if (self.syncStatusValue != 1) { //Local changes take priority for (NSString *attribute in attributes) { NSString *className = [[attributes valueForKey:attribute] attributeValueClassName]; - + if ([className isEqualToString:@"NSData"]) { - PFFile* remoteFile = [parseObject objectForKey:attribute]; - [self setValue:[NSData dataWithData:[remoteFile getData]] forKey:attribute]; - continue; + id value = [parseObject objectForKey:attribute]; + if ([value isKindOfClass:[NSArray class]]) { + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value]; + [self setValue:data forKey:attribute]; + continue; + } else if ([value isKindOfClass:[NSNull class]]) { + [self setValue:nil forKey:attribute]; + continue; + } else if (value == nil) { + continue; + } else { + PFFile* remoteFile = value; + [self setValue:[NSData dataWithData:[remoteFile getData]] forKey:attribute]; + continue; + } } if (![attribute isEqualToString:@"createdHere"] && ![attribute isEqualToString:@"updatedAt"] && ![attribute isEqualToString:@"syncStatus"] && ![attribute isEqualToString:@"objectId"]) { - //TODO: Catch NSUndefinedKeyException if key does not exist on PFObject + //TODO: Catch NSUndefinedKeyException if key does not exist on PFObject + id value = [parseObject objectForKey:attribute]; + if (value && ![value isKindOfClass:[NSNull class]]) { [self setValue:[parseObject valueForKey:attribute] forKey:attribute]; + } } } } @@ -432,10 +550,24 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { NSObject *value = [self valueForKey:relationship]; NSEntityDescription *destEntity = [[relationships objectForKey:relationship] destinationEntity]; - if ([[relationships objectForKey:relationship] isToMany]) { - //To-many relationship + NSRelationshipDescription *relationshipDescription = [relationships objectForKey:relationship]; + + if ([relationshipDescription isToMany]) { + // To-many relationship + NSMutableArray *relatedLocalObjects = [NSMutableArray arrayWithArray:[(NSSet *)value allObjects]]; - NSMutableArray *relatedRemoteObjects = [NSMutableArray arrayWithArray:[parseObject objectForKey:relationship]]; + NSMutableArray *relatedRemoteObjects = nil; + + if ([[relationshipDescription inverseRelationship] isToMany]) { + // AKB: if many-to-many use PFRelation + PFRelation *relation = [parseObject relationforKey:relationship]; + PFQuery *query = [relation query]; + + relatedRemoteObjects = [NSMutableArray arrayWithArray:[query findObjects]]; + + } else { + relatedRemoteObjects = [NSMutableArray arrayWithArray:[parseObject objectForKey:relationship]]; + } //Empty relationships in a PFObject will return an NSNull object if ([relatedRemoteObjects isKindOfClass:[NSNull class]]) { @@ -457,17 +589,15 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { FSLog(@"Keeping local related object"); continue; } - SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Set", relationship]); + SEL selector = NSSelectorFromString([NSString stringWithFormat:@"remove%@Object:", relationship]); if ([self respondsToSelector:selector]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" - NSMutableOrderedSet *theSet = [self performSelector:selector]; - [theSet removeObject:localObject]; + [self performSelector:selector withObject:localObject]; #pragma clang diagnostic pop } else { - NSString *selString = NSStringFromSelector(selector); - FSALog(@"%@ entity does not respond to selector: %@", [[self entity] name], selString); + FSALog(@"%@ entity does not respond to selector: %@", [[self entity] name], NSStringFromSelector(selector)); } } @@ -475,7 +605,7 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { [relatedRemoteObjects removeObjectsInArray:localObjectsForRemoteIds]; FSLog(@"Walking through adding objects: %@", relatedRemoteObjects); for (PFObject *relatedRemoteObject in relatedRemoteObjects) { - FTASyncParent *localObject = [FTASyncParent FTA_localObjectForClass:destEntity WithRemoteId:relatedRemoteObject.objectId]; + FTASyncParent *localObject = [FTASyncParent FTA_localObjectForClass:destEntity WithRemoteId:relatedRemoteObject.objectId WithContext:context]; if (!localObject) { //Related object doesn't exist locally @@ -487,7 +617,7 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { } FSLog(@"Local object with remoteId %@ in relationship %@ was not found", relatedRemoteObject.objectId, relationship); - localObject = [FTASyncParent FTA_newObjectForClass:destEntity WithRemoteObject:relatedRemoteObject]; + localObject = [FTASyncParent FTA_newObjectForClass:destEntity WithRemoteObject:relatedRemoteObject WithContext:context]; localObject.syncStatusValue = 0; //Object is not new local nor does it have local changes } else if (![self shouldUseRemoteObject:relatedRemoteObject insteadOfLocal:nil forToMany:YES relationship:relationship]) { @@ -495,26 +625,24 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { continue; } - //SEL selector = NSSelectorFromString([NSString stringWithFormat:@"add%@Object:", [destEntity name]]); - SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Set", relationship]); + SEL selector = NSSelectorFromString([NSString stringWithFormat:@"add%@Object:", relationship]); if ([self respondsToSelector:selector]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" - //[self performSelector:selector withObject:localObject]; - NSMutableOrderedSet *theSet = [self performSelector:selector]; - [theSet addObject:localObject]; + [self performSelector:selector withObject:localObject]; #pragma clang diagnostic pop } else { - NSString *selString = NSStringFromSelector(selector); - FSALog(@"%@ entity does not respond to selector: %@", [[self entity] name], selString); + FSALog(@"%@ entity does not respond to selector: %@", [[self entity] name], NSStringFromSelector(selector)); } } } else { + NSLog(@"relation ship!"); //To-one relationship PFObject *relatedRemoteObject = [parseObject objectForKey:relationship]; - FTASyncParent *localRelatedObject = [FTASyncParent FTA_localObjectForClass:destEntity WithRemoteId:relatedRemoteObject.objectId]; + NSLog(@"parseObject: %@", relatedRemoteObject); + FTASyncParent *localRelatedObject = [FTASyncParent FTA_localObjectForClass:destEntity WithRemoteId:relatedRemoteObject.objectId WithContext:context]; FTASyncParent *currentLocalRelatedObject = [self valueForKey:relationship]; if (!localRelatedObject && relatedRemoteObject) { @@ -526,9 +654,12 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { continue; } - FSLog(@"Local object with remoteId %@ in relationship %@ was not found", relatedRemoteObject.objectId, relationship); - localRelatedObject = [FTASyncParent FTA_newObjectForClass:destEntity WithRemoteObject:relatedRemoteObject]; + FSLog(@"Local object with remoteId %@ in relationship %@ was not found %@", relatedRemoteObject.objectId, relationship, relatedRemoteObject); + localRelatedObject = [FTASyncParent FTA_newObjectForClass:destEntity WithRemoteObject:relatedRemoteObject WithContext:context]; localRelatedObject.syncStatusValue = 0; + if ([relatedRemoteObject isDataAvailable]) { + [localRelatedObject updateObjectWithRemoteObject:relatedRemoteObject WithContext:context]; + } } else if(![self shouldUseRemoteObject:relatedRemoteObject insteadOfLocal:currentLocalRelatedObject forToMany:NO relationship:relationship]) { continue; @@ -538,8 +669,9 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { } } - if (self.syncStatusValue == 2) { + if (self.syncStatusValue == 2) { //This is a new object from remote so reset syncStatus + NSLog(@"sync new object!"); [self FTA_updateObjectMetadataWithRemoteObject:parseObject andResetSyncStatus:YES]; } else { @@ -551,6 +683,7 @@ - (void)updateObjectWithRemoteObject:(PFObject *)parseObject { - (void)FTA_updateObjectMetadataWithRemoteObject:(PFObject *)parseObject andResetSyncStatus:(BOOL)resetStatus { if (!self.objectId) { + NSLog(@"set!!! %@", parseObject.objectId); self.objectId = parseObject.objectId; } else if (![[self valueForKey:@"objectId"] isEqualToString:parseObject.objectId]) { @@ -589,7 +722,7 @@ + (void)FTA_updateObjectsForClass:(NSEntityDescription *)entityDesc withRemoteOb for (PFObject *remoteObject in parseObjects) { FTASyncParent *localObject = [self FTA_localObjectForClass:entityDesc WithRemoteId:remoteObject.objectId]; if (!localObject) { - FSALog(@"Could not find local object matching remote object: %@", remoteObject); + //FSALog(@"Could not find local object matching remote object: %@", remoteObject); localObject = [FTASyncParent FTA_newObjectForClass:entityDesc WithRemoteObject:remoteObject]; //break; } @@ -601,10 +734,10 @@ + (void)FTA_updateObjectsForClass:(NSEntityDescription *)entityDesc withRemoteOb + (void)FTA_deleteObjectsForClass:(NSEntityDescription *)entityDesc withRemoteObjects:(NSArray *)parseObjects { for (PFObject *remoteObject in parseObjects) { FTASyncParent *localObject = [self FTA_localObjectForClass:entityDesc WithRemoteId:remoteObject.objectId]; + if (!localObject) { FSLog(@"Object already removed locally: %@", remoteObject); } - [localObject MR_deleteEntity]; } } diff --git a/Source/_FTASyncParent.h b/Source/_FTASyncParent.h new file mode 100644 index 0000000..7a9a681 --- /dev/null +++ b/Source/_FTASyncParent.h @@ -0,0 +1,142 @@ +// DO NOT EDIT. This file is machine-generated and constantly overwritten. +// Make changes to FTASyncParent.h instead. + +#import + + +extern const struct FTASyncParentAttributes { + __unsafe_unretained NSString *createdHere; + __unsafe_unretained NSString *deleted; + __unsafe_unretained NSString *objectId; + __unsafe_unretained NSString *syncStatus; + __unsafe_unretained NSString *updatedAt; +} FTASyncParentAttributes; + +extern const struct FTASyncParentRelationships { +} FTASyncParentRelationships; + +extern const struct FTASyncParentFetchedProperties { +} FTASyncParentFetchedProperties; + + + + + + + + +@interface FTASyncParentID : NSManagedObjectID {} +@end + +@interface _FTASyncParent : NSManagedObject {} ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; ++ (NSString*)entityName; ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; +- (FTASyncParentID*)objectID; + + + + +@property (nonatomic, strong) NSNumber* createdHere; + + +@property BOOL createdHereValue; +- (BOOL)createdHereValue; +- (void)setCreatedHereValue:(BOOL)value_; + +//- (BOOL)validateCreatedHere:(id*)value_ error:(NSError**)error_; + + + + +@property (nonatomic, strong) NSNumber* deleted; + + +@property BOOL deletedValue; +- (BOOL)deletedValue; +- (void)setDeletedValue:(BOOL)value_; + +//- (BOOL)validateDeleted:(id*)value_ error:(NSError**)error_; + + + + +@property (nonatomic, strong) NSString* objectId; + + +//- (BOOL)validateObjectId:(id*)value_ error:(NSError**)error_; + + + + +@property (nonatomic, strong) NSNumber* syncStatus; + + +@property int16_t syncStatusValue; +- (int16_t)syncStatusValue; +- (void)setSyncStatusValue:(int16_t)value_; + +//- (BOOL)validateSyncStatus:(id*)value_ error:(NSError**)error_; + + + + +@property (nonatomic, strong) NSDate* updatedAt; + + +//- (BOOL)validateUpdatedAt:(id*)value_ error:(NSError**)error_; + + + + + + +@end + +@interface _FTASyncParent (CoreDataGeneratedAccessors) + +@end + +@interface _FTASyncParent (CoreDataGeneratedPrimitiveAccessors) + + +- (NSNumber*)primitiveCreatedHere; +- (void)setPrimitiveCreatedHere:(NSNumber*)value; + +- (BOOL)primitiveCreatedHereValue; +- (void)setPrimitiveCreatedHereValue:(BOOL)value_; + + + + +- (NSNumber*)primitiveDeleted; +- (void)setPrimitiveDeleted:(NSNumber*)value; + +- (BOOL)primitiveDeletedValue; +- (void)setPrimitiveDeletedValue:(BOOL)value_; + + + + +- (NSString*)primitiveObjectId; +- (void)setPrimitiveObjectId:(NSString*)value; + + + + +- (NSNumber*)primitiveSyncStatus; +- (void)setPrimitiveSyncStatus:(NSNumber*)value; + +- (int16_t)primitiveSyncStatusValue; +- (void)setPrimitiveSyncStatusValue:(int16_t)value_; + + + + +- (NSDate*)primitiveUpdatedAt; +- (void)setPrimitiveUpdatedAt:(NSDate*)value; + + + + +@end diff --git a/Source/_FTASyncParent.m b/Source/_FTASyncParent.m new file mode 100644 index 0000000..7f9fb8d --- /dev/null +++ b/Source/_FTASyncParent.m @@ -0,0 +1,162 @@ +// DO NOT EDIT. This file is machine-generated and constantly overwritten. +// Make changes to FTASyncParent.m instead. + +#import "_FTASyncParent.h" + +const struct FTASyncParentAttributes FTASyncParentAttributes = { + .createdHere = @"createdHere", + .deleted = @"deleted", + .objectId = @"objectId", + .syncStatus = @"syncStatus", + .updatedAt = @"updatedAt", +}; + +const struct FTASyncParentRelationships FTASyncParentRelationships = { +}; + +const struct FTASyncParentFetchedProperties FTASyncParentFetchedProperties = { +}; + +@implementation FTASyncParentID +@end + +@implementation _FTASyncParent + ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { + NSParameterAssert(moc_); + return [NSEntityDescription insertNewObjectForEntityForName:@"FTASyncParent" inManagedObjectContext:moc_]; +} + ++ (NSString*)entityName { + return @"FTASyncParent"; +} + ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { + NSParameterAssert(moc_); + return [NSEntityDescription entityForName:@"FTASyncParent" inManagedObjectContext:moc_]; +} + +- (FTASyncParentID*)objectID { + return (FTASyncParentID*)[super objectID]; +} + ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; + + if ([key isEqualToString:@"createdHereValue"]) { + NSSet *affectingKey = [NSSet setWithObject:@"createdHere"]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + } + if ([key isEqualToString:@"deletedValue"]) { + NSSet *affectingKey = [NSSet setWithObject:@"deleted"]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + } + if ([key isEqualToString:@"syncStatusValue"]) { + NSSet *affectingKey = [NSSet setWithObject:@"syncStatus"]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + } + + return keyPaths; +} + + + + +@dynamic createdHere; + + + +- (BOOL)createdHereValue { + NSNumber *result = [self createdHere]; + return [result boolValue]; +} + +- (void)setCreatedHereValue:(BOOL)value_ { + [self setCreatedHere:[NSNumber numberWithBool:value_]]; +} + +- (BOOL)primitiveCreatedHereValue { + NSNumber *result = [self primitiveCreatedHere]; + return [result boolValue]; +} + +- (void)setPrimitiveCreatedHereValue:(BOOL)value_ { + [self setPrimitiveCreatedHere:[NSNumber numberWithBool:value_]]; +} + + + + + +@dynamic deleted; + + + +- (BOOL)deletedValue { + NSNumber *result = [self deleted]; + return [result boolValue]; +} + +- (void)setDeletedValue:(BOOL)value_ { + [self setDeleted:[NSNumber numberWithBool:value_]]; +} + +- (BOOL)primitiveDeletedValue { + NSNumber *result = [self primitiveDeleted]; + return [result boolValue]; +} + +- (void)setPrimitiveDeletedValue:(BOOL)value_ { + [self setPrimitiveDeleted:[NSNumber numberWithBool:value_]]; +} + + + + + +@dynamic objectId; + + + + + + +@dynamic syncStatus; + + + +- (int16_t)syncStatusValue { + NSNumber *result = [self syncStatus]; + return [result shortValue]; +} + +- (void)setSyncStatusValue:(int16_t)value_ { + [self setSyncStatus:[NSNumber numberWithShort:value_]]; +} + +- (int16_t)primitiveSyncStatusValue { + NSNumber *result = [self primitiveSyncStatus]; + return [result shortValue]; +} + +- (void)setPrimitiveSyncStatusValue:(int16_t)value_ { + [self setPrimitiveSyncStatus:[NSNumber numberWithShort:value_]]; +} + + + + + +@dynamic updatedAt; + + + + + + + + + + + +@end