├── Pods ├── Headers │ ├── Private │ │ └── Mantle │ │ │ ├── Mantle.h │ │ │ ├── MTLModel.h │ │ │ ├── EXTScope.h │ │ │ ├── MTLJSONAdapter.h │ │ │ ├── MTLReflection.h │ │ │ ├── metamacros.h │ │ │ ├── MTLModel+NSCoding.h │ │ │ ├── MTLValueTransformer.h │ │ │ ├── EXTKeyPathCoding.h │ │ │ ├── EXTRuntimeExtensions.h │ │ │ ├── NSError+MTLModelException.h │ │ │ ├── MTLTransformerErrorHandling.h │ │ │ ├── NSDictionary+MTLJSONKeyPath.h │ │ │ ├── NSObject+MTLComparisonAdditions.h │ │ │ ├── NSArray+MTLManipulationAdditions.h │ │ │ ├── NSDictionary+MTLMappingAdditions.h │ │ │ ├── NSDictionary+MTLManipulationAdditions.h │ │ │ ├── NSValueTransformer+MTLInversionAdditions.h │ │ │ └── NSValueTransformer+MTLPredefinedTransformerAdditions.h │ └── Public │ │ └── Mantle │ │ ├── Mantle.h │ │ ├── MTLModel.h │ │ ├── MTLJSONAdapter.h │ │ ├── MTLReflection.h │ │ ├── MTLModel+NSCoding.h │ │ ├── MTLValueTransformer.h │ │ ├── MTLTransformerErrorHandling.h │ │ ├── NSDictionary+MTLJSONKeyPath.h │ │ ├── NSError+MTLModelException.h │ │ ├── NSArray+MTLManipulationAdditions.h │ │ ├── NSDictionary+MTLMappingAdditions.h │ │ ├── NSObject+MTLComparisonAdditions.h │ │ ├── NSDictionary+MTLManipulationAdditions.h │ │ ├── NSValueTransformer+MTLInversionAdditions.h │ │ └── NSValueTransformer+MTLPredefinedTransformerAdditions.h ├── Target Support Files │ ├── Mantle │ │ ├── Mantle-dummy.m │ │ ├── Mantle-prefix.pch │ │ └── Mantle.xcconfig │ └── Pods-OXCMantle │ │ ├── Pods-OXCMantle-dummy.m │ │ ├── Pods-OXCMantle.debug.xcconfig │ │ ├── Pods-OXCMantle.release.xcconfig │ │ ├── Pods-OXCMantle-acknowledgements.markdown │ │ ├── Pods-OXCMantle-acknowledgements.plist │ │ ├── Pods-OXCMantle-frameworks.sh │ │ └── Pods-OXCMantle-resources.sh ├── Manifest.lock └── Mantle │ ├── Mantle │ ├── extobjc │ │ ├── EXTScope.m │ │ ├── EXTKeyPathCoding.h │ │ ├── EXTRuntimeExtensions.h │ │ ├── EXTScope.h │ │ └── EXTRuntimeExtensions.m │ ├── NSObject+MTLComparisonAdditions.m │ ├── NSObject+MTLComparisonAdditions.h │ ├── MTLTransformerErrorHandling.m │ ├── NSDictionary+MTLMappingAdditions.h │ ├── NSValueTransformer+MTLInversionAdditions.h │ ├── NSDictionary+MTLMappingAdditions.m │ ├── NSError+MTLModelException.h │ ├── Mantle.h │ ├── NSArray+MTLManipulationAdditions.h │ ├── NSArray+MTLManipulationAdditions.m │ ├── NSDictionary+MTLJSONKeyPath.h │ ├── NSError+MTLModelException.m │ ├── NSDictionary+MTLManipulationAdditions.m │ ├── NSDictionary+MTLManipulationAdditions.h │ ├── MTLReflection.h │ ├── NSValueTransformer+MTLInversionAdditions.m │ ├── NSDictionary+MTLJSONKeyPath.m │ ├── MTLReflection.m │ ├── MTLValueTransformer.h │ ├── MTLTransformerErrorHandling.h │ ├── MTLValueTransformer.m │ ├── MTLModel+NSCoding.h │ ├── NSValueTransformer+MTLPredefinedTransformerAdditions.h │ ├── MTLModel.h │ ├── MTLModel+NSCoding.m │ └── MTLModel.m │ └── LICENSE.md ├── Podfile ├── OXCMantle.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── OXCMantle.xcscheme ├── OXCMantle ├── ViewController.h ├── Classes │ ├── OXCModel │ │ ├── OXModel.h │ │ ├── NSValueTransformer+MantleExtention.h │ │ ├── OXModel.m │ │ └── NSValueTransformer+MantleExtention.m │ ├── OXCValidation │ │ ├── OXLongTypeValidator.h │ │ ├── OXDateTypeValidator.h │ │ ├── OXUnsignedLongTypeValicdator.h │ │ ├── OXArrayTypeValidator.h │ │ ├── OXNumberTypeValidator.h │ │ ├── OXStringTypeValidator.h │ │ ├── OXFloatTypeValidator.h │ │ ├── OXBooleanTypeValidator.h │ │ ├── OXDictionaryTypeValidator.h │ │ ├── OXDoubleTypeValidator.h │ │ ├── OXIntegerTypeValidator.h │ │ ├── OXUnsignedIntegerTypeValidator.h │ │ ├── OXBaseModelValidator.h │ │ ├── NSString+ValidationUtils.h │ │ ├── OXDoubleTypeValidator.m │ │ ├── OXIntegerTypeValidator.m │ │ ├── OXUnsignedLongTypeValicdator.m │ │ ├── OXArrayTypeValidator.m │ │ ├── OXDictionaryTypeValidator.m │ │ ├── OXNumberTypeValidator.m │ │ ├── OXLongTypeValidator.m │ │ ├── OXBaseValidator.h │ │ ├── OXFloatTypeValidator.m │ │ ├── OXBaseValidator.m │ │ ├── OXValidatorReflection.h │ │ ├── OXBaseModelValidator.m │ │ ├── OXStringTypeValidator.m │ │ ├── OXUnsignedIntegerTypeValidator.m │ │ ├── OXDValidationFunctions.h │ │ ├── NSString+ValidationUtils.m │ │ ├── OXBooleanTypeValidator.m │ │ ├── OXEXTRuntimeExtensions.h │ │ ├── OXDateTypeValidator.m │ │ ├── OXEXTRuntimeExtensions.m │ │ ├── OXValidatorReflection.m │ │ └── OXDValidationFunctions.m │ └── OXCMantle.h ├── AppDelegate.h ├── main.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── ModelExample │ ├── ProtocolExample.h │ ├── ModelExample.h │ └── ModelExample.m ├── Info.plist ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.xib ├── ViewController.m └── AppDelegate.m ├── OXCMantle.xcworkspace └── contents.xcworkspacedata ├── Podfile.lock ├── .gitignore ├── .travis.yml ├── LICENSE ├── OXCMantle.podspec ├── OXCMantleTests └── OXCMantleTests.m └── README.md /Pods/Headers/Private/Mantle/Mantle.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/Mantle.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/Mantle.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/Mantle.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLModel.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLModel.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLModel.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLModel.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/EXTScope.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/extobjc/EXTScope.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLJSONAdapter.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLJSONAdapter.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLReflection.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLReflection.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/metamacros.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/extobjc/metamacros.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLJSONAdapter.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLJSONAdapter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLReflection.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLReflection.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLModel+NSCoding.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLModel+NSCoding.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLModel+NSCoding.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLModel+NSCoding.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLValueTransformer.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLValueTransformer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLValueTransformer.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLValueTransformer.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/EXTKeyPathCoding.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/extobjc/EXTKeyPathCoding.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/EXTRuntimeExtensions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/extobjc/EXTRuntimeExtensions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSError+MTLModelException.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSError+MTLModelException.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/MTLTransformerErrorHandling.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLTransformerErrorHandling.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSDictionary+MTLJSONKeyPath.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSError+MTLModelException.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSError+MTLModelException.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/MTLTransformerErrorHandling.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/MTLTransformerErrorHandling.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSDictionary+MTLJSONKeyPath.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSObject+MTLComparisonAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSObject+MTLComparisonAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSArray+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSArray+MTLManipulationAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSDictionary+MTLMappingAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLMappingAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSObject+MTLComparisonAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSObject+MTLComparisonAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSArray+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSArray+MTLManipulationAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSDictionary+MTLMappingAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLMappingAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSDictionary+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | target "OXCMantle" do 2 | xcodeproj 'OXCMantle.xcodeproj' 3 | platform :ios ,'7.0' 4 | pod 'Mantle' 5 | end 6 | -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSDictionary+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSValueTransformer+MTLInversionAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSValueTransformer+MTLInversionAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h: -------------------------------------------------------------------------------- 1 | ../../../Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h -------------------------------------------------------------------------------- /Pods/Target Support Files/Mantle/Mantle-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Mantle : NSObject 3 | @end 4 | @implementation PodsDummy_Mantle 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_OXCMantle : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_OXCMantle 5 | @end 6 | -------------------------------------------------------------------------------- /OXCMantle.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OXCMantle/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Mantle/Mantle-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /OXCMantle.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCModel/OXModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXModel.h 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "Mantle.h" 10 | #import "NSValueTransformer+MantleExtention.h" 11 | @interface OXModel : MTLModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXLongTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXLongTypeValidator.h 3 | // Oxen 4 | // 5 | // Created by Matthew on 7/2/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "OXNumberTypeValidator.h" 10 | 11 | @interface OXLongTypeValidator : OXNumberTypeValidator 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Mantle (2.1.0): 3 | - Mantle/extobjc (= 2.1.0) 4 | - Mantle/extobjc (2.1.0) 5 | 6 | DEPENDENCIES: 7 | - Mantle 8 | 9 | SPEC CHECKSUMS: 10 | Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b 11 | 12 | PODFILE CHECKSUM: 87211aad168b80d7e8faf9e2092c4e6decbf6998 13 | 14 | COCOAPODS: 1.2.1.beta.1 15 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Mantle (2.1.0): 3 | - Mantle/extobjc (= 2.1.0) 4 | - Mantle/extobjc (2.1.0) 5 | 6 | DEPENDENCIES: 7 | - Mantle 8 | 9 | SPEC CHECKSUMS: 10 | Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b 11 | 12 | PODFILE CHECKSUM: 87211aad168b80d7e8faf9e2092c4e6decbf6998 13 | 14 | COCOAPODS: 1.2.1.beta.1 15 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDateTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXDateTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXDateTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXUnsignedLongTypeValicdator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXUnsignLognTypeValicdator.h 3 | // Oxen 4 | // 5 | // Created by Matthew on 12/18/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "OXNumberTypeValidator.h" 10 | 11 | @interface OXUnsignedLongTypeValicdator : OXNumberTypeValidator 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXArrayTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXArrayTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXArrayTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXNumberTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXNumberTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXNumberTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXStringTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXStringTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXStringTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXFloatTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXFloatTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXNumberTypeValidator.h" 12 | 13 | 14 | @interface OXFloatTypeValidator : OXNumberTypeValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBooleanTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXBooleanTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXNumberTypeValidator.h" 12 | 13 | 14 | @interface OXBooleanTypeValidator : OXNumberTypeValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDictionaryTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXDictionaryTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXDictionaryTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDoubleTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXDoubleTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXNumberTypeValidator.h" 12 | 13 | 14 | @interface OXDoubleTypeValidator : OXNumberTypeValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXIntegerTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXIntegerTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXNumberTypeValidator.h" 12 | 13 | 14 | @interface OXIntegerTypeValidator : OXNumberTypeValidator 15 | 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXUnsignedIntegerTypeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXUnsignedIntegerTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXUnsignedIntegerTypeValidator : OXBaseValidator 15 | 16 | @end -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/extobjc/EXTScope.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXTScope.m 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-05-04. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "EXTScope.h" 11 | 12 | void mtl_executeCleanupBlock (__strong mtl_cleanupBlock_t *block) { 13 | (*block)(); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBaseModelValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXBaseModelValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | #import "OXBaseValidator.h" 12 | 13 | 14 | @interface OXBaseModelValidator : OXBaseValidator 15 | -(id)initWithClass:(Class)baseModelClass; 16 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCMantle.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXCMantle.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/6/23. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #ifndef OXCMantle_h 10 | #define OXCMantle_h 11 | #import 12 | #import "NSValueTransformer+MantleExtention.h" 13 | #import 14 | #import "OXModel.h" 15 | #endif /* OXCMantle_h */ 16 | -------------------------------------------------------------------------------- /OXCMantle/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MTLComparisonAdditions.m 3 | // Mantle 4 | // 5 | // Created by Josh Vera on 10/26/12. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | // Portions copyright (c) 2011 Bitswift. All rights reserved. 9 | // See the LICENSE file for more information. 10 | // 11 | 12 | #import "NSObject+MTLComparisonAdditions.h" 13 | 14 | BOOL MTLEqualObjects(id obj1, id obj2) { 15 | return (obj1 == obj2 || [obj1 isEqual:obj2]); 16 | } 17 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MTLComparisonAdditions.h 3 | // Mantle 4 | // 5 | // Created by Josh Vera on 10/26/12. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | // Portions copyright (c) 2011 Bitswift. All rights reserved. 9 | // See the LICENSE file for more information. 10 | // 11 | 12 | #import 13 | 14 | /// Returns whether both objects are identical or equal via -isEqual: 15 | BOOL MTLEqualObjects(id obj1, id obj2); 16 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/NSString+ValidationUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+NSString_ValidationUtils.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (ValidationUtils) 12 | + (NSString *)capitalizeFirstCharacter:(NSString *)string; 13 | + (NSString *)stripNonNumericCharacters:(NSString *)string; 14 | + (NSString *)leftPadString:(NSString *)string length:(NSUInteger)length padCharacter:(NSString *)padCharacter; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLTransformerErrorHandling.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTLTransformerErrorHandling.h 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 10/6/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLTransformerErrorHandling.h" 10 | 11 | NSString * const MTLTransformerErrorHandlingErrorDomain = @"MTLTransformerErrorHandlingErrorDomain"; 12 | 13 | const NSInteger MTLTransformerErrorHandlingErrorInvalidInput = 1; 14 | 15 | NSString * const MTLTransformerErrorHandlingInputValueErrorKey = @"MTLTransformerErrorHandlingInputValueErrorKey"; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLMappingAdditions.h 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 10/31/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (MTLMappingAdditions) 12 | 13 | /// Creates an identity mapping for serialization. 14 | /// 15 | /// class - A subclass of MTLModel. 16 | /// 17 | /// Returns a dictionary that maps all properties of the given class to 18 | /// themselves. 19 | + (NSDictionary *)mtl_identityPropertyMapWithModel:(Class)modelClass; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Mantle/Mantle.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Mantle 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Mantle" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Mantle" 4 | OTHER_LDFLAGS = -framework "Foundation" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Mantle 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Mantle" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Mantle" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Mantle" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Mantle" -framework "Foundation" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Mantle" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Mantle" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Mantle" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Mantle" -framework "Foundation" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSValueTransformer+MTLInversionAdditions.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-05-18. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSValueTransformer (MTLInversionAdditions) 12 | 13 | /// Flips the direction of the receiver's transformation, such that 14 | /// -transformedValue: will become -reverseTransformedValue:, and vice-versa. 15 | /// 16 | /// The receiver must allow reverse transformation. 17 | /// 18 | /// Returns an inverted transformer. 19 | - (NSValueTransformer *)mtl_invertedTransformer; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLMappingAdditions.m 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 10/31/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLModel.h" 10 | 11 | #import "NSDictionary+MTLMappingAdditions.h" 12 | 13 | @implementation NSDictionary (MTLMappingAdditions) 14 | 15 | + (NSDictionary *)mtl_identityPropertyMapWithModel:(Class)modelClass { 16 | NSCParameterAssert([modelClass conformsToProtocol:@protocol(MTLModel)]); 17 | 18 | NSArray *propertyKeys = [modelClass propertyKeys].allObjects; 19 | 20 | return [NSDictionary dictionaryWithObjects:propertyKeys forKeys:propertyKeys]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_workspace: OXCMantle.xcworkspace 3 | git: 4 | submodules: false 5 | before_install: 6 | - pod install 7 | script: 8 | - xcodebuild $XCODE_ACTION 9 | -workspace "$TRAVIS_XCODE_WORKSPACE" 10 | -scheme "$TRAVIS_XCODE_SCHEME" 11 | -sdk "$XCODE_SDK" 12 | -destination "$XCODE_DESTINATION" 13 | RUN_CLANG_STATIC_ANALYZER=NO 14 | | xcpretty 15 | matrix: 16 | include: 17 | 18 | - xcode_scheme: "OXCMantle" 19 | osx_image: xcode8 20 | env: 21 | - XCODE_ACTION=test 22 | - XCODE_SDK=iphonesimulator 23 | - XCODE_DESTINATION="name=iPhone 7" 24 | notifications: 25 | email: 26 | - 308325102@qq.com 27 | 28 | 29 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDoubleTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXDoubleTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXDoubleTypeValidator.h" 11 | 12 | 13 | @implementation OXDoubleTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = NO; 21 | if ([value respondsToSelector:@selector(doubleValue)]){ 22 | return @([value doubleValue]); 23 | } 24 | return @0.0; 25 | }; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXIntegerTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXIntegerTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXIntegerTypeValidator.h" 11 | 12 | 13 | @implementation OXIntegerTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = YES; 21 | if ([value respondsToSelector:@selector(integerValue)]){ 22 | return @([value integerValue]); 23 | } 24 | return @0; 25 | }; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | @end -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSError+MTLModelException.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSError+MTLModelException.h 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 7/6/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSError (MTLModelException) 12 | 13 | /// Creates a new error for an exception that occurred during updating an 14 | /// MTLModel. 15 | /// 16 | /// exception - The exception that was thrown while updating the model. 17 | /// This argument must not be nil. 18 | /// 19 | /// Returns an error that takes its localized description and failure reason 20 | /// from the exception. 21 | + (instancetype)mtl_modelErrorWithException:(NSException *)exception; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXUnsignedLongTypeValicdator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXUnsignLognTypeValicdator.m 3 | // Oxen 4 | // 5 | // Created by Matthew on 12/18/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "OXUnsignedLongTypeValicdator.h" 10 | 11 | @implementation OXUnsignedLongTypeValicdator 12 | 13 | - (id)init { 14 | self = [super init]; 15 | 16 | if (self) { 17 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 18 | *isValid = YES; 19 | if ([value respondsToSelector:@selector(longValue)]){ 20 | return @([value unsignedLongValue]); 21 | } 22 | return @0; 23 | }; 24 | } 25 | 26 | return self; 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXArrayTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXArrayTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXArrayTypeValidator.h" 11 | 12 | 13 | @implementation OXArrayTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSArray * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = NO; 21 | return nil; 22 | }; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 29 | _isValid = [*value isKindOfClass:[NSArray class]]; 30 | return [super validateValue:value error:error]; 31 | } 32 | 33 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCModel/NSValueTransformer+MantleExtention.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSValueTransformer+MantleExtention.h 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/23/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import 10 | #import "OXValidatorReflection.h" 11 | 12 | //扩展加入了 系统自己的类 13 | @interface NSValueTransformer (MantleExtention) 14 | + (NSValueTransformer *)oxc_mtl_JSONArrayTransformerWithBasicClass:(Class)basicClass; 15 | + (NSValueTransformer *)oxc_mtl_basicClassyTransformerWithBasicType:(OXPropertyType)propertyType; 16 | @end 17 | 18 | @interface NSValueTransformer (OXCDiscarded) 19 | + (NSValueTransformer *)mtl_JSONArrayTransformerWithBasicClass:(Class)basicClass __attribute__((unavailable("oxc_mtl_JSONArrayTransformerWithBasicClass:")));; 20 | @end -------------------------------------------------------------------------------- /OXCMantle/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDictionaryTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXDictionaryTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXDictionaryTypeValidator.h" 11 | 12 | 13 | @implementation OXDictionaryTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSDictionary * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = NO; 21 | return nil; 22 | }; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 29 | _isValid = [*value isKindOfClass:[NSDictionary class]]; 30 | return [super validateValue:value error:error]; 31 | } 32 | 33 | @end -------------------------------------------------------------------------------- /OXCMantle/ModelExample/ProtocolExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProtocolExample.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/6/14. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol ProtocolExample 12 | 13 | @property (copy ,nonatomic) NSString *ID; 14 | @property (strong ,nonatomic) NSArray *names; 15 | @property (strong ,nonatomic) NSArray *examples; 16 | @property (strong ,nonatomic) NSDate *date; 17 | @property (strong ,nonatomic) NSURL *url; 18 | 19 | @property (nonatomic ,copy ,readonly)NSString *test1; 20 | @property (nonatomic ,copy ,readonly)NSString *test2; 21 | @property (nonatomic ,copy ,readonly)NSString *test3; 22 | @property (nonatomic ,copy ,readonly)NSString *test4; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCModel/OXModel.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // OXModel.m 4 | // Oxen 5 | // 6 | // Created by Matthew on 6/16/14. 7 | // Released under the MIT license 8 | // 9 | 10 | #import "OXModel.h" 11 | #import "OXValidatorReflection.h" 12 | #import "NSValueTransformer+MantleExtention.h" 13 | #import "NSDictionary+MTLMappingAdditions.h" 14 | @implementation OXModel 15 | #pragma mark - MTLJSONSerializing 16 | + (NSDictionary *)JSONKeyPathsByPropertyKey{ 17 | return [NSDictionary mtl_identityPropertyMapWithModel:self]; 18 | } 19 | 20 | + (NSValueTransformer*)JSONTransformerForKey:(NSString*)key{ 21 | OXPropertyType propertyType = [OXValidatorReflection oxc_propertypeWithName:key clazz:self.class]; 22 | return [NSValueTransformer oxc_mtl_basicClassyTransformerWithBasicType:propertyType]; 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXNumberTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXNumberTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXNumberTypeValidator.h" 11 | 12 | 13 | @implementation OXNumberTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = YES; 21 | return [NSDecimalNumber decimalNumberWithString:value]; 22 | }; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 29 | _isValid = [*value isKindOfClass:[NSNumber class]]; 30 | return [super validateValue:value error:error]; 31 | } 32 | 33 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXLongTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXLongTypeValidator.m 3 | // Oxen 4 | // 5 | // Created by Matthew on 7/2/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "OXLongTypeValidator.h" 10 | 11 | @implementation OXLongTypeValidator 12 | 13 | - (id)init { 14 | self = [super init]; 15 | 16 | if (self) { 17 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 18 | *isValid = YES; 19 | if ([value respondsToSelector:@selector(longValue)]){ 20 | return @([value longValue]); 21 | }else if([value respondsToSelector:@selector(longLongValue)]){ 22 | return @([value longLongValue]); 23 | } 24 | return @0; 25 | }; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBaseValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXBaseValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import 11 | 12 | typedef id (^OXDefaultValidation) (id value, BOOL *isValid, NSError **error); 13 | typedef id (^OXPostValidation) (id value); 14 | 15 | @interface OXBaseValidator : NSObject { 16 | @protected 17 | BOOL _isValid; 18 | } 19 | 20 | @property (nonatomic, assign, readonly) BOOL isValid; 21 | @property (nonatomic, strong) OXDefaultValidation defaultValidation; 22 | @property (nonatomic, strong) OXPostValidation postValidation; 23 | 24 | - (BOOL)validateValue:(id *)value error:(NSError **)error; 25 | 26 | - (id)initWithDefaultValidation:(OXDefaultValidation)defaultValidation; 27 | 28 | - (id)initWithPostValidation:(OXPostValidation)postValidation; 29 | 30 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXFloatTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXFloatTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXFloatTypeValidator.h" 11 | #import "NSString+ValidationUtils.h" 12 | 13 | 14 | @implementation OXFloatTypeValidator 15 | 16 | - (id)init { 17 | self = [super init]; 18 | if (self) { 19 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = YES; 21 | if ([value isKindOfClass:[NSString class]]){ 22 | 23 | 24 | value = [NSString stripNonNumericCharacters:value]; 25 | } 26 | if ([value respondsToSelector:@selector(floatValue)]){ 27 | return @([value floatValue]); 28 | } 29 | return @0.0f; 30 | }; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | @end -------------------------------------------------------------------------------- /OXCMantle/ModelExample/ModelExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // ModelExample.h 3 | // OXCen 4 | // 5 | // Created by 张旭东 on 15/7/25. 6 | // Copyright (c) 2015年 zhangxudong. All rights reserved. 7 | // 8 | 9 | #import "OXModel.h" 10 | #import "ProtocolExample.h" 11 | typedef NS_ENUM(NSInteger ,ModelExampleType) { 12 | ModelExampleTypeUnknow, 13 | ModelExampleTypeDisable, 14 | ModelExampleTypeEnable 15 | }; 16 | 17 | @interface ModelExample : OXModel 18 | 19 | 20 | @property (copy ,nonatomic) NSString *ID; 21 | @property (assign ,nonatomic) BOOL isNew; 22 | @property (assign ,nonatomic) NSInteger age; 23 | @property (strong ,nonatomic) NSArray *names; 24 | @property (strong ,nonatomic) NSArray *examples; 25 | @property (strong ,nonatomic) NSDate *date; 26 | @property (strong ,nonatomic) NSURL *url; 27 | @property (assign ,nonatomic) ModelExampleType exampleType; 28 | 29 | @property (assign ,nonatomic) ModelExample *example; 30 | @end 31 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/Mantle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Mantle.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-04. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Mantle. 12 | FOUNDATION_EXPORT double MantleVersionNumber; 13 | 14 | //! Project version string for Mantle. 15 | FOUNDATION_EXPORT const unsigned char MantleVersionString[]; 16 | 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+MTLManipulationAdditions.h 3 | // Mantle 4 | // 5 | // Created by Josh Abernathy on 9/19/12. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSArray (MTLManipulationAdditions) 12 | 13 | /// The first object in the array or nil if the array is empty. 14 | /// Forwards to `firstObject` which has been first declared in iOS7, but works with iOS4/10.6. 15 | @property (nonatomic, readonly, strong) id mtl_firstObject; 16 | 17 | /// Returns a new array without all instances of the given object. 18 | - (NSArray *)mtl_arrayByRemovingObject:(id)object; 19 | 20 | /// Returns a new array without the first object. If the array is empty, it 21 | /// returns the empty array. 22 | - (NSArray *)mtl_arrayByRemovingFirstObject; 23 | 24 | /// Returns a new array without the last object. If the array is empty, it 25 | /// returns the empty array. 26 | - (NSArray *)mtl_arrayByRemovingLastObject; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBaseValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXBaseValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXBaseValidator.h" 11 | 12 | 13 | @implementation OXBaseValidator 14 | 15 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 16 | if (!self.isValid){ 17 | if (self.defaultValidation) { 18 | *value = self.defaultValidation(*value, &_isValid, error); 19 | } 20 | } 21 | if (self.isValid && self.postValidation){ 22 | *value = self.postValidation(*value); 23 | } 24 | 25 | return self.isValid; 26 | } 27 | 28 | - (id)initWithDefaultValidation:(OXDefaultValidation)defaultValidation { 29 | self = [self init]; 30 | 31 | if (self){ 32 | _defaultValidation = defaultValidation; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | - (id)initWithPostValidation:(OXPostValidation)postValidation { 39 | self = [self init]; 40 | 41 | if (self){ 42 | _postValidation = postValidation; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | @end -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+MTLManipulationAdditions.m 3 | // Mantle 4 | // 5 | // Created by Josh Abernathy on 9/19/12. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import "NSArray+MTLManipulationAdditions.h" 10 | 11 | @interface NSArray (MTLDeclarations) 12 | 13 | // This declaration is needed so Mantle can be compiled with SDK 6 / 10.8. 14 | - (id)firstObject; 15 | 16 | @end 17 | 18 | @implementation NSArray (MTLManipulationAdditions) 19 | 20 | - (id)mtl_firstObject { 21 | return self.firstObject; 22 | } 23 | 24 | - (instancetype)mtl_arrayByRemovingObject:(id)object { 25 | NSMutableArray *result = [self mutableCopy]; 26 | [result removeObject:object]; 27 | return result; 28 | } 29 | 30 | - (instancetype)mtl_arrayByRemovingFirstObject { 31 | if (self.count == 0) return self; 32 | 33 | return [self subarrayWithRange:NSMakeRange(1, self.count - 1)]; 34 | } 35 | 36 | - (instancetype)mtl_arrayByRemovingLastObject { 37 | if (self.count == 0) return self; 38 | 39 | return [self subarrayWithRange:NSMakeRange(0, self.count - 1)]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXValidatorReflection.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXValidatorReflection.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/6/11. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "OXBaseValidator.h" 11 | typedef NS_ENUM(NSUInteger, OXPropertyType){ 12 | OXPropertyUnknown = 0, 13 | OXPropertyTypeString, 14 | OXPropertyTypeBool, 15 | OXPropertyTypeNumber, 16 | OXPropertyTypeInteger, 17 | OXPropertyTypeFloat, 18 | OXPropertyTypeArray, 19 | OXPropertyTypeMutableArray, 20 | OXPropertyTypeDictionary, 21 | OXPropertyTypeMutableDictionary, 22 | OXPropertyTypeUnsignedInteger, 23 | OXPropertyTypeDate, 24 | OXPropertyTypeDouble, 25 | OXPropertyTypeLong, 26 | OXPropertyTypeUnsignedLong, 27 | }; 28 | 29 | 30 | @interface OXValidatorReflection : NSObject 31 | + (OXPropertyType)oxc_propertypeWithName:(NSString *)propertyName clazz:(Class)clazz; 32 | + (OXBaseValidator *)oxc_validatorForPropertyType:(OXPropertyType)propertyType; 33 | + (OXPropertyType)oxc_propertyTypeForBasicClassStr:(NSString *)clazzStr; 34 | @end 35 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLJSONKeyPath.h 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 19/03/14. 6 | // Copyright (c) 2014 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (MTLJSONKeyPath) 12 | 13 | /// Looks up the value of a key path in the receiver. 14 | /// 15 | /// JSONKeyPath - The key path that should be resolved. Every element along this 16 | /// key path needs to be an instance of NSDictionary for the 17 | /// resolving to be successful. 18 | /// success - If not NULL, this will be set to a boolean indicating whether 19 | /// the key path was resolved successfully. 20 | /// error - If not NULL, this may be set to an error that occurs during 21 | /// resolving the value. 22 | /// 23 | /// Returns the value for the key path which may be nil. Clients should inspect 24 | /// the success parameter to decide how to proceed with the result. 25 | - (id)mtl_valueForJSONKeyPath:(NSString *)JSONKeyPath success:(BOOL *)success error:(NSError **)error; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 张旭东 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBaseModelValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXBaseModelValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXBaseModelValidator.h" 11 | @implementation OXBaseModelValidator 12 | 13 | - (id)initWithClass:(Class)baseModelClass { 14 | self = [super init]; 15 | 16 | if (self){ 17 | __weak Class blockModelClass = baseModelClass; 18 | self.postValidation = ^id (id value){ 19 | return [[blockModelClass alloc] initWithDictionary:value]; 20 | }; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | - (id)initWithDefaultValidation:(OXDefaultValidation)defaultValidation { 27 | self = [self init]; 28 | 29 | if (self) { 30 | self.defaultValidation = defaultValidation; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | - (id)init { 37 | return [self initWithClass:[NSObject class]]; 38 | } 39 | 40 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 41 | _isValid = [*value isKindOfClass:[NSDictionary class]]; 42 | return [super validateValue:value error:error]; 43 | } 44 | 45 | @end -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXStringTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXStringTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXStringTypeValidator.h" 11 | 12 | 13 | @implementation OXStringTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSString *(id value, BOOL *isValid, NSError **error){ 20 | 21 | *isValid = YES; 22 | if (!value) { 23 | return nil; 24 | } 25 | if ([value isKindOfClass:[NSString class]]) { 26 | return (NSString *)value; 27 | } 28 | if ([value respondsToSelector:@selector(stringValue)]){ 29 | return [value stringValue]; 30 | } 31 | *isValid = NO; 32 | return nil; 33 | }; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 40 | _isValid = [*value isKindOfClass:[NSString class]]; 41 | return [super validateValue:value error:error]; 42 | } 43 | 44 | @end -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSError+MTLModelException.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSError+MTLModelException.m 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 7/6/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLModel.h" 10 | 11 | #import "NSError+MTLModelException.h" 12 | 13 | // The domain for errors originating from MTLModel. 14 | static NSString * const MTLModelErrorDomain = @"MTLModelErrorDomain"; 15 | 16 | // An exception was thrown and caught. 17 | static const NSInteger MTLModelErrorExceptionThrown = 1; 18 | 19 | // Associated with the NSException that was caught. 20 | static NSString * const MTLModelThrownExceptionErrorKey = @"MTLModelThrownException"; 21 | 22 | @implementation NSError (MTLModelException) 23 | 24 | + (instancetype)mtl_modelErrorWithException:(NSException *)exception { 25 | NSParameterAssert(exception != nil); 26 | 27 | NSDictionary *userInfo = @{ 28 | NSLocalizedDescriptionKey: exception.description, 29 | NSLocalizedFailureReasonErrorKey: exception.reason, 30 | MTLModelThrownExceptionErrorKey: exception 31 | }; 32 | 33 | return [NSError errorWithDomain:MTLModelErrorDomain code:MTLModelErrorExceptionThrown userInfo:userInfo]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLManipulationAdditions.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-24. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+MTLManipulationAdditions.h" 10 | 11 | @implementation NSDictionary (MTLManipulationAdditions) 12 | 13 | - (NSDictionary *)mtl_dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary { 14 | NSMutableDictionary *result = [self mutableCopy]; 15 | [result addEntriesFromDictionary:dictionary]; 16 | return result; 17 | } 18 | 19 | - (NSDictionary *)mtl_dictionaryByRemovingValuesForKeys:(NSArray *)keys { 20 | NSMutableDictionary *result = [self mutableCopy]; 21 | [result removeObjectsForKeys:keys]; 22 | return result; 23 | } 24 | 25 | @end 26 | 27 | @implementation NSDictionary (MTLManipulationAdditions_Deprecated) 28 | 29 | #pragma clang diagnostic push 30 | #pragma clang diagnostic ignored "-Wdeprecated" 31 | 32 | - (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys { 33 | return [self mtl_dictionaryByRemovingValuesForKeys:keys.allObjects]; 34 | } 35 | 36 | #pragma clang diagnostic pop 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLManipulationAdditions.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-24. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (MTLManipulationAdditions) 12 | 13 | /// Merges the keys and values from the given dictionary into the receiver. If 14 | /// both the receiver and `dictionary` have a given key, the value from 15 | /// `dictionary` is used. 16 | /// 17 | /// Returns a new dictionary containing the entries of the receiver combined with 18 | /// those of `dictionary`. 19 | - (NSDictionary *)mtl_dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary; 20 | 21 | /// Creates a new dictionary with all the entries for the given keys removed from 22 | /// the receiver. 23 | - (NSDictionary *)mtl_dictionaryByRemovingValuesForKeys:(NSArray *)keys; 24 | 25 | @end 26 | 27 | @interface NSDictionary (MTLManipulationAdditions_Deprecated) 28 | 29 | - (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys __attribute__((deprecated("Replaced by -mtl_dictionaryByRemovingValuesForKeys:"))); 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXUnsignedIntegerTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXUnsignedIntegerTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/17/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXUnsignedIntegerTypeValidator.h" 11 | 12 | 13 | @implementation OXUnsignedIntegerTypeValidator 14 | 15 | - (id)init { 16 | self = [super init]; 17 | 18 | if (self) { 19 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 20 | *isValid = YES; 21 | if ([value respondsToSelector:@selector(integerValue)]){ 22 | NSInteger intValue = [value integerValue]; 23 | if (intValue >= 0){ 24 | return @(intValue); 25 | } 26 | } 27 | return @0U; 28 | }; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 35 | BOOL isValid = NO; 36 | 37 | if ([*value isKindOfClass:[NSNumber class]]){ 38 | if ([*value integerValue] >= 0){ 39 | isValid = YES; 40 | } 41 | } 42 | 43 | _isValid = isValid; 44 | 45 | return [super validateValue:value error:error]; 46 | } 47 | 48 | @end -------------------------------------------------------------------------------- /OXCMantle.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "OXCMantle" 3 | s.version = "1.1.2" 4 | s.summary = "在Mantle的基础上夹生了类型验证,修复了一些bug" 5 | s.description = <<-DESC 6 | 在Mantle的基础上夹生了类型验证,修复了一些bug 7 | 修复了64位NSInteger不能正常转换的问题 8 | DESC 9 | s.homepage = "https://github.com/hytzxd/OXCMantle" 10 | s.license = { :type => "MIT", :file => "LICENSE" } 11 | s.author = { "Alien" => "308325102@qq.com" } 12 | s.platform = :ios ,"7.0" 13 | s.source = { :git => "https://github.com/hytzxd/OXCMantle.git", :branch => "master", :tag => '1.1.2' } 14 | s.requires_arc = true 15 | s.source_files = 'OXCMantle/Classes/*.{h}' 16 | s.dependency 'Mantle', '~> 2.0.7' 17 | s.frameworks = 'Foundation' 18 | s.subspec 'OXCValidation' do |ss| 19 | ss.source_files = 'OXCMantle/Classes/OXCValidation/**/*.{h,m}' 20 | ss.public_header_files = 'OXCMantle/Classes/OXCValidation/**/*.{h}' 21 | end 22 | s.subspec 'OXCModel' do |ss| 23 | ss.source_files = 'OXCMantle/Classes/OXCModel/*.{h,m}' 24 | ss.public_header_files = 'OXCMantle/Classes/OXCModel/**/*.{h}' 25 | ss.dependency 'Mantle', '~> 2.0.7' 26 | ss.dependency 'OXCMantle/OXCValidation' 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /OXCMantle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLReflection.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTLReflection.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-03-12. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /// Creates a selector from a key and a constant string. 12 | /// 13 | /// key - The key to insert into the generated selector. This key should be in 14 | /// its natural case. 15 | /// suffix - A string to append to the key as part of the selector. 16 | /// 17 | /// Returns a selector, or NULL if the input strings cannot form a valid 18 | /// selector. 19 | SEL MTLSelectorWithKeyPattern(NSString *key, const char *suffix) __attribute__((pure, nonnull(1, 2))); 20 | 21 | /// Creates a selector from a key and a constant prefix and suffix. 22 | /// 23 | /// prefix - A string to prepend to the key as part of the selector. 24 | /// key - The key to insert into the generated selector. This key should be in 25 | /// its natural case, and will have its first letter capitalized when 26 | /// inserted. 27 | /// suffix - A string to append to the key as part of the selector. 28 | /// 29 | /// Returns a selector, or NULL if the input strings cannot form a valid 30 | /// selector. 31 | SEL MTLSelectorWithCapitalizedKeyPattern(const char *prefix, NSString *key, const char *suffix) __attribute__((pure, nonnull(1, 2, 3))); 32 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDValidationFunctions.h: -------------------------------------------------------------------------------- 1 | // 2 | // OXDValidationFunctions.h 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/7/28. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #ifndef OXDValidationFunctions_h 10 | #define OXDValidationFunctions_h 11 | #import 12 | 13 | BOOL oxd_validateStringProperty(id *ioValue, NSError *__autoreleasing* outError); 14 | 15 | BOOL oxd_validateBoolProperty(id *ioValue, NSError *__autoreleasing* outError); 16 | 17 | BOOL oxd_validateNumberProperty(id *ioValue, NSError *__autoreleasing* outError); 18 | 19 | BOOL oxd_validateIntegerProperty(id *ioValue, NSError *__autoreleasing* outError); 20 | 21 | BOOL oxd_validateUnsignedLongProperty(id *ioValue, NSError *__autoreleasing* outError); 22 | 23 | BOOL oxd_validateLongProperty(id *ioValue, NSError *__autoreleasing* outError); 24 | 25 | BOOL oxd_validateFloatProperty(id *ioValue, NSError *__autoreleasing* outError); 26 | 27 | BOOL oxd_validateArrayProperty(id *ioValue, NSError *__autoreleasing* outError); 28 | 29 | BOOL oxd_validateDictionaryProperty(id *ioValue, NSError *__autoreleasing* outError); 30 | 31 | BOOL oxd_validateUnsignedIntegerProperty(id *ioValue, NSError *__autoreleasing* outError); 32 | 33 | BOOL oxd_validateDoubleProperty(id *ioValue, NSError *__autoreleasing* outError); 34 | 35 | BOOL oxd_validateDateProperty(id *ioValue, NSError *__autoreleasing* outError); 36 | 37 | 38 | #endif /* OXDValidationFunctions_h */ 39 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/NSString+ValidationUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+NSString_ValidationUtils.m 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import "NSString+ValidationUtils.h" 10 | 11 | @implementation NSString (ValidationUtils) 12 | + (NSString *)capitalizeFirstCharacter:(NSString *)string { 13 | NSString *firstCharacter = [[string substringToIndex:1] capitalizedString]; 14 | NSString *cappedString = [string stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstCharacter]; 15 | return cappedString; 16 | } 17 | 18 | + (NSString *)stripNonNumericCharacters:(NSString *)string { 19 | NSMutableString *res = [[NSMutableString alloc] init]; 20 | 21 | for(uint i = 0; i < [string length]; i++) { 22 | char next = (char) [string characterAtIndex:(NSUInteger) i]; 23 | 24 | if((next >= '0' && next <= '9') || next == '.') { 25 | [res appendFormat:@"%c", next]; 26 | } 27 | } 28 | 29 | return res; 30 | 31 | } 32 | 33 | + (NSString *)leftPadString:(NSString *)string length:(NSUInteger)length padCharacter:(NSString *)padCharacter { 34 | NSUInteger padding = length - [string length]; 35 | if (padding > 0){ 36 | NSString *pad = [[NSString string] stringByPaddingToLength:padding withString:padCharacter startingAtIndex:0]; 37 | return [pad stringByAppendingString:string]; 38 | } 39 | return string; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSValueTransformer+MTLInversionAdditions.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-05-18. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "NSValueTransformer+MTLInversionAdditions.h" 10 | #import "MTLTransformerErrorHandling.h" 11 | #import "MTLValueTransformer.h" 12 | 13 | @implementation NSValueTransformer (MTLInversionAdditions) 14 | 15 | - (NSValueTransformer *)mtl_invertedTransformer { 16 | NSParameterAssert(self.class.allowsReverseTransformation); 17 | 18 | if ([self conformsToProtocol:@protocol(MTLTransformerErrorHandling)]) { 19 | NSParameterAssert([self respondsToSelector:@selector(reverseTransformedValue:success:error:)]); 20 | 21 | id errorHandlingSelf = (id)self; 22 | 23 | return [MTLValueTransformer transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { 24 | return [errorHandlingSelf reverseTransformedValue:value success:success error:error]; 25 | } reverseBlock:^(id value, BOOL *success, NSError **error) { 26 | return [errorHandlingSelf transformedValue:value success:success error:error]; 27 | }]; 28 | } else { 29 | return [MTLValueTransformer transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { 30 | return [self reverseTransformedValue:value]; 31 | } reverseBlock:^(id value, BOOL *success, NSError **error) { 32 | return [self transformedValue:value]; 33 | }]; 34 | } 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /OXCMantle/ModelExample/ModelExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // ModelExample.m 3 | // OXCen 4 | // 5 | // Created by 张旭东 on 15/7/25. 6 | // Copyright (c) 2015年 zhangxudong. All rights reserved. 7 | // 8 | 9 | #import "ModelExample.h" 10 | @implementation ModelExample 11 | + (NSDictionary *)JSONKeyPathsByPropertyKey{ 12 | NSMutableDictionary* keys = [NSMutableDictionary dictionaryWithDictionary:[NSDictionary mtl_identityPropertyMapWithModel:self]]; 13 | keys[@"ID"] = @"id"; 14 | return keys; 15 | } 16 | + (NSValueTransformer *)namesJSONTransformer{ 17 | return [NSValueTransformer oxc_mtl_JSONArrayTransformerWithBasicClass:[NSString class]]; 18 | } 19 | + (NSValueTransformer *)examplesJSONTransformer{ 20 | return [MTLJSONAdapter arrayTransformerWithModelClass:[ModelExample class]]; 21 | } 22 | + (NSValueTransformer *)exampleTypeJSONTransformer { 23 | return [NSValueTransformer 24 | mtl_valueMappingTransformerWithDictionary: 25 | @{@(ModelExampleTypeEnable):@(ModelExampleTypeEnable), 26 | @(ModelExampleTypeDisable):@(ModelExampleTypeDisable)} 27 | defaultValue:@(ModelExampleTypeUnknow) 28 | reverseDefaultValue: @(ModelExampleTypeUnknow)]; 29 | 30 | 31 | } 32 | 33 | - (NSString *)test1{ 34 | return @"1"; 35 | } 36 | - (NSString *)test2{ 37 | return @"1"; 38 | } 39 | - (NSString *)test3{ 40 | return @"1"; 41 | } 42 | - (NSString *)test4{ 43 | return @"1"; 44 | } 45 | @end 46 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MTLJSONKeyPath.m 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 19/03/14. 6 | // Copyright (c) 2014 GitHub. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+MTLJSONKeyPath.h" 10 | 11 | #import "MTLJSONAdapter.h" 12 | 13 | @implementation NSDictionary (MTLJSONKeyPath) 14 | 15 | - (id)mtl_valueForJSONKeyPath:(NSString *)JSONKeyPath success:(BOOL *)success error:(NSError **)error { 16 | NSArray *components = [JSONKeyPath componentsSeparatedByString:@"."]; 17 | 18 | id result = self; 19 | for (NSString *component in components) { 20 | // Check the result before resolving the key path component to not 21 | // affect the last value of the path. 22 | if (result == nil || result == NSNull.null) break; 23 | 24 | if (![result isKindOfClass:NSDictionary.class]) { 25 | if (error != NULL) { 26 | NSDictionary *userInfo = @{ 27 | NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid JSON dictionary", @""), 28 | NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"JSON key path %1$@ could not resolved because an incompatible JSON dictionary was supplied: \"%2$@\"", @""), JSONKeyPath, self] 29 | }; 30 | 31 | *error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorInvalidJSONDictionary userInfo:userInfo]; 32 | } 33 | 34 | if (success != NULL) *success = NO; 35 | 36 | return nil; 37 | } 38 | 39 | result = result[component]; 40 | } 41 | 42 | if (success != NULL) *success = YES; 43 | 44 | return result; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /OXCMantle/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /OXCMantle/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "ModelExample.h" 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | NSDictionary *dict = @{@"description":@"", 21 | @"id":@"999", 22 | @"date":[NSNull null], 23 | @"age":@99, 24 | @"names":@[@1,@0,@"xd"], 25 | @"url":@"https://www.google.com", 26 | @"exampleType":@(1), 27 | @"isNew":@0, 28 | @"example":@{@"id":@"999", 29 | @"date":[NSNull null], 30 | @"age":[NSNull null], 31 | @"names":@[@"xd",@"xd",@"xd"], 32 | @"url":@"https://www.google.com", 33 | @"exampleType":@(1), 34 | @"isNew":@"YES", 35 | @"example":@{}}}; 36 | 37 | 38 | 39 | NSError *error = nil; 40 | ModelExample *example = [MTLJSONAdapter modelOfClass:[ModelExample class] fromJSONDictionary:dict error:&error]; 41 | NSLog(@"%@ %@",example,error); 42 | } 43 | 44 | - (void)didReceiveMemoryWarning { 45 | [super didReceiveMemoryWarning]; 46 | // Dispose of any resources that can be recreated. 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /OXCMantle/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /OXCMantleTests/OXCMantleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXCMantleTests.m 3 | // OXCMantleTests 4 | // 5 | // Created by 张旭东 on 15/8/6. 6 | // Copyright (c) 2015年 张旭东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | //#import "ModelExample.h" 12 | //#import "MTLJSONAdapter.h" 13 | @interface OXCMantleTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OXCMantleTests 18 | 19 | - (void)setUp { 20 | [super setUp]; 21 | // Put setup code here. This method is called before the invocation of each test method in the class. 22 | } 23 | 24 | - (void)tearDown { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample { 30 | // This is an example of a functional test case. 31 | XCTAssert(YES, @"Pass"); 32 | } 33 | 34 | 35 | //- (void)testModel{ 36 | // NSDictionary *dict = @{@"id":@"999", 37 | // @"date":@(460457629.178584), 38 | // @"names":@[@"xd",@"xd",@"xd"], 39 | // @"examples":@[ 40 | // @{@"id":@"999", 41 | // @"date":@(460457629.178584), 42 | // @"names":@[@"xd",@"xd",@"xd"]}, 43 | // @{@"id":@"999", 44 | // @"date":@(460457629.178584), 45 | // @"names":@[@"xd",@"xd",@"xd"]}, 46 | // @{@"id":@"999", 47 | // @"date":@(460457629.178584), 48 | // @"names":@[@"xd",@"xd",@"xd"]}, 49 | // 50 | // ]}; 51 | // NSError *error = nil; 52 | //// ModelExample *example = [MTLJSONAdapter modelOfClass:[ModelExample class] fromJSONDictionary:dict error:&error]; 53 | //// NSLog(@"%@",example); 54 | //} 55 | - (void)testPerformanceExample { 56 | // This is an example of a performance test case. 57 | [self measureBlock:^{ 58 | // Put the code you want to measure the time of here. 59 | }]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLReflection.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTLReflection.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-03-12. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLReflection.h" 10 | #import 11 | 12 | SEL MTLSelectorWithKeyPattern(NSString *key, const char *suffix) { 13 | NSUInteger keyLength = [key maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 14 | NSUInteger suffixLength = strlen(suffix); 15 | 16 | char selector[keyLength + suffixLength + 1]; 17 | 18 | BOOL success = [key getBytes:selector maxLength:keyLength usedLength:&keyLength encoding:NSUTF8StringEncoding options:0 range:NSMakeRange(0, key.length) remainingRange:NULL]; 19 | if (!success) return NULL; 20 | 21 | memcpy(selector + keyLength, suffix, suffixLength); 22 | selector[keyLength + suffixLength] = '\0'; 23 | 24 | return sel_registerName(selector); 25 | } 26 | 27 | SEL MTLSelectorWithCapitalizedKeyPattern(const char *prefix, NSString *key, const char *suffix) { 28 | NSUInteger prefixLength = strlen(prefix); 29 | NSUInteger suffixLength = strlen(suffix); 30 | 31 | NSString *initial = [key substringToIndex:1].uppercaseString; 32 | NSUInteger initialLength = [initial maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 33 | 34 | NSString *rest = [key substringFromIndex:1]; 35 | NSUInteger restLength = [rest maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 36 | 37 | char selector[prefixLength + initialLength + restLength + suffixLength + 1]; 38 | memcpy(selector, prefix, prefixLength); 39 | 40 | BOOL success = [initial getBytes:selector + prefixLength maxLength:initialLength usedLength:&initialLength encoding:NSUTF8StringEncoding options:0 range:NSMakeRange(0, initial.length) remainingRange:NULL]; 41 | if (!success) return NULL; 42 | 43 | success = [rest getBytes:selector + prefixLength + initialLength maxLength:restLength usedLength:&restLength encoding:NSUTF8StringEncoding options:0 range:NSMakeRange(0, rest.length) remainingRange:NULL]; 44 | if (!success) return NULL; 45 | 46 | memcpy(selector + prefixLength + initialLength + restLength, suffix, suffixLength); 47 | selector[prefixLength + initialLength + restLength + suffixLength] = '\0'; 48 | 49 | return sel_registerName(selector); 50 | } 51 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLValueTransformer.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTLValueTransformer.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-11. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MTLTransformerErrorHandling.h" 12 | 13 | /// A block that represents a transformation. 14 | /// 15 | /// value - The value to transform. 16 | /// success - The block must set this parameter to indicate whether the 17 | /// transformation was successful. 18 | /// MTLValueTransformer will always call this block with *success 19 | /// initialized to YES. 20 | /// error - If not NULL, this may be set to an error that occurs during 21 | /// transforming the value. 22 | /// 23 | /// Returns the result of the transformation, which may be nil. 24 | typedef id (^MTLValueTransformerBlock)(id value, BOOL *success, NSError **error); 25 | 26 | /// 27 | /// A value transformer supporting block-based transformation. 28 | /// 29 | @interface MTLValueTransformer : NSValueTransformer 30 | 31 | /// Returns a transformer which transforms values using the given block. Reverse 32 | /// transformations will not be allowed. 33 | + (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)transformation; 34 | 35 | /// Returns a transformer which transforms values using the given block, for 36 | /// forward or reverse transformations. 37 | + (instancetype)transformerUsingReversibleBlock:(MTLValueTransformerBlock)transformation; 38 | 39 | /// Returns a transformer which transforms values using the given blocks. 40 | + (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardTransformation reverseBlock:(MTLValueTransformerBlock)reverseTransformation; 41 | 42 | @end 43 | 44 | @interface MTLValueTransformer (Deprecated) 45 | 46 | + (NSValueTransformer *)transformerWithBlock:(id (^)(id))transformationBlock __attribute__((deprecated("Replaced by +transformerUsingForwardBlock:"))); 47 | 48 | + (NSValueTransformer *)reversibleTransformerWithBlock:(id (^)(id))transformationBlock __attribute__((deprecated("Replaced by +transformerUsingReversibleBlock:"))); 49 | 50 | + (NSValueTransformer *)reversibleTransformerWithForwardBlock:(id (^)(id))forwardBlock reverseBlock:(id (^)(id))reverseBlock __attribute__((deprecated("Replaced by +transformerUsingForwardBlock:reverseBlock:"))); 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/hytzxd/OXCMantle.svg?branch=master)](https://travis-ci.org/hytzxd/OXCMantle) 2 | # OXCMantle 3 | 在mantle上加入了类型验证的功能。(json转model) 4 | 该项目已纳入Cocoapods管理,目前是1.0.1版本 5 | 6 | 你可以使用如下的方式来将本项目加入自己的工程 7 | 8 | pod 'OXCMantle', '~> 1.0.0' 9 | 使用方法 直接用代码说吧 10 | 11 | 12 | ``` 13 | 14 | #import "OXModel.h" 15 | 16 | @interface ModelExample : OXModel 17 | @property (copy ,nonatomic)NSString *ID; 18 | @property (assign ,nonatomic)NSInteger age; 19 | @property (strong ,nonatomic)NSArray *names; 20 | @property (strong ,nonatomic)NSArray *examples; 21 | @property (strong ,nonatomic)NSDate *date; 22 | @end 23 | 24 | 25 | #import "ModelExample.h" 26 | 27 | @implementation ModelExample 28 | + (NSDictionary *)JSONKeyPathsByPropertyKey{ 29 | NSMutableDictionary* keys = [NSMutableDictionary dictionaryWithDictionary:[super JSONKeyPathsByPropertyKey]]; 30 | keys[@"ID"] = @"id"; 31 | return keys; 32 | } 33 | 34 | + (NSValueTransformer *)namesJSONTransformer{ 35 | return [NSValueTransformer mtl_JSONArrayTransformerWithBasicClass:[NSString class]]; 36 | } 37 | + (NSValueTransformer *)replysJSONTransformer{ 38 | return [MTLJSONAdapter arrayTransformerWithModelClass:[ModelExample class]]; 39 | } 40 | @end 41 | 42 | 43 | 44 | 45 | 46 | 下面来说一下怎样解析,还是代码 47 | 48 | NSDictionary *dict = @{@"id":@(999), 49 | @"date":@(460457629.178584), 50 | @"age":@"421431", 51 | @"names":@[@"xd",@"xd",@"xd"], 52 | @"examples":@[ 53 | @{@"id":@"9999", 54 | @"date":@(460457629.178584), 55 | @"names":@[@"xd1",@"xd2",@"xd3"]}, 56 | @{@"id":@"99900", 57 | @"date":@(460457629.178584), 58 | @"names":@[@"xd",@"xd",@"xd"]}, 59 | @{@"id":@"999999", 60 | @"date":@(460457629.178584), 61 | @"names":@[@"xd",@"xd",@"xd"]}, 62 | 63 | ]}; 64 | NSError *error = nil; 65 | ModelExample *example = [MTLJSONAdapter modelOfClass:[ModelExample class] fromJSONDictionary:dict error:&error]; 66 | NSLog(@"%@",example); 67 | 68 | ``` 69 | 如果有一些好的 批评或者意见 欢迎指出。 70 | 谢谢~ 71 | 72 | -------------------------------------------------------------------------------- /Pods/Mantle/LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) GitHub, Inc.** 2 | **All rights reserved.** 3 | 4 | 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: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | 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. 9 | 10 | --- 11 | 12 | **This project uses portions of code from the Proton framework.** 13 | **Proton is copyright (c) 2012, Bitswift, Inc.** 14 | **All rights reserved.** 15 | 16 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 17 | 18 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 19 | * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/extobjc/EXTKeyPathCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTKeyPathCoding.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 19.06.12. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import 11 | #import "metamacros.h" 12 | 13 | /** 14 | * \@keypath allows compile-time verification of key paths. Given a real object 15 | * receiver and key path: 16 | * 17 | * @code 18 | 19 | NSString *UTF8StringPath = @keypath(str.lowercaseString.UTF8String); 20 | // => @"lowercaseString.UTF8String" 21 | 22 | NSString *versionPath = @keypath(NSObject, version); 23 | // => @"version" 24 | 25 | NSString *lowercaseStringPath = @keypath(NSString.new, lowercaseString); 26 | // => @"lowercaseString" 27 | 28 | * @endcode 29 | * 30 | * ... the macro returns an \c NSString containing all but the first path 31 | * component or argument (e.g., @"lowercaseString.UTF8String", @"version"). 32 | * 33 | * In addition to simply creating a key path, this macro ensures that the key 34 | * path is valid at compile-time (causing a syntax error if not), and supports 35 | * refactoring, such that changing the name of the property will also update any 36 | * uses of \@keypath. 37 | */ 38 | #define keypath(...) \ 39 | metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__)) 40 | 41 | #define keypath1(PATH) \ 42 | (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1)) 43 | 44 | #define keypath2(OBJ, PATH) \ 45 | (((void)(NO && ((void)OBJ.PATH, NO)), # PATH)) 46 | 47 | /** 48 | * \@collectionKeypath allows compile-time verification of key paths across collections NSArray/NSSet etc. Given a real object 49 | * receiver, collection object receiver and related keypaths: 50 | * 51 | * @code 52 | 53 | NSString *employeesFirstNamePath = @collectionKeypath(department.employees, Employee.new, firstName) 54 | // => @"employees.firstName" 55 | 56 | NSString *employeesFirstNamePath = @collectionKeypath(Department.new, employees, Employee.new, firstName) 57 | // => @"employees.firstName" 58 | 59 | * @endcode 60 | * 61 | */ 62 | #define collectionKeypath(...) \ 63 | metamacro_if_eq(3, metamacro_argcount(__VA_ARGS__))(collectionKeypath3(__VA_ARGS__))(collectionKeypath4(__VA_ARGS__)) 64 | 65 | #define collectionKeypath3(PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) 66 | 67 | #define collectionKeypath4(OBJ, PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(OBJ, PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) 68 | 69 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Mantle 5 | 6 | **Copyright (c) GitHub, Inc.** 7 | **All rights reserved.** 8 | 9 | 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: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | 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. 14 | 15 | --- 16 | 17 | **This project uses portions of code from the Proton framework.** 18 | **Proton is copyright (c) 2012, Bitswift, Inc.** 19 | **All rights reserved.** 20 | 21 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 22 | 23 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 24 | * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLTransformerErrorHandling.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTLTransformerErrorHandling.h 3 | // Mantle 4 | // 5 | // Created by Robert Böhnke on 10/6/13. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /// The domain for errors originating from the MTLTransformerErrorHandling 12 | /// protocol. 13 | /// 14 | /// Transformers conforming to this protocol are expected to use this error 15 | /// domain if the transformation fails. 16 | extern NSString * const MTLTransformerErrorHandlingErrorDomain; 17 | 18 | /// Used to indicate that the input value was illegal. 19 | /// 20 | /// Transformers conforming to this protocol are expected to use this error code 21 | /// if the transformation fails due to an invalid input value. 22 | extern const NSInteger MTLTransformerErrorHandlingErrorInvalidInput; 23 | 24 | /// Associated with the invalid input value. 25 | /// 26 | /// Transformers conforming to this protocol are expected to associate this key 27 | /// with the invalid input in the userInfo dictionary. 28 | extern NSString * const MTLTransformerErrorHandlingInputValueErrorKey; 29 | 30 | /// This protocol can be implemented by NSValueTransformer subclasses to 31 | /// communicate errors that occur during transformation. 32 | @protocol MTLTransformerErrorHandling 33 | @required 34 | 35 | /// Transforms a value, returning any error that occurred during transformation. 36 | /// 37 | /// value - The value to transform. 38 | /// success - If not NULL, this will be set to a boolean indicating whether the 39 | /// transformation was successful. 40 | /// error - If not NULL, this may be set to an error that occurs during 41 | /// transforming the value. 42 | /// 43 | /// Returns the result of the transformation which may be nil. Clients should 44 | /// inspect the success parameter to decide how to proceed with the result. 45 | - (id)transformedValue:(id)value success:(BOOL *)success error:(NSError **)error; 46 | 47 | @optional 48 | 49 | /// Reverse-transforms a value, returning any error that occurred during 50 | /// transformation. 51 | /// 52 | /// Transformers conforming to this protocol are expected to implemented this 53 | /// method if they support reverse transformation. 54 | /// 55 | /// value - The value to transform. 56 | /// success - If not NULL, this will be set to a boolean indicating whether the 57 | /// transformation was successful. 58 | /// error - If not NULL, this may be set to an error that occurs during 59 | /// transforming the value. 60 | /// 61 | /// Returns the result of the reverse transformation which may be nil. Clients 62 | /// should inspect the success parameter to decide how to proceed with the 63 | /// result. 64 | - (id)reverseTransformedValue:(id)value success:(BOOL *)success error:(NSError **)error; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXBooleanTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXBooleanTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXBooleanTypeValidator.h" 11 | 12 | // Parse a number value from 'id'. 13 | static __inline__ __attribute__((always_inline)) NSNumber *YYNSNumberCreateFromID(__unsafe_unretained id value) { 14 | static NSCharacterSet *dot; 15 | static NSDictionary *dic; 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | dot = [NSCharacterSet characterSetWithRange:NSMakeRange('.', 1)]; 19 | dic = @{@"TRUE" : @(YES), 20 | @"True" : @(YES), 21 | @"true" : @(YES), 22 | @"FALSE" : @(NO), 23 | @"False" : @(NO), 24 | @"false" : @(NO), 25 | @"YES" : @(YES), 26 | @"Yes" : @(YES), 27 | @"yes" : @(YES), 28 | @"NO" : @(NO), 29 | @"No" : @(NO), 30 | @"no" : @(NO), 31 | @"NIL" : (id)kCFNull, 32 | @"Nil" : (id)kCFNull, 33 | @"nil" : (id)kCFNull, 34 | @"NULL" : (id)kCFNull, 35 | @"Null" : (id)kCFNull, 36 | @"null" : (id)kCFNull, 37 | @"(NULL)" : (id)kCFNull, 38 | @"(Null)" : (id)kCFNull, 39 | @"(null)" : (id)kCFNull, 40 | @"" : (id)kCFNull, 41 | @"" : (id)kCFNull, 42 | @"" : (id)kCFNull}; 43 | }); 44 | 45 | if (!value || value == (id)kCFNull) return nil; 46 | if ([value isKindOfClass:[NSNumber class]]) return value; 47 | if ([value isKindOfClass:[NSString class]]) { 48 | NSNumber *num = dic[value]; 49 | if (num) { 50 | if (num == (id)kCFNull) return nil; 51 | return num; 52 | } 53 | if ([(NSString *)value rangeOfCharacterFromSet:dot].location != NSNotFound) { 54 | const char *cstring = ((NSString *)value).UTF8String; 55 | if (!cstring) return nil; 56 | double num = atof(cstring); 57 | if (isnan(num) || isinf(num)) return nil; 58 | return @(num); 59 | } else { 60 | const char *cstring = ((NSString *)value).UTF8String; 61 | if (!cstring) return nil; 62 | return @(atoll(cstring)); 63 | } 64 | } 65 | return @0; 66 | } 67 | 68 | @implementation OXBooleanTypeValidator 69 | 70 | - (id)init { 71 | self = [super init]; 72 | if (self) { 73 | self.defaultValidation = ^NSNumber * (id value, BOOL *isValid, NSError **error){ 74 | *isValid = YES; 75 | return YYNSNumberCreateFromID(value); 76 | }; 77 | } 78 | 79 | return self; 80 | } 81 | 82 | @end -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | **Copyright (c) GitHub, Inc.** 18 | **All rights reserved.** 19 | 20 | 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: 21 | 22 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 23 | 24 | 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. 25 | 26 | --- 27 | 28 | **This project uses portions of code from the Proton framework.** 29 | **Proton is copyright (c) 2012, Bitswift, Inc.** 30 | **All rights reserved.** 31 | 32 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 33 | 34 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 35 | * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 36 | 37 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | License 40 | MIT 41 | Title 42 | Mantle 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | Generated by CocoaPods - https://cocoapods.org 49 | Title 50 | 51 | Type 52 | PSGroupSpecifier 53 | 54 | 55 | StringsTable 56 | Acknowledgements 57 | Title 58 | Acknowledgements 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTRuntimeExtensions.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-03-05. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import 11 | 12 | /** 13 | * Describes the memory management policy of a property. 14 | */ 15 | typedef enum { 16 | /** 17 | * The value is assigned. 18 | */ 19 | mtl_propertyMemoryManagementPolicyAssign = 0, 20 | 21 | /** 22 | * The value is retained. 23 | */ 24 | mtl_propertyMemoryManagementPolicyRetain, 25 | 26 | /** 27 | * The value is copied. 28 | */ 29 | mtl_propertyMemoryManagementPolicyCopy 30 | } mtl_propertyMemoryManagementPolicy; 31 | 32 | /** 33 | * Describes the attributes and type information of a property. 34 | */ 35 | typedef struct { 36 | /** 37 | * Whether this property was declared with the \c readonly attribute. 38 | */ 39 | BOOL readonly; 40 | 41 | /** 42 | * Whether this property was declared with the \c nonatomic attribute. 43 | */ 44 | BOOL nonatomic; 45 | 46 | /** 47 | * Whether the property is a weak reference. 48 | */ 49 | BOOL weak; 50 | 51 | /** 52 | * Whether the property is eligible for garbage collection. 53 | */ 54 | BOOL canBeCollected; 55 | 56 | /** 57 | * Whether this property is defined with \c \@dynamic. 58 | */ 59 | BOOL dynamic; 60 | 61 | /** 62 | * The memory management policy for this property. This will always be 63 | * #mtl_propertyMemoryManagementPolicyAssign if #readonly is \c YES. 64 | */ 65 | mtl_propertyMemoryManagementPolicy memoryManagementPolicy; 66 | 67 | /** 68 | * The selector for the getter of this property. This will reflect any 69 | * custom \c getter= attribute provided in the property declaration, or the 70 | * inferred getter name otherwise. 71 | */ 72 | SEL getter; 73 | 74 | /** 75 | * The selector for the setter of this property. This will reflect any 76 | * custom \c setter= attribute provided in the property declaration, or the 77 | * inferred setter name otherwise. 78 | * 79 | * @note If #readonly is \c YES, this value will represent what the setter 80 | * \e would be, if the property were writable. 81 | */ 82 | SEL setter; 83 | 84 | /** 85 | * The backing instance variable for this property, or \c NULL if \c 86 | * \c @synthesize was not used, and therefore no instance variable exists. This 87 | * would also be the case if the property is implemented dynamically. 88 | */ 89 | const char *ivar; 90 | 91 | /** 92 | * If this property is defined as being an instance of a specific class, 93 | * this will be the class object representing it. 94 | * 95 | * This will be \c nil if the property was defined as type \c id, if the 96 | * property is not of an object type, or if the class could not be found at 97 | * runtime. 98 | */ 99 | Class objectClass; 100 | 101 | /** 102 | * The type encoding for the value of this property. This is the type as it 103 | * would be returned by the \c \@encode() directive. 104 | */ 105 | char type[]; 106 | } mtl_propertyAttributes; 107 | 108 | /** 109 | * Returns a pointer to a structure containing information about \a property. 110 | * You must \c free() the returned pointer. Returns \c NULL if there is an error 111 | * obtaining information from \a property. 112 | */ 113 | mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property); 114 | -------------------------------------------------------------------------------- /OXCMantle/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXEXTRuntimeExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTRuntimeExtensions.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-03-05. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import 11 | 12 | /** 13 | * Describes the memory management policy of a property. 14 | */ 15 | typedef enum { 16 | /** 17 | * The value is assigned. 18 | */ 19 | OX_mtl_propertyMemoryManagementPolicyAssign = 0, 20 | 21 | /** 22 | * The value is retained. 23 | */ 24 | OX_mtl_propertyMemoryManagementPolicyRetain, 25 | 26 | /** 27 | * The value is copied. 28 | */ 29 | OX_mtl_propertyMemoryManagementPolicyCopy 30 | } OX_mtl_propertyMemoryManagementPolicy; 31 | 32 | /** 33 | * Describes the attributes and type information of a property. 34 | */ 35 | typedef struct { 36 | /** 37 | * Whether this property was declared with the \c readonly attribute. 38 | */ 39 | BOOL readonly; 40 | 41 | /** 42 | * Whether this property was declared with the \c nonatomic attribute. 43 | */ 44 | BOOL nonatomic; 45 | 46 | /** 47 | * Whether the property is a weak reference. 48 | */ 49 | BOOL weak; 50 | 51 | /** 52 | * Whether the property is eligible for garbage collection. 53 | */ 54 | BOOL canBeCollected; 55 | 56 | /** 57 | * Whether this property is defined with \c \@dynamic. 58 | */ 59 | BOOL dynamic; 60 | 61 | /** 62 | * The memory management policy for this property. This will always be 63 | * #mtl_propertyMemoryManagementPolicyAssign if #readonly is \c YES. 64 | */ 65 | OX_mtl_propertyMemoryManagementPolicy memoryManagementPolicy; 66 | 67 | /** 68 | * The selector for the getter of this property. This will reflect any 69 | * custom \c getter= attribute provided in the property declaration, or the 70 | * inferred getter name otherwise. 71 | */ 72 | SEL getter; 73 | 74 | /** 75 | * The selector for the setter of this property. This will reflect any 76 | * custom \c setter= attribute provided in the property declaration, or the 77 | * inferred setter name otherwise. 78 | * 79 | * @note If #readonly is \c YES, this value will represent what the setter 80 | * \e would be, if the property were writable. 81 | */ 82 | SEL setter; 83 | 84 | /** 85 | * The backing instance variable for this property, or \c NULL if \c 86 | * \c @synthesize was not used, and therefore no instance variable exists. This 87 | * would also be the case if the property is implemented dynamically. 88 | */ 89 | const char *ivar; 90 | 91 | /** 92 | * If this property is defined as being an instance of a specific class, 93 | * this will be the class object representing it. 94 | * 95 | * This will be \c nil if the property was defined as type \c id, if the 96 | * property is not of an object type, or if the class could not be found at 97 | * runtime. 98 | */ 99 | Class objectClass; 100 | 101 | /** 102 | * The type encoding for the value of this property. This is the type as it 103 | * would be returned by the \c \@encode() directive. 104 | */ 105 | char type[]; 106 | } OX_mtl_propertyAttributes; 107 | 108 | /** 109 | * Returns a pointer to a structure containing information about \a property. 110 | * You must \c free() the returned pointer. Returns \c NULL if there is an error 111 | * obtaining information from \a property. 112 | */ 113 | OX_mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property); 114 | 115 | 116 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 63 | 64 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 65 | code_sign_cmd="$code_sign_cmd &" 66 | fi 67 | echo "$code_sign_cmd" 68 | eval "$code_sign_cmd" 69 | fi 70 | } 71 | 72 | # Strip invalid architectures 73 | strip_invalid_archs() { 74 | binary="$1" 75 | # Get architectures for current file 76 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 77 | stripped="" 78 | for arch in $archs; do 79 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 80 | # Strip non-valid architectures in-place 81 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 82 | stripped="$stripped $arch" 83 | fi 84 | done 85 | if [[ "$stripped" ]]; then 86 | echo "Stripped $binary of architectures:$stripped" 87 | fi 88 | } 89 | 90 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 91 | wait 92 | fi 93 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/extobjc/EXTScope.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTScope.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-05-04. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "metamacros.h" 11 | 12 | /** 13 | * \@onExit defines some code to be executed when the current scope exits. The 14 | * code must be enclosed in braces and terminated with a semicolon, and will be 15 | * executed regardless of how the scope is exited, including from exceptions, 16 | * \c goto, \c return, \c break, and \c continue. 17 | * 18 | * Provided code will go into a block to be executed later. Keep this in mind as 19 | * it pertains to memory management, restrictions on assignment, etc. Because 20 | * the code is used within a block, \c return is a legal (though perhaps 21 | * confusing) way to exit the cleanup block early. 22 | * 23 | * Multiple \@onExit statements in the same scope are executed in reverse 24 | * lexical order. This helps when pairing resource acquisition with \@onExit 25 | * statements, as it guarantees teardown in the opposite order of acquisition. 26 | * 27 | * @note This statement cannot be used within scopes defined without braces 28 | * (like a one line \c if). In practice, this is not an issue, since \@onExit is 29 | * a useless construct in such a case anyways. 30 | */ 31 | #define onExit \ 32 | try {} @finally {} \ 33 | __strong mtl_cleanupBlock_t metamacro_concat(mtl_exitBlock_, __LINE__) __attribute__((cleanup(mtl_executeCleanupBlock), unused)) = ^ 34 | 35 | /** 36 | * Creates \c __weak shadow variables for each of the variables provided as 37 | * arguments, which can later be made strong again with #strongify. 38 | * 39 | * This is typically used to weakly reference variables in a block, but then 40 | * ensure that the variables stay alive during the actual execution of the block 41 | * (if they were live upon entry). 42 | * 43 | * See #strongify for an example of usage. 44 | */ 45 | #define weakify(...) \ 46 | try {} @finally {} \ 47 | metamacro_foreach_cxt(mtl_weakify_,, __weak, __VA_ARGS__) 48 | 49 | /** 50 | * Like #weakify, but uses \c __unsafe_unretained instead, for targets or 51 | * classes that do not support weak references. 52 | */ 53 | #define unsafeify(...) \ 54 | try {} @finally {} \ 55 | metamacro_foreach_cxt(mtl_weakify_,, __unsafe_unretained, __VA_ARGS__) 56 | 57 | /** 58 | * Strongly references each of the variables provided as arguments, which must 59 | * have previously been passed to #weakify. 60 | * 61 | * The strong references created will shadow the original variable names, such 62 | * that the original names can be used without issue (and a significantly 63 | * reduced risk of retain cycles) in the current scope. 64 | * 65 | * @code 66 | 67 | id foo = [[NSObject alloc] init]; 68 | id bar = [[NSObject alloc] init]; 69 | 70 | @weakify(foo, bar); 71 | 72 | // this block will not keep 'foo' or 'bar' alive 73 | BOOL (^matchesFooOrBar)(id) = ^ BOOL (id obj){ 74 | // but now, upon entry, 'foo' and 'bar' will stay alive until the block has 75 | // finished executing 76 | @strongify(foo, bar); 77 | 78 | return [foo isEqual:obj] || [bar isEqual:obj]; 79 | }; 80 | 81 | * @endcode 82 | */ 83 | #define strongify(...) \ 84 | try {} @finally {} \ 85 | _Pragma("clang diagnostic push") \ 86 | _Pragma("clang diagnostic ignored \"-Wshadow\"") \ 87 | metamacro_foreach(mtl_strongify_,, __VA_ARGS__) \ 88 | _Pragma("clang diagnostic pop") 89 | 90 | /*** implementation details follow ***/ 91 | typedef void (^mtl_cleanupBlock_t)(); 92 | 93 | void mtl_executeCleanupBlock (__strong mtl_cleanupBlock_t *block); 94 | 95 | #define mtl_weakify_(INDEX, CONTEXT, VAR) \ 96 | CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR); 97 | 98 | #define mtl_strongify_(INDEX, VAR) \ 99 | __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_); 100 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCModel/NSValueTransformer+MantleExtention.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSValueTransformer+MantleExtention.m 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/23/14. 6 | // Released under the MIT license 7 | // 8 | 9 | #import "NSValueTransformer+MantleExtention.h" 10 | #import "NSValueTransformer+MTLPredefinedTransformerAdditions.h" 11 | #import "MTLJSONAdapter.h" 12 | #import "MTLModel.h" 13 | #import "MTLValueTransformer.h" 14 | #import "OXStringTypeValidator.h" 15 | 16 | @implementation NSValueTransformer (MantleExtention) 17 | 18 | + (NSValueTransformer *)oxc_mtl_JSONArrayTransformerWithBasicClass:(Class)basicClass{ 19 | return [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error){ 20 | NSArray *dictionaries = value; 21 | if (dictionaries == nil) return nil; 22 | 23 | NSAssert([dictionaries isKindOfClass:NSArray.class], @"Expected a array of object, got: %@", dictionaries); 24 | 25 | NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count]; 26 | for (id JSONObject in dictionaries) { 27 | if (JSONObject == NSNull.null) { 28 | [models addObject:NSNull.null]; 29 | continue; 30 | } 31 | if (value == nil) return nil; 32 | OXPropertyType propertyType = [OXValidatorReflection oxc_propertyTypeForBasicClassStr:NSStringFromClass(basicClass)]; 33 | NSAssert(OXPropertyUnknown != propertyType, @"只接受基本的数据类型 OXPropertyType 中包含的类型"); 34 | if (OXPropertyUnknown == propertyType) { 35 | continue; 36 | } 37 | OXBaseValidator *validator = [OXValidatorReflection oxc_validatorForPropertyType:propertyType]; 38 | NSError* err; 39 | id model = JSONObject; 40 | [validator validateValue:&model error:&err]; 41 | [models addObject:model]; 42 | } 43 | 44 | return models; 45 | } reverseBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) { 46 | NSArray *models = value; 47 | if (models == nil) return nil; 48 | 49 | NSAssert([models isKindOfClass:NSArray.class], @"Expected a array of object, got: %@", models); 50 | 51 | NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count]; 52 | for (id model in models) { 53 | if (model == NSNull.null) { 54 | [dictionaries addObject:NSNull.null]; 55 | continue; 56 | } 57 | [dictionaries addObject:[model description]]; 58 | } 59 | 60 | return dictionaries; 61 | }]; 62 | } 63 | 64 | 65 | + (NSValueTransformer *)oxc_mtl_basicClassyTransformerWithBasicType:(OXPropertyType)propertyType{ 66 | 67 | NSValueTransformer *transformer = [NSValueTransformer valueTransformerForName:[NSString stringWithFormat:@"oxc_mtl_%lu",(unsigned long)propertyType]]; 68 | if (transformer) { 69 | return transformer; 70 | } 71 | 72 | OXBaseValidator *transformerValidator = [OXValidatorReflection oxc_validatorForPropertyType:propertyType]; 73 | if (!transformerValidator) { 74 | return nil; 75 | } 76 | 77 | transformer = 78 | [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error){ 79 | 80 | NSError* err; 81 | id model = value; 82 | [transformerValidator validateValue:&model error:&err]; 83 | return model; 84 | } reverseBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) { 85 | 86 | if (value == nil) return nil; 87 | OXBaseValidator *validator = [OXStringTypeValidator new]; 88 | id model = value; 89 | [validator validateValue:&model error:nil]; 90 | return [model description]; 91 | }]; 92 | 93 | [NSValueTransformer setValueTransformer:transformer forName:[NSString stringWithFormat:@"oxc_mtl_%lu",(unsigned long)propertyType]]; 94 | return transformer; 95 | } 96 | 97 | 98 | @end 99 | 100 | 101 | @implementation NSValueTransformer (OXCDiscarded) 102 | 103 | + (NSValueTransformer *)mtl_JSONArrayTransformerWithBasicClass:(Class)basicClass{ 104 | return [self oxc_mtl_JSONArrayTransformerWithBasicClass:basicClass]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTLValueTransformer.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-11. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLValueTransformer.h" 10 | 11 | // 12 | // Any MTLValueTransformer supporting reverse transformation. Necessary because 13 | // +allowsReverseTransformation is a class method. 14 | // 15 | @interface MTLReversibleValueTransformer : MTLValueTransformer 16 | @end 17 | 18 | @interface MTLValueTransformer () 19 | 20 | @property (nonatomic, copy, readonly) MTLValueTransformerBlock forwardBlock; 21 | @property (nonatomic, copy, readonly) MTLValueTransformerBlock reverseBlock; 22 | 23 | @end 24 | 25 | @implementation MTLValueTransformer 26 | 27 | #pragma mark Lifecycle 28 | 29 | + (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardBlock { 30 | return [[self alloc] initWithForwardBlock:forwardBlock reverseBlock:nil]; 31 | } 32 | 33 | + (instancetype)transformerUsingReversibleBlock:(MTLValueTransformerBlock)reversibleBlock { 34 | return [self transformerUsingForwardBlock:reversibleBlock reverseBlock:reversibleBlock]; 35 | } 36 | 37 | + (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock { 38 | return [[MTLReversibleValueTransformer alloc] initWithForwardBlock:forwardBlock reverseBlock:reverseBlock]; 39 | } 40 | 41 | - (id)initWithForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock { 42 | NSParameterAssert(forwardBlock != nil); 43 | 44 | self = [super init]; 45 | if (self == nil) return nil; 46 | 47 | _forwardBlock = [forwardBlock copy]; 48 | _reverseBlock = [reverseBlock copy]; 49 | 50 | return self; 51 | } 52 | 53 | #pragma mark NSValueTransformer 54 | 55 | + (BOOL)allowsReverseTransformation { 56 | return NO; 57 | } 58 | 59 | + (Class)transformedValueClass { 60 | return NSObject.class; 61 | } 62 | 63 | - (id)transformedValue:(id)value { 64 | NSError *error = nil; 65 | BOOL success = YES; 66 | 67 | return self.forwardBlock(value, &success, &error); 68 | } 69 | 70 | - (id)transformedValue:(id)value success:(BOOL *)outerSuccess error:(NSError **)outerError { 71 | NSError *error = nil; 72 | BOOL success = YES; 73 | 74 | id transformedValue = self.forwardBlock(value, &success, &error); 75 | 76 | if (outerSuccess != NULL) *outerSuccess = success; 77 | if (outerError != NULL) *outerError = error; 78 | 79 | return transformedValue; 80 | } 81 | 82 | @end 83 | 84 | @implementation MTLReversibleValueTransformer 85 | 86 | #pragma mark Lifecycle 87 | 88 | - (id)initWithForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock { 89 | NSParameterAssert(reverseBlock != nil); 90 | return [super initWithForwardBlock:forwardBlock reverseBlock:reverseBlock]; 91 | } 92 | 93 | #pragma mark NSValueTransformer 94 | 95 | + (BOOL)allowsReverseTransformation { 96 | return YES; 97 | } 98 | 99 | - (id)reverseTransformedValue:(id)value { 100 | NSError *error = nil; 101 | BOOL success = YES; 102 | 103 | return self.reverseBlock(value, &success, &error); 104 | } 105 | 106 | - (id)reverseTransformedValue:(id)value success:(BOOL *)outerSuccess error:(NSError **)outerError { 107 | NSError *error = nil; 108 | BOOL success = YES; 109 | 110 | id transformedValue = self.reverseBlock(value, &success, &error); 111 | 112 | if (outerSuccess != NULL) *outerSuccess = success; 113 | if (outerError != NULL) *outerError = error; 114 | 115 | return transformedValue; 116 | } 117 | 118 | @end 119 | 120 | 121 | @implementation MTLValueTransformer (Deprecated) 122 | 123 | #pragma clang diagnostic push 124 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 125 | 126 | + (instancetype)transformerWithBlock:(id (^)(id))transformationBlock { 127 | return [self transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { 128 | return transformationBlock(value); 129 | }]; 130 | } 131 | 132 | + (instancetype)reversibleTransformerWithBlock:(id (^)(id))transformationBlock { 133 | return [self transformerUsingReversibleBlock:^(id value, BOOL *success, NSError **error) { 134 | return transformationBlock(value); 135 | }]; 136 | } 137 | 138 | + (instancetype)reversibleTransformerWithForwardBlock:(id (^)(id))forwardBlock reverseBlock:(id (^)(id))reverseBlock { 139 | return [self 140 | transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { 141 | return forwardBlock(value); 142 | } 143 | reverseBlock:^(id value, BOOL *success, NSError **error) { 144 | return reverseBlock(value); 145 | }]; 146 | } 147 | 148 | #pragma clang diagnostic pop 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /OXCMantle.xcodeproj/xcshareddata/xcschemes/OXCMantle.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-OXCMantle/Pods-OXCMantle-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | 3) 22 | TARGET_DEVICE_ARGS="--target-device tv" 23 | ;; 24 | *) 25 | TARGET_DEVICE_ARGS="--target-device mac" 26 | ;; 27 | esac 28 | 29 | install_resource() 30 | { 31 | if [[ "$1" = /* ]] ; then 32 | RESOURCE_PATH="$1" 33 | else 34 | RESOURCE_PATH="${PODS_ROOT}/$1" 35 | fi 36 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 37 | cat << EOM 38 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 39 | EOM 40 | exit 1 41 | fi 42 | case $RESOURCE_PATH in 43 | *.storyboard) 44 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 45 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 46 | ;; 47 | *.xib) 48 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 49 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 50 | ;; 51 | *.framework) 52 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 54 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 55 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | ;; 57 | *.xcdatamodel) 58 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 59 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 60 | ;; 61 | *.xcdatamodeld) 62 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 63 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 64 | ;; 65 | *.xcmappingmodel) 66 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 67 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 68 | ;; 69 | *.xcassets) 70 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 71 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 72 | ;; 73 | *) 74 | echo "$RESOURCE_PATH" 75 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 76 | ;; 77 | esac 78 | } 79 | 80 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 83 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | fi 86 | rm -f "$RESOURCES_TO_COPY" 87 | 88 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 89 | then 90 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 91 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 92 | while read line; do 93 | if [[ $line != "${PODS_ROOT}*" ]]; then 94 | XCASSET_FILES+=("$line") 95 | fi 96 | done <<<"$OTHER_XCASSETS" 97 | 98 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | fi 100 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLModel+NSCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTLModel+NSCoding.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-02-12. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLModel.h" 10 | 11 | /// Defines how a MTLModel property key should be encoded into an archive. 12 | /// 13 | /// MTLModelEncodingBehaviorExcluded - The property should never be encoded. 14 | /// MTLModelEncodingBehaviorUnconditional - The property should always be 15 | /// encoded. 16 | /// MTLModelEncodingBehaviorConditional - The object should be encoded only 17 | /// if unconditionally encoded elsewhere. 18 | /// This should only be used for object 19 | /// properties. 20 | typedef enum : NSUInteger { 21 | MTLModelEncodingBehaviorExcluded = 0, 22 | MTLModelEncodingBehaviorUnconditional, 23 | MTLModelEncodingBehaviorConditional, 24 | } MTLModelEncodingBehavior; 25 | 26 | /// Implements default archiving and unarchiving behaviors for MTLModel. 27 | @interface MTLModel (NSCoding) 28 | 29 | /// Initializes the receiver from an archive. 30 | /// 31 | /// This will decode the original +modelVersion of the archived object, then 32 | /// invoke -decodeValueForKey:withCoder:modelVersion: for each of the receiver's 33 | /// +propertyKeys. 34 | /// 35 | /// Returns an initialized model object, or nil if a decoding error occurred. 36 | - (id)initWithCoder:(NSCoder *)coder; 37 | 38 | /// Archives the receiver using the given coder. 39 | /// 40 | /// This will encode the receiver's +modelVersion, then the receiver's properties 41 | /// according to the behaviors specified in +encodingBehaviorsByPropertyKey. 42 | - (void)encodeWithCoder:(NSCoder *)coder; 43 | 44 | /// Determines how the +propertyKeys of the class are encoded into an archive. 45 | /// The values of this dictionary should be boxed MTLModelEncodingBehavior 46 | /// values. 47 | /// 48 | /// Any keys not present in the dictionary will be excluded from the archive. 49 | /// 50 | /// Subclasses overriding this method should combine their values with those of 51 | /// `super`. 52 | /// 53 | /// Returns a dictionary mapping the receiver's +propertyKeys to default encoding 54 | /// behaviors. If a property is an object with `weak` semantics, the default 55 | /// behavior is MTLModelEncodingBehaviorConditional; otherwise, the default is 56 | /// MTLModelEncodingBehaviorUnconditional. 57 | + (NSDictionary *)encodingBehaviorsByPropertyKey; 58 | 59 | /// Determines the classes that are allowed to be decoded for each of the 60 | /// receiver's properties when using . The values of this 61 | /// dictionary should be NSArrays of Class objects. 62 | /// 63 | /// If any encodable keys (as determined by +encodingBehaviorsByPropertyKey) are 64 | /// not present in the dictionary, an exception will be thrown during secure 65 | /// encoding or decoding. 66 | /// 67 | /// Subclasses overriding this method should combine their values with those of 68 | /// `super`. 69 | /// 70 | /// Returns a dictionary mapping the receiver's encodable keys (as determined by 71 | /// +encodingBehaviorsByPropertyKey) to default allowed classes, based on the 72 | /// type that each property is declared as. If type of an encodable property 73 | /// cannot be determined (e.g., it is declared as `id`), it will be omitted from 74 | /// the dictionary, and subclasses must provide a valid value to prevent an 75 | /// exception being thrown during encoding/decoding. 76 | + (NSDictionary *)allowedSecureCodingClassesByPropertyKey; 77 | 78 | /// Decodes the value of the given property key from an archive. 79 | /// 80 | /// By default, this method looks for a `-decodeWithCoder:modelVersion:` 81 | /// method on the receiver, and invokes it if found. 82 | /// 83 | /// If the custom method is not implemented and `coder` does not require secure 84 | /// coding, `-[NSCoder decodeObjectForKey:]` will be invoked with the given 85 | /// `key`. 86 | /// 87 | /// If the custom method is not implemented and `coder` requires secure coding, 88 | /// `-[NSCoder decodeObjectOfClasses:forKey:]` will be invoked with the 89 | /// information from +allowedSecureCodingClassesByPropertyKey and the given `key`. The 90 | /// receiver must conform to for this to work correctly. 91 | /// 92 | /// key - The property key to decode the value for. This argument cannot 93 | /// be nil. 94 | /// coder - The NSCoder representing the archive being decoded. This 95 | /// argument cannot be nil. 96 | /// modelVersion - The version of the original model object that was encoded. 97 | /// 98 | /// Returns the decoded and boxed value, or nil if the key was not present. 99 | - (id)decodeValueForKey:(NSString *)key withCoder:(NSCoder *)coder modelVersion:(NSUInteger)modelVersion; 100 | 101 | /// The version of this MTLModel subclass. 102 | /// 103 | /// This version number is saved in archives so that later model changes can be 104 | /// made backwards-compatible with old versions. 105 | /// 106 | /// Subclasses should override this method to return a higher version number 107 | /// whenever a breaking change is made to the model. 108 | /// 109 | /// Returns 0. 110 | + (NSUInteger)modelVersion; 111 | 112 | @end 113 | 114 | /// This method must be overridden to support archives created by older versions 115 | /// of Mantle (before the `MTLModel+NSCoding` interface existed). 116 | @interface MTLModel (OldArchiveSupport) 117 | 118 | /// Converts an archived external representation to a dictionary suitable for 119 | /// passing to -initWithDictionary:. 120 | /// 121 | /// externalRepresentation - The decoded external representation of the receiver. 122 | /// fromVersion - The model version at the time the external 123 | /// representation was encoded. 124 | /// 125 | /// Returns nil by default, indicating that conversion failed. 126 | + (NSDictionary *)dictionaryValueFromArchivedExternalRepresentation:(NSDictionary *)externalRepresentation version:(NSUInteger)fromVersion; 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSValueTransformer+MTLPredefinedTransformerAdditions.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-27. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MTLTransformerErrorHandling.h" 12 | 13 | /// The name for a value transformer that converts strings into URLs and back. 14 | extern NSString * const MTLURLValueTransformerName; 15 | 16 | /// The name for a value transformer that converts strings into NSUUIDs and back. 17 | extern NSString * const MTLUUIDValueTransformerName; 18 | 19 | /// Ensure an NSNumber is backed by __NSCFBoolean/CFBooleanRef 20 | /// 21 | /// NSJSONSerialization, and likely other serialization libraries, ordinarily 22 | /// serialize NSNumbers as numbers, and thus booleans would be serialized as 23 | /// 0/1. The exception is when the NSNumber is backed by __NSCFBoolean, which, 24 | /// though very much an implementation detail, is detected and serialized as a 25 | /// proper boolean. 26 | extern NSString * const MTLBooleanValueTransformerName; 27 | 28 | @interface NSValueTransformer (MTLPredefinedTransformerAdditions) 29 | 30 | /// An optionally reversible transformer which applies the given transformer to 31 | /// each element of an array. 32 | /// 33 | /// transformer - The transformer to apply to each element. If the transformer 34 | /// is reversible, the transformer returned by this method will be 35 | /// reversible. This argument must not be nil. 36 | /// 37 | /// Returns a transformer which applies a transformation to each element of an 38 | /// array. 39 | + (NSValueTransformer *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer; 40 | 41 | /// A reversible value transformer to transform between the keys and objects of a 42 | /// dictionary. 43 | /// 44 | /// dictionary - The dictionary whose keys and values should be 45 | /// transformed between. This argument must not be nil. 46 | /// defaultValue - The result to fall back to, in case no key matching the 47 | /// input value was found during a forward transformation. 48 | /// reverseDefaultValue - The result to fall back to, in case no value matching 49 | /// the input value was found during a reverse 50 | /// transformation. 51 | /// 52 | /// Can for example be used for transforming between enum values and their string 53 | /// representation. 54 | /// 55 | /// NSValueTransformer *valueTransformer = [NSValueTransformer mtl_valueMappingTransformerWithDictionary:@{ 56 | /// @"foo": @(EnumDataTypeFoo), 57 | /// @"bar": @(EnumDataTypeBar), 58 | /// } defaultValue: @(EnumDataTypeUndefined) reverseDefaultValue: @"undefined"]; 59 | /// 60 | /// Returns a transformer which will map from keys to objects for forward 61 | /// transformations, and from objects to keys for reverse transformations. 62 | + (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue; 63 | 64 | /// Returns a value transformer created by calling 65 | /// `+mtl_valueMappingTransformerWithDictionary:defaultValue:reverseDefaultValue:` 66 | /// with a default value of `nil` and a reverse default value of `nil`. 67 | + (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary; 68 | 69 | /// A reversible value transformer to transform between a date and its string 70 | /// representation 71 | /// 72 | /// dateFormat - The date format used by the date formatter (http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table) 73 | /// calendar - The calendar used by the date formatter 74 | /// locale - The locale used by the date formatter 75 | /// timeZone - The time zone used by the date formatter 76 | /// 77 | /// Returns a transformer which will map from strings to dates for forward 78 | /// transformations, and from dates to strings for reverse transformations. 79 | + (NSValueTransformer *)mtl_dateTransformerWithDateFormat:(NSString *)dateFormat calendar:(NSCalendar *)calendar locale:(NSLocale *)locale timeZone:(NSTimeZone *)timeZone defaultDate:(NSDate *)defaultDate; 80 | 81 | /// Returns a value transformer created by calling 82 | /// `+mtl_dateTransformerWithDateFormat:calendar:locale:timeZone:defaultDate:` 83 | /// with a calendar, locale, time zone and default date of `nil`. 84 | + (NSValueTransformer *)mtl_dateTransformerWithDateFormat:(NSString *)dateFormat locale:(NSLocale *)locale; 85 | 86 | /// A reversible value transformer to transform between a number and its string 87 | /// representation 88 | /// 89 | /// numberStyle - The number style used by the number formatter 90 | /// 91 | /// Returns a transformer which will map from strings to numbers for forward 92 | /// transformations, and from numbers to strings for reverse transformations. 93 | + (NSValueTransformer *)mtl_numberTransformerWithNumberStyle:(NSNumberFormatterStyle)numberStyle locale:(NSLocale *)locale; 94 | 95 | /// A reversible value transformer to transform between an object and its string 96 | /// representation 97 | /// 98 | /// formatter - The formatter used to perform the transformation 99 | /// objectClass - The class of object that the formatter operates on 100 | /// 101 | /// Returns a transformer which will map from strings to objects for forward 102 | /// transformations, and from objects to strings for reverse transformations. 103 | + (NSValueTransformer *)mtl_transformerWithFormatter:(NSFormatter *)formatter forObjectClass:(Class)objectClass; 104 | 105 | /// A value transformer that errors if the transformed value are not of the given 106 | /// class. 107 | /// 108 | /// class - The expected class. This argument must not be nil. 109 | /// 110 | /// Returns a transformer which will return an error if the transformed in value 111 | /// is not a member of class. Otherwise, the value is simply passed through. 112 | + (NSValueTransformer *)mtl_validatingTransformerForClass:(Class)modelClass; 113 | 114 | + (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[MTLJSONAdapter dictionaryTransformerWithModelClass:]"))); 115 | 116 | + (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[MTLJSONAdapter arrayTransformerWithModelClass:]"))); 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDateTypeValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXDateTypeValidator 3 | // Oxen 4 | // 5 | // Created by Matthew on 6/16/14. 6 | // Released under the MIT license 7 | // 8 | 9 | 10 | #import "OXDateTypeValidator.h" 11 | /** 12 | * 此处使用了YYModel的函数 https://github.com/ibireme/YYModel/blob/master/YYModel/NSObject%2BYYModel.m 13 | */ 14 | /// Parse string to date. 15 | static __inline__ __attribute__((always_inline)) NSDate *YYNSDateFromString(__unsafe_unretained NSString *string) { 16 | typedef NSDate* (^YYNSDateParseBlock)(NSString *string); 17 | #define kParserNum 34 18 | static YYNSDateParseBlock blocks[kParserNum + 1] = {0}; 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | { 22 | /* 23 | 2014-01-20 // Google 24 | */ 25 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 26 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 27 | formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 28 | formatter.dateFormat = @"yyyy-MM-dd"; 29 | blocks[10] = ^(NSString *string) { return [formatter dateFromString:string]; }; 30 | } 31 | 32 | { 33 | /* 34 | 2014-01-20 12:24:48 35 | 2014-01-20T12:24:48 // Google 36 | 2014-01-20 12:24:48.000 37 | 2014-01-20T12:24:48.000 38 | */ 39 | NSDateFormatter *formatter1 = [[NSDateFormatter alloc] init]; 40 | formatter1.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 41 | formatter1.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 42 | formatter1.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; 43 | 44 | NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init]; 45 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 46 | formatter2.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 47 | formatter2.dateFormat = @"yyyy-MM-dd HH:mm:ss"; 48 | 49 | NSDateFormatter *formatter3 = [[NSDateFormatter alloc] init]; 50 | formatter3.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 51 | formatter3.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 52 | formatter3.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS"; 53 | 54 | NSDateFormatter *formatter4 = [[NSDateFormatter alloc] init]; 55 | formatter4.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 56 | formatter4.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 57 | formatter4.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; 58 | 59 | blocks[19] = ^(NSString *string) { 60 | if ([string characterAtIndex:10] == 'T') { 61 | return [formatter1 dateFromString:string]; 62 | } else { 63 | return [formatter2 dateFromString:string]; 64 | } 65 | }; 66 | 67 | blocks[23] = ^(NSString *string) { 68 | if ([string characterAtIndex:10] == 'T') { 69 | return [formatter3 dateFromString:string]; 70 | } else { 71 | return [formatter4 dateFromString:string]; 72 | } 73 | }; 74 | } 75 | 76 | { 77 | /* 78 | 2014-01-20T12:24:48Z // Github, Apple 79 | 2014-01-20T12:24:48+0800 // Facebook 80 | 2014-01-20T12:24:48+12:00 // Google 81 | 2014-01-20T12:24:48.000Z 82 | 2014-01-20T12:24:48.000+0800 83 | 2014-01-20T12:24:48.000+12:00 84 | */ 85 | NSDateFormatter *formatter = [NSDateFormatter new]; 86 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 87 | formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ"; 88 | 89 | NSDateFormatter *formatter2 = [NSDateFormatter new]; 90 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 91 | formatter2.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ"; 92 | 93 | blocks[20] = ^(NSString *string) { return [formatter dateFromString:string]; }; 94 | blocks[24] = ^(NSString *string) { return [formatter dateFromString:string]?: [formatter2 dateFromString:string]; }; 95 | blocks[25] = ^(NSString *string) { return [formatter dateFromString:string]; }; 96 | blocks[28] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 97 | blocks[29] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 98 | } 99 | 100 | { 101 | /* 102 | Fri Sep 04 00:12:21 +0800 2015 // Weibo, Twitter 103 | Fri Sep 04 00:12:21.000 +0800 2015 104 | */ 105 | NSDateFormatter *formatter = [NSDateFormatter new]; 106 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 107 | formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; 108 | 109 | NSDateFormatter *formatter2 = [NSDateFormatter new]; 110 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 111 | formatter2.dateFormat = @"EEE MMM dd HH:mm:ss.SSS Z yyyy"; 112 | 113 | blocks[30] = ^(NSString *string) { return [formatter dateFromString:string]; }; 114 | blocks[34] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 115 | } 116 | }); 117 | if (!string) return nil; 118 | if (string.length > kParserNum) return nil; 119 | YYNSDateParseBlock parser = blocks[string.length]; 120 | if (!parser) return nil; 121 | return parser(string); 122 | #undef kParserNum 123 | } 124 | 125 | 126 | 127 | @implementation OXDateTypeValidator 128 | 129 | - (id)init { 130 | self = [super init]; 131 | 132 | if (self) { 133 | self.defaultValidation = ^NSDate *(id value, BOOL *isValid, NSError **error){ 134 | if ([value isKindOfClass:[NSNumber class]]){ 135 | *isValid = YES; 136 | return [NSDate dateWithTimeIntervalSince1970:[value doubleValue]]; 137 | } 138 | 139 | static dispatch_once_t onceToken; 140 | static dispatch_queue_t dateQueue; 141 | dispatch_once(&onceToken, ^{ 142 | dateQueue = dispatch_queue_create("com.OXCMantle.OXDateTypeValidator.datequeue", NULL); 143 | }); 144 | NSString *stringDate; 145 | if ([value isKindOfClass:[NSString class]]){ 146 | stringDate = value; 147 | } else if ([value respondsToSelector:@selector(stringValue)]){ 148 | stringDate = [value stringValue]; 149 | } 150 | if (stringDate){ 151 | *isValid = YES; 152 | __block NSDate *date; 153 | dispatch_sync(dateQueue, ^{ 154 | date = YYNSDateFromString(stringDate); 155 | }); 156 | *isValid = date?YES:NO; 157 | return date; 158 | } 159 | *isValid = NO; 160 | return nil; 161 | }; 162 | } 163 | return self; 164 | } 165 | 166 | - (BOOL)validateValue:(id *)value error:(NSError **)error { 167 | _isValid = [*value isKindOfClass:[NSDate class]]; 168 | return [super validateValue:value error:error]; 169 | } 170 | 171 | @end -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXTRuntimeExtensions.m 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-03-05. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "EXTRuntimeExtensions.h" 11 | 12 | #import 13 | 14 | mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property) { 15 | const char * const attrString = property_getAttributes(property); 16 | if (!attrString) { 17 | fprintf(stderr, "ERROR: Could not get attribute string from property %s\n", property_getName(property)); 18 | return NULL; 19 | } 20 | 21 | if (attrString[0] != 'T') { 22 | fprintf(stderr, "ERROR: Expected attribute string \"%s\" for property %s to start with 'T'\n", attrString, property_getName(property)); 23 | return NULL; 24 | } 25 | 26 | const char *typeString = attrString + 1; 27 | const char *next = NSGetSizeAndAlignment(typeString, NULL, NULL); 28 | if (!next) { 29 | fprintf(stderr, "ERROR: Could not read past type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 30 | return NULL; 31 | } 32 | 33 | size_t typeLength = next - typeString; 34 | if (!typeLength) { 35 | fprintf(stderr, "ERROR: Invalid type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 36 | return NULL; 37 | } 38 | 39 | // allocate enough space for the structure and the type string (plus a NUL) 40 | mtl_propertyAttributes *attributes = calloc(1, sizeof(mtl_propertyAttributes) + typeLength + 1); 41 | if (!attributes) { 42 | fprintf(stderr, "ERROR: Could not allocate mtl_propertyAttributes structure for attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 43 | return NULL; 44 | } 45 | 46 | // copy the type string 47 | strncpy(attributes->type, typeString, typeLength); 48 | attributes->type[typeLength] = '\0'; 49 | 50 | // if this is an object type, and immediately followed by a quoted string... 51 | if (typeString[0] == *(@encode(id)) && typeString[1] == '"') { 52 | // we should be able to extract a class name 53 | const char *className = typeString + 2; 54 | next = strchr(className, '"'); 55 | 56 | if (!next) { 57 | fprintf(stderr, "ERROR: Could not read class name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 58 | return NULL; 59 | } 60 | 61 | if (className != next) { 62 | size_t classNameLength = next - className; 63 | char trimmedName[classNameLength + 1]; 64 | 65 | strncpy(trimmedName, className, classNameLength); 66 | trimmedName[classNameLength] = '\0'; 67 | 68 | // attempt to look up the class in the runtime 69 | attributes->objectClass = objc_getClass(trimmedName); 70 | } 71 | } 72 | 73 | if (*next != '\0') { 74 | // skip past any junk before the first flag 75 | next = strchr(next, ','); 76 | } 77 | 78 | while (next && *next == ',') { 79 | char flag = next[1]; 80 | next += 2; 81 | 82 | switch (flag) { 83 | case '\0': 84 | break; 85 | 86 | case 'R': 87 | attributes->readonly = YES; 88 | break; 89 | 90 | case 'C': 91 | attributes->memoryManagementPolicy = mtl_propertyMemoryManagementPolicyCopy; 92 | break; 93 | 94 | case '&': 95 | attributes->memoryManagementPolicy = mtl_propertyMemoryManagementPolicyRetain; 96 | break; 97 | 98 | case 'N': 99 | attributes->nonatomic = YES; 100 | break; 101 | 102 | case 'G': 103 | case 'S': 104 | { 105 | const char *nextFlag = strchr(next, ','); 106 | SEL name = NULL; 107 | 108 | if (!nextFlag) { 109 | // assume that the rest of the string is the selector 110 | const char *selectorString = next; 111 | next = ""; 112 | 113 | name = sel_registerName(selectorString); 114 | } else { 115 | size_t selectorLength = nextFlag - next; 116 | if (!selectorLength) { 117 | fprintf(stderr, "ERROR: Found zero length selector name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 118 | goto errorOut; 119 | } 120 | 121 | char selectorString[selectorLength + 1]; 122 | 123 | strncpy(selectorString, next, selectorLength); 124 | selectorString[selectorLength] = '\0'; 125 | 126 | name = sel_registerName(selectorString); 127 | next = nextFlag; 128 | } 129 | 130 | if (flag == 'G') 131 | attributes->getter = name; 132 | else 133 | attributes->setter = name; 134 | } 135 | 136 | break; 137 | 138 | case 'D': 139 | attributes->dynamic = YES; 140 | attributes->ivar = NULL; 141 | break; 142 | 143 | case 'V': 144 | // assume that the rest of the string (if present) is the ivar name 145 | if (*next == '\0') { 146 | // if there's nothing there, let's assume this is dynamic 147 | attributes->ivar = NULL; 148 | } else { 149 | attributes->ivar = next; 150 | next = ""; 151 | } 152 | 153 | break; 154 | 155 | case 'W': 156 | attributes->weak = YES; 157 | break; 158 | 159 | case 'P': 160 | attributes->canBeCollected = YES; 161 | break; 162 | 163 | case 't': 164 | fprintf(stderr, "ERROR: Old-style type encoding is unsupported in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 165 | 166 | // skip over this type encoding 167 | while (*next != ',' && *next != '\0') 168 | ++next; 169 | 170 | break; 171 | 172 | default: 173 | fprintf(stderr, "ERROR: Unrecognized attribute string flag '%c' in attribute string \"%s\" for property %s\n", flag, attrString, property_getName(property)); 174 | } 175 | } 176 | 177 | if (next && *next != '\0') { 178 | fprintf(stderr, "Warning: Unparsed data \"%s\" in attribute string \"%s\" for property %s\n", next, attrString, property_getName(property)); 179 | } 180 | 181 | if (!attributes->getter) { 182 | // use the property name as the getter by default 183 | attributes->getter = sel_registerName(property_getName(property)); 184 | } 185 | 186 | if (!attributes->setter) { 187 | const char *propertyName = property_getName(property); 188 | size_t propertyNameLength = strlen(propertyName); 189 | 190 | // we want to transform the name to setProperty: style 191 | size_t setterLength = propertyNameLength + 4; 192 | 193 | char setterName[setterLength + 1]; 194 | strncpy(setterName, "set", 3); 195 | strncpy(setterName + 3, propertyName, propertyNameLength); 196 | 197 | // capitalize property name for the setter 198 | setterName[3] = (char)toupper(setterName[3]); 199 | 200 | setterName[setterLength - 1] = ':'; 201 | setterName[setterLength] = '\0'; 202 | 203 | attributes->setter = sel_registerName(setterName); 204 | } 205 | 206 | return attributes; 207 | 208 | errorOut: 209 | free(attributes); 210 | return NULL; 211 | } 212 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTLModel.h 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-11. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /// Defines a property's storage behavior, which affects how it will be copied, 12 | /// compared, and persisted. 13 | /// 14 | /// MTLPropertyStorageNone - This property is not included in -description, 15 | /// -hash, or anything else. 16 | /// MTLPropertyStorageTransitory - This property is included in one-off 17 | /// operations like -copy and -dictionaryValue but 18 | /// does not affect -isEqual: or -hash. 19 | /// It may disappear at any time. 20 | /// MTLPropertyStoragePermanent - The property is included in serialization 21 | /// (like `NSCoding`) and equality, since it can 22 | /// be expected to stick around. 23 | typedef enum : NSUInteger { 24 | MTLPropertyStorageNone, 25 | MTLPropertyStorageTransitory, 26 | MTLPropertyStoragePermanent, 27 | } MTLPropertyStorage; 28 | 29 | /// This protocol defines the minimal interface that classes need to implement to 30 | /// interact with Mantle adapters. 31 | /// 32 | /// It is intended for scenarios where inheriting from MTLModel is not feasible. 33 | /// However, clients are encouraged to subclass the MTLModel class if they can. 34 | /// 35 | /// Clients that wish to implement their own adapters should target classes 36 | /// conforming to this protocol rather than subclasses of MTLModel to ensure 37 | /// maximum compatibility. 38 | @protocol MTLModel 39 | 40 | /// Initializes a new instance of the receiver using key-value coding, setting 41 | /// the keys and values in the given dictionary. 42 | /// 43 | /// dictionaryValue - Property keys and values to set on the instance. Any NSNull 44 | /// values will be converted to nil before being used. KVC 45 | /// validation methods will automatically be invoked for all of 46 | /// the properties given. 47 | /// error - If not NULL, this may be set to any error that occurs 48 | /// (like a KVC validation error). 49 | /// 50 | /// Returns an initialized model object, or nil if validation failed. 51 | + (instancetype)modelWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; 52 | 53 | /// A dictionary representing the properties of the receiver. 54 | /// 55 | /// Combines the values corresponding to all +propertyKeys into a dictionary, 56 | /// with any nil values represented by NSNull. 57 | /// 58 | /// This property must never be nil. 59 | @property (nonatomic, copy, readonly) NSDictionary *dictionaryValue; 60 | 61 | /// Initializes the receiver using key-value coding, setting the keys and values 62 | /// in the given dictionary. 63 | /// 64 | /// Subclass implementations may override this method, calling the super 65 | /// implementation, in order to perform further processing and initialization 66 | /// after deserialization. 67 | /// 68 | /// dictionaryValue - Property keys and values to set on the receiver. Any NSNull 69 | /// values will be converted to nil before being used. KVC 70 | /// validation methods will automatically be invoked for all of 71 | /// the properties given. If nil, this method is equivalent to 72 | /// -init. 73 | /// error - If not NULL, this may be set to any error that occurs 74 | /// (like a KVC validation error). 75 | /// 76 | /// Returns an initialized model object, or nil if validation failed. 77 | - (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; 78 | 79 | /// Merges the value of the given key on the receiver with the value of the same 80 | /// key from the given model object, giving precedence to the other model object. 81 | - (void)mergeValueForKey:(NSString *)key fromModel:(id)model; 82 | 83 | /// Returns the keys for all @property declarations, except for `readonly` 84 | /// properties without ivars, or properties on MTLModel itself. 85 | + (NSSet *)propertyKeys; 86 | 87 | /// Validates the model. 88 | /// 89 | /// error - If not NULL, this may be set to any error that occurs during 90 | /// validation 91 | /// 92 | /// Returns YES if the model is valid, or NO if the validation failed. 93 | - (BOOL)validate:(NSError **)error; 94 | 95 | @end 96 | 97 | /// An abstract base class for model objects, using reflection to provide 98 | /// sensible default behaviors. 99 | /// 100 | /// The default implementations of , -hash, and -isEqual: make use of 101 | /// the +propertyKeys method. 102 | @interface MTLModel : NSObject 103 | 104 | /// Initializes the receiver using key-value coding, setting the keys and values 105 | /// in the given dictionary. 106 | /// 107 | /// dictionaryValue - Property keys and values to set on the receiver. Any NSNull 108 | /// values will be converted to nil before being used. KVC 109 | /// validation methods will automatically be invoked for all of 110 | /// the properties given. If nil, this method is equivalent to 111 | /// -init. 112 | /// error - If not NULL, this may be set to any error that occurs 113 | /// (like a KVC validation error). 114 | /// 115 | /// Returns an initialized model object, or nil if validation failed. 116 | - (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; 117 | 118 | /// Initializes the receiver with default values. 119 | /// 120 | /// This is the designated initializer for this class. 121 | - (instancetype)init; 122 | 123 | /// By default, this method looks for a `-mergeFromModel:` method on the 124 | /// receiver, and invokes it if found. If not found, and `model` is not nil, the 125 | /// value for the given key is taken from `model`. 126 | - (void)mergeValueForKey:(NSString *)key fromModel:(id)model; 127 | 128 | /// Merges the values of the given model object into the receiver, using 129 | /// -mergeValueForKey:fromModel: for each key in +propertyKeys. 130 | /// 131 | /// `model` must be an instance of the receiver's class or a subclass thereof. 132 | - (void)mergeValuesForKeysFromModel:(id)model; 133 | 134 | /// The storage behavior of a given key. 135 | /// 136 | /// The default implementation returns MTLPropertyStorageNone for properties that 137 | /// are readonly and not backed by an instance variable and 138 | /// MTLPropertyStoragePermanent otherwise. 139 | /// 140 | /// Subclasses can use this method to prevent MTLModel from resolving circular 141 | /// references by returning MTLPropertyStorageTransitory. 142 | /// 143 | /// Returns the storage behavior for a given key on the receiver. 144 | + (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey; 145 | 146 | /// Compares the receiver with another object for equality. 147 | /// 148 | /// The default implementation is equivalent to comparing all properties of both 149 | /// models for which +storageBehaviorForPropertyWithKey: returns 150 | /// MTLPropertyStoragePermanent. 151 | /// 152 | /// Returns YES if the two models are considered equal, NO otherwise. 153 | - (BOOL)isEqual:(id)object; 154 | 155 | /// A string that describes the contents of the receiver. 156 | /// 157 | /// The default implementation is based on the receiver's class and all its 158 | /// properties for which +storageBehaviorForPropertyWithKey: returns 159 | /// MTLPropertyStoragePermanent. 160 | - (NSString *)description; 161 | 162 | @end 163 | 164 | /// Implements validation logic for MTLModel. 165 | @interface MTLModel (Validation) 166 | 167 | /// Validates the model. 168 | /// 169 | /// The default implementation simply invokes -validateValue:forKey:error: with 170 | /// all +propertyKeys and their current value. If -validateValue:forKey:error: 171 | /// returns a new value, the property is set to that new value. 172 | /// 173 | /// error - If not NULL, this may be set to any error that occurs during 174 | /// validation 175 | /// 176 | /// Returns YES if the model is valid, or NO if the validation failed. 177 | - (BOOL)validate:(NSError **)error; 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXEXTRuntimeExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXTRuntimeExtensions.m 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-03-05. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "OXEXTRuntimeExtensions.h" 11 | #import 12 | OX_mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property) { 13 | const char * const attrString = property_getAttributes(property); 14 | if (!attrString) { 15 | fprintf(stderr, "ERROR: Could not get attribute string from property %s\n", property_getName(property)); 16 | return NULL; 17 | } 18 | 19 | if (attrString[0] != 'T') { 20 | fprintf(stderr, "ERROR: Expected attribute string \"%s\" for property %s to start with 'T'\n", attrString, property_getName(property)); 21 | return NULL; 22 | } 23 | 24 | const char *typeString = attrString + 1; 25 | const char *next = NSGetSizeAndAlignment(typeString, NULL, NULL); 26 | if (!next) { 27 | fprintf(stderr, "ERROR: Could not read past type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 28 | return NULL; 29 | } 30 | 31 | size_t typeLength = next - typeString; 32 | if (!typeLength) { 33 | fprintf(stderr, "ERROR: Invalid type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 34 | return NULL; 35 | } 36 | 37 | // allocate enough space for the structure and the type string (plus a NUL) 38 | OX_mtl_propertyAttributes *attributes = calloc(1, sizeof(OX_mtl_propertyAttributes) + typeLength + 1); 39 | if (!attributes) { 40 | fprintf(stderr, "ERROR: Could not allocate mtl_propertyAttributes structure for attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 41 | return NULL; 42 | } 43 | 44 | // copy the type string 45 | strncpy(attributes->type, typeString, typeLength); 46 | attributes->type[typeLength] = '\0'; 47 | 48 | // if this is an object type, and immediately followed by a quoted string... 49 | if (typeString[0] == *(@encode(id)) && typeString[1] == '"') { 50 | // we should be able to extract a class name 51 | const char *className = typeString + 2; 52 | next = strchr(className, '"'); 53 | 54 | if (!next) { 55 | fprintf(stderr, "ERROR: Could not read class name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 56 | return NULL; 57 | } 58 | 59 | if (className != next) { 60 | size_t classNameLength = next - className; 61 | char trimmedName[classNameLength + 1]; 62 | 63 | strncpy(trimmedName, className, classNameLength); 64 | trimmedName[classNameLength] = '\0'; 65 | 66 | // attempt to look up the class in the runtime 67 | attributes->objectClass = objc_getClass(trimmedName); 68 | } 69 | } 70 | 71 | if (*next != '\0') { 72 | // skip past any junk before the first flag 73 | next = strchr(next, ','); 74 | } 75 | 76 | while (next && *next == ',') { 77 | char flag = next[1]; 78 | next += 2; 79 | 80 | switch (flag) { 81 | case '\0': 82 | break; 83 | 84 | case 'R': 85 | attributes->readonly = YES; 86 | break; 87 | 88 | case 'C': 89 | attributes->memoryManagementPolicy = OX_mtl_propertyMemoryManagementPolicyCopy; 90 | break; 91 | 92 | case '&': 93 | attributes->memoryManagementPolicy = OX_mtl_propertyMemoryManagementPolicyRetain; 94 | break; 95 | 96 | case 'N': 97 | attributes->nonatomic = YES; 98 | break; 99 | 100 | case 'G': 101 | case 'S': 102 | { 103 | const char *nextFlag = strchr(next, ','); 104 | SEL name = NULL; 105 | 106 | if (!nextFlag) { 107 | // assume that the rest of the string is the selector 108 | const char *selectorString = next; 109 | next = ""; 110 | 111 | name = sel_registerName(selectorString); 112 | } else { 113 | size_t selectorLength = nextFlag - next; 114 | if (!selectorLength) { 115 | fprintf(stderr, "ERROR: Found zero length selector name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 116 | goto errorOut; 117 | } 118 | 119 | char selectorString[selectorLength + 1]; 120 | 121 | strncpy(selectorString, next, selectorLength); 122 | selectorString[selectorLength] = '\0'; 123 | 124 | name = sel_registerName(selectorString); 125 | next = nextFlag; 126 | } 127 | 128 | if (flag == 'G') 129 | attributes->getter = name; 130 | else 131 | attributes->setter = name; 132 | } 133 | 134 | break; 135 | 136 | case 'D': 137 | attributes->dynamic = YES; 138 | attributes->ivar = NULL; 139 | break; 140 | 141 | case 'V': 142 | // assume that the rest of the string (if present) is the ivar name 143 | if (*next == '\0') { 144 | // if there's nothing there, let's assume this is dynamic 145 | attributes->ivar = NULL; 146 | } else { 147 | attributes->ivar = next; 148 | next = ""; 149 | } 150 | 151 | break; 152 | 153 | case 'W': 154 | attributes->weak = YES; 155 | break; 156 | 157 | case 'P': 158 | attributes->canBeCollected = YES; 159 | break; 160 | 161 | case 't': 162 | fprintf(stderr, "ERROR: Old-style type encoding is unsupported in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); 163 | 164 | // skip over this type encoding 165 | while (*next != ',' && *next != '\0') 166 | ++next; 167 | 168 | break; 169 | 170 | default: 171 | fprintf(stderr, "ERROR: Unrecognized attribute string flag '%c' in attribute string \"%s\" for property %s\n", flag, attrString, property_getName(property)); 172 | } 173 | } 174 | 175 | if (next && *next != '\0') { 176 | fprintf(stderr, "Warning: Unparsed data \"%s\" in attribute string \"%s\" for property %s\n", next, attrString, property_getName(property)); 177 | } 178 | 179 | if (!attributes->getter) { 180 | // use the property name as the getter by default 181 | attributes->getter = sel_registerName(property_getName(property)); 182 | } 183 | 184 | if (!attributes->setter) { 185 | const char *propertyName = property_getName(property); 186 | size_t propertyNameLength = strlen(propertyName); 187 | 188 | // we want to transform the name to setProperty: style 189 | size_t setterLength = propertyNameLength + 4; 190 | 191 | char setterName[setterLength + 1]; 192 | strncpy(setterName, "set", 3); 193 | strncpy(setterName + 3, propertyName, propertyNameLength); 194 | 195 | // capitalize property name for the setter 196 | setterName[3] = (char)toupper(setterName[3]); 197 | 198 | setterName[setterLength - 1] = ':'; 199 | setterName[setterLength] = '\0'; 200 | 201 | attributes->setter = sel_registerName(setterName); 202 | } 203 | 204 | return attributes; 205 | 206 | errorOut: 207 | free(attributes); 208 | return NULL; 209 | } 210 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXValidatorReflection.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXValidatorReflection.m 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/6/11. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #import "OXValidatorReflection.h" 10 | #import "OXEXTRuntimeExtensions.h" 11 | #import "NSString+ValidationUtils.h" 12 | #import 13 | 14 | #import "OXStringTypeValidator.h" 15 | #import "OXBooleanTypeValidator.h" 16 | #import "OXIntegerTypeValidator.h" 17 | #import "OXFloatTypeValidator.h" 18 | #import "OXArrayTypeValidator.h" 19 | #import "OXDictionaryTypeValidator.h" 20 | #import "OXUnsignedIntegerTypeValidator.h" 21 | #import "OXDoubleTypeValidator.h" 22 | #import "OXDateTypeValidator.h" 23 | #import "OXLongTypeValidator.h" 24 | #import "OXUnsignedLongTypeValicdator.h" 25 | 26 | BOOL validateStringProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 27 | OXStringTypeValidator *validator = [OXStringTypeValidator new]; 28 | 29 | return [validator validateValue:ioValue error:outError]; 30 | } 31 | 32 | BOOL validateBoolProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 33 | OXBooleanTypeValidator *validator = [OXBooleanTypeValidator new]; 34 | 35 | return [validator validateValue:ioValue error:outError]; 36 | } 37 | 38 | BOOL validateNumberProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 39 | OXNumberTypeValidator *validator = [OXNumberTypeValidator new]; 40 | 41 | return [validator validateValue:ioValue error:outError]; 42 | } 43 | 44 | BOOL validateIntegerProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 45 | OXIntegerTypeValidator *validator = [OXIntegerTypeValidator new]; 46 | 47 | return [validator validateValue:ioValue error:outError]; 48 | } 49 | 50 | BOOL validateUnsignedLongProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 51 | OXUnsignedLongTypeValicdator *validator = [OXUnsignedLongTypeValicdator new]; 52 | 53 | return [validator validateValue:ioValue error:outError]; 54 | } 55 | 56 | BOOL validateLongProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 57 | OXLongTypeValidator *validator = [OXLongTypeValidator new]; 58 | 59 | return [validator validateValue:ioValue error:outError]; 60 | } 61 | 62 | BOOL validateFloatProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 63 | OXFloatTypeValidator *validator = [OXFloatTypeValidator new]; 64 | 65 | return [validator validateValue:ioValue error:outError]; 66 | } 67 | 68 | BOOL validateArrayProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 69 | OXArrayTypeValidator *validator = [OXArrayTypeValidator new]; 70 | 71 | return [validator validateValue:ioValue error:outError]; 72 | } 73 | 74 | BOOL validateDictionaryProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 75 | OXDictionaryTypeValidator *validator = [OXDictionaryTypeValidator new]; 76 | 77 | return [validator validateValue:ioValue error:outError]; 78 | } 79 | 80 | BOOL validateUnsignedIntegerProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 81 | OXUnsignedIntegerTypeValidator *validator = [OXUnsignedIntegerTypeValidator new]; 82 | 83 | return [validator validateValue:ioValue error:outError]; 84 | } 85 | 86 | BOOL validateDoubleProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 87 | OXDoubleTypeValidator *validator = [OXDoubleTypeValidator new]; 88 | 89 | return [validator validateValue:ioValue error:outError]; 90 | } 91 | 92 | BOOL validateDateProperty(id self, SEL _cmd, id *ioValue, NSError *__autoreleasing* outError){ 93 | OXDateTypeValidator *validator = [OXDateTypeValidator new]; 94 | 95 | return [validator validateValue:ioValue error:outError]; 96 | } 97 | 98 | 99 | 100 | 101 | 102 | @implementation OXValidatorReflection 103 | + (OXPropertyType)oxc_propertypeWithName:(NSString *)propertyName clazz:(Class)clazz{ 104 | objc_property_t property = class_getProperty(clazz, propertyName.UTF8String); 105 | if (property == NULL){ 106 | return OXPropertyUnknown; 107 | } 108 | OX_mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); 109 | NSString *classStr = NSStringFromClass(attributes->objectClass); 110 | 111 | if (0 == classStr.length) { 112 | classStr = [NSString stringWithUTF8String:attributes->type]; 113 | } 114 | free(attributes); 115 | OXPropertyType type = [self oxc_propertyTypeForBasicClassStr:classStr];; 116 | return type; 117 | } 118 | 119 | + (OXPropertyType)oxc_propertyTypeForBasicClassStr:(NSString *)clazzStr{ 120 | OXPropertyType typeVlaue = [[[self oxc_oxpropertyTypeDict] objectForKey:clazzStr] integerValue]; 121 | return typeVlaue; 122 | } 123 | 124 | + (NSDictionary *)oxc_oxpropertyTypeDict{ 125 | static NSDictionary *propertyTypesDict = nil; 126 | if (0 == propertyTypesDict.allKeys.count) { 127 | propertyTypesDict = @{@"Unknown" : @(OXPropertyUnknown), 128 | NSStringFromClass([NSString class]) : @(OXPropertyTypeString), 129 | [NSString stringWithFormat:@"%s",@encode(BOOL)] : @(OXPropertyTypeBool), 130 | NSStringFromClass([NSNumber class]): @(OXPropertyTypeNumber), 131 | [NSString stringWithFormat:@"%s",@encode(int)] : @(OXPropertyTypeInteger), 132 | [NSString stringWithFormat:@"%s",@encode(float)] : @(OXPropertyTypeFloat), 133 | NSStringFromClass([NSArray class]) : @(OXPropertyTypeArray), 134 | NSStringFromClass([NSMutableArray class]) : @(OXPropertyTypeMutableArray), 135 | NSStringFromClass([NSDictionary class]) : @(OXPropertyTypeDictionary), 136 | NSStringFromClass([NSMutableDictionary class]) : @(OXPropertyTypeMutableDictionary), 137 | [NSString stringWithFormat:@"%s",@encode(unsigned int)] : @(OXPropertyTypeUnsignedInteger), 138 | NSStringFromClass([NSDate class]) : @(OXPropertyTypeDate), 139 | [NSString stringWithFormat:@"%s",@encode(double)] : @(OXPropertyTypeDouble), 140 | [NSString stringWithFormat:@"%s",@encode(long)] : @(OXPropertyTypeLong), 141 | [NSString stringWithFormat:@"%s",@encode(unsigned long)] : @(OXPropertyTypeUnsignedLong), 142 | }; 143 | 144 | } 145 | return propertyTypesDict; 146 | } 147 | 148 | + (OXBaseValidator *)oxc_validatorForPropertyType:(OXPropertyType)propertyType{ 149 | static NSDictionary *validatorDict = nil; 150 | if (validatorDict.allKeys.count == 0) { 151 | validatorDict = @{ 152 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeString]: [OXStringTypeValidator new], 153 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeBool]: [OXStringTypeValidator new], 154 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeNumber]: [OXNumberTypeValidator new], 155 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeInteger]: [OXIntegerTypeValidator new], 156 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeFloat]: [OXFloatTypeValidator new], 157 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeArray]: [OXArrayTypeValidator new], 158 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeMutableArray]: [OXArrayTypeValidator new], 159 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeDictionary]: [OXDictionaryTypeValidator new], 160 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeMutableDictionary]: [OXDictionaryTypeValidator new], 161 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeUnsignedInteger]: [OXUnsignedIntegerTypeValidator new], 162 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeDate]: [OXDateTypeValidator new], 163 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeDouble]: [OXDoubleTypeValidator new], 164 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeLong]: [OXLongTypeValidator new], 165 | [NSString stringWithFormat:@"%lu",(unsigned long)OXPropertyTypeUnsignedLong]: [OXUnsignedLongTypeValicdator new] 166 | }; 167 | } 168 | return validatorDict[[NSString stringWithFormat:@"%lu",(unsigned long)propertyType]]; 169 | } 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /OXCMantle/Classes/OXCValidation/OXDValidationFunctions.m: -------------------------------------------------------------------------------- 1 | // 2 | // OXDValidationFunctions.c 3 | // OXCMantle 4 | // 5 | // Created by 张旭东 on 16/7/28. 6 | // Copyright © 2016年 张旭东. All rights reserved. 7 | // 8 | 9 | #include "OXDValidationFunctions.h" 10 | 11 | /// Parse a number value from 'id'. 12 | static __attribute__((always_inline)) NSNumber *OXD_YYNSNumberCreateFromID(__unsafe_unretained id value) { 13 | static NSCharacterSet *dot; 14 | static NSDictionary *dic; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | dot = [NSCharacterSet characterSetWithRange:NSMakeRange('.', 1)]; 18 | dic = @{@"TRUE" : @(YES), 19 | @"True" : @(YES), 20 | @"true" : @(YES), 21 | @"FALSE" : @(NO), 22 | @"False" : @(NO), 23 | @"false" : @(NO), 24 | @"YES" : @(YES), 25 | @"Yes" : @(YES), 26 | @"yes" : @(YES), 27 | @"NO" : @(NO), 28 | @"No" : @(NO), 29 | @"no" : @(NO), 30 | @"NIL" : (id)kCFNull, 31 | @"Nil" : (id)kCFNull, 32 | @"nil" : (id)kCFNull, 33 | @"NULL" : (id)kCFNull, 34 | @"Null" : (id)kCFNull, 35 | @"null" : (id)kCFNull, 36 | @"(NULL)" : (id)kCFNull, 37 | @"(Null)" : (id)kCFNull, 38 | @"(null)" : (id)kCFNull, 39 | @"" : (id)kCFNull, 40 | @"" : (id)kCFNull, 41 | @"" : (id)kCFNull}; 42 | }); 43 | 44 | if (!value || value == (id)kCFNull) return nil; 45 | if ([value isKindOfClass:[NSNumber class]]) return value; 46 | if ([value isKindOfClass:[NSString class]]) { 47 | NSNumber *num = dic[value]; 48 | if (num) { 49 | if (num == (id)kCFNull) return nil; 50 | return num; 51 | } 52 | if ([(NSString *)value rangeOfCharacterFromSet:dot].location != NSNotFound) { 53 | const char *cstring = ((NSString *)value).UTF8String; 54 | if (!cstring) return nil; 55 | double num = atof(cstring); 56 | if (isnan(num) || isinf(num)) return nil; 57 | return @(num); 58 | } else { 59 | const char *cstring = ((NSString *)value).UTF8String; 60 | if (!cstring) return nil; 61 | return @(atoll(cstring)); 62 | } 63 | } 64 | return nil; 65 | } 66 | 67 | /// Parse string to date. 68 | static __attribute__((always_inline)) NSDate *_OXD_YYNSDateFromString(__unsafe_unretained NSString *string) { 69 | typedef NSDate* (^YYNSDateParseBlock)(NSString *string); 70 | #define kParserNum 34 71 | static YYNSDateParseBlock blocks[kParserNum + 1] = {0}; 72 | static dispatch_once_t onceToken; 73 | dispatch_once(&onceToken, ^{ 74 | { 75 | /* 76 | 2014-01-20 // Google 77 | */ 78 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 79 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 80 | formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 81 | formatter.dateFormat = @"yyyy-MM-dd"; 82 | blocks[10] = ^(NSString *string) { return [formatter dateFromString:string]; }; 83 | } 84 | 85 | { 86 | /* 87 | 2014-01-20 12:24:48 88 | 2014-01-20T12:24:48 // Google 89 | 2014-01-20 12:24:48.000 90 | 2014-01-20T12:24:48.000 91 | */ 92 | NSDateFormatter *formatter1 = [[NSDateFormatter alloc] init]; 93 | formatter1.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 94 | formatter1.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 95 | formatter1.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; 96 | 97 | NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init]; 98 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 99 | formatter2.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 100 | formatter2.dateFormat = @"yyyy-MM-dd HH:mm:ss"; 101 | 102 | NSDateFormatter *formatter3 = [[NSDateFormatter alloc] init]; 103 | formatter3.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 104 | formatter3.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 105 | formatter3.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS"; 106 | 107 | NSDateFormatter *formatter4 = [[NSDateFormatter alloc] init]; 108 | formatter4.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 109 | formatter4.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 110 | formatter4.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; 111 | 112 | blocks[19] = ^(NSString *string) { 113 | if ([string characterAtIndex:10] == 'T') { 114 | return [formatter1 dateFromString:string]; 115 | } else { 116 | return [formatter2 dateFromString:string]; 117 | } 118 | }; 119 | 120 | blocks[23] = ^(NSString *string) { 121 | if ([string characterAtIndex:10] == 'T') { 122 | return [formatter3 dateFromString:string]; 123 | } else { 124 | return [formatter4 dateFromString:string]; 125 | } 126 | }; 127 | } 128 | 129 | { 130 | /* 131 | 2014-01-20T12:24:48Z // Github, Apple 132 | 2014-01-20T12:24:48+0800 // Facebook 133 | 2014-01-20T12:24:48+12:00 // Google 134 | 2014-01-20T12:24:48.000Z 135 | 2014-01-20T12:24:48.000+0800 136 | 2014-01-20T12:24:48.000+12:00 137 | */ 138 | NSDateFormatter *formatter = [NSDateFormatter new]; 139 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 140 | formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ"; 141 | 142 | NSDateFormatter *formatter2 = [NSDateFormatter new]; 143 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 144 | formatter2.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ"; 145 | 146 | blocks[20] = ^(NSString *string) { return [formatter dateFromString:string]; }; 147 | blocks[24] = ^(NSString *string) { return [formatter dateFromString:string]?: [formatter2 dateFromString:string]; }; 148 | blocks[25] = ^(NSString *string) { return [formatter dateFromString:string]; }; 149 | blocks[28] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 150 | blocks[29] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 151 | } 152 | 153 | { 154 | /* 155 | Fri Sep 04 00:12:21 +0800 2015 // Weibo, Twitter 156 | Fri Sep 04 00:12:21.000 +0800 2015 157 | */ 158 | NSDateFormatter *formatter = [NSDateFormatter new]; 159 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 160 | formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; 161 | 162 | NSDateFormatter *formatter2 = [NSDateFormatter new]; 163 | formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 164 | formatter2.dateFormat = @"EEE MMM dd HH:mm:ss.SSS Z yyyy"; 165 | 166 | blocks[30] = ^(NSString *string) { return [formatter dateFromString:string]; }; 167 | blocks[34] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; 168 | } 169 | }); 170 | if (!string) return nil; 171 | if (string.length > kParserNum) return nil; 172 | YYNSDateParseBlock parser = blocks[string.length]; 173 | if (!parser) return nil; 174 | return parser(string); 175 | #undef kParserNum 176 | } 177 | 178 | 179 | BOOL oxd_validateStringProperty(id *ioValue, NSError *__autoreleasing* outError){ 180 | return YES; 181 | } 182 | 183 | BOOL oxd_validateBoolProperty(id *ioValue, NSError *__autoreleasing* outError){ 184 | return YES; 185 | } 186 | 187 | 188 | BOOL oxd_validateNumberProperty(id *ioValue, NSError *__autoreleasing* outError){ 189 | return YES; 190 | } 191 | 192 | 193 | BOOL oxd_validateIntegerProperty(id *ioValue, NSError *__autoreleasing* outError){ 194 | return YES; 195 | } 196 | 197 | 198 | BOOL oxd_validateUnsignedLongProperty(id *ioValue, NSError *__autoreleasing* outError){ 199 | return YES; 200 | } 201 | 202 | 203 | BOOL oxd_validateLongProperty(id *ioValue, NSError *__autoreleasing* outError){ 204 | return YES; 205 | } 206 | 207 | 208 | BOOL oxd_validateFloatProperty(id *ioValue, NSError *__autoreleasing* outError){ 209 | return YES; 210 | } 211 | 212 | 213 | BOOL oxd_validateArrayProperty(id *ioValue, NSError *__autoreleasing* outError){ 214 | return YES; 215 | } 216 | 217 | BOOL oxd_validateDictionaryProperty(id *ioValue, NSError *__autoreleasing* outError){ 218 | return YES; 219 | } 220 | 221 | BOOL oxd_validateUnsignedIntegerProperty(id *ioValue, NSError *__autoreleasing* outError){ 222 | return YES; 223 | } 224 | 225 | BOOL oxd_validateDoubleProperty(id *ioValue, NSError *__autoreleasing* outError){ 226 | return YES; 227 | } 228 | 229 | BOOL oxd_validateDateProperty(id *ioValue, NSError *__autoreleasing* outError){ 230 | return YES; 231 | } 232 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLModel+NSCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTLModel+NSCoding.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2013-02-12. 6 | // Copyright (c) 2013 GitHub. All rights reserved. 7 | // 8 | 9 | #import "MTLModel+NSCoding.h" 10 | #import 11 | #import 12 | #import "MTLReflection.h" 13 | 14 | // Used in archives to store the modelVersion of the archived instance. 15 | static NSString * const MTLModelVersionKey = @"MTLModelVersion"; 16 | 17 | // Used to cache the reflection performed in +allowedSecureCodingClassesByPropertyKey. 18 | static void *MTLModelCachedAllowedClassesKey = &MTLModelCachedAllowedClassesKey; 19 | 20 | // Returns whether the given NSCoder requires secure coding. 21 | static BOOL coderRequiresSecureCoding(NSCoder *coder) { 22 | SEL requiresSecureCodingSelector = @selector(requiresSecureCoding); 23 | 24 | // Only invoke the method if it's implemented (i.e., only on OS X 10.8+ and 25 | // iOS 6+). 26 | if (![coder respondsToSelector:requiresSecureCodingSelector]) return NO; 27 | 28 | BOOL (*requiresSecureCodingIMP)(NSCoder *, SEL) = (__typeof__(requiresSecureCodingIMP))[coder methodForSelector:requiresSecureCodingSelector]; 29 | if (requiresSecureCodingIMP == NULL) return NO; 30 | 31 | return requiresSecureCodingIMP(coder, requiresSecureCodingSelector); 32 | } 33 | 34 | // Returns all of the given class' encodable property keys (those that will not 35 | // be excluded from archives). 36 | static NSSet *encodablePropertyKeysForClass(Class modelClass) { 37 | return [[modelClass encodingBehaviorsByPropertyKey] keysOfEntriesPassingTest:^ BOOL (NSString *propertyKey, NSNumber *behavior, BOOL *stop) { 38 | return behavior.unsignedIntegerValue != MTLModelEncodingBehaviorExcluded; 39 | }]; 40 | } 41 | 42 | // Verifies that all of the specified class' encodable property keys are present 43 | // in +allowedSecureCodingClassesByPropertyKey, and throws an exception if not. 44 | static void verifyAllowedClassesByPropertyKey(Class modelClass) { 45 | NSDictionary *allowedClasses = [modelClass allowedSecureCodingClassesByPropertyKey]; 46 | 47 | NSMutableSet *specifiedPropertyKeys = [[NSMutableSet alloc] initWithArray:allowedClasses.allKeys]; 48 | [specifiedPropertyKeys minusSet:encodablePropertyKeysForClass(modelClass)]; 49 | 50 | if (specifiedPropertyKeys.count > 0) { 51 | [NSException raise:NSInvalidArgumentException format:@"Cannot encode %@ securely, because keys are missing from +allowedSecureCodingClassesByPropertyKey: %@", modelClass, specifiedPropertyKeys]; 52 | } 53 | } 54 | 55 | @implementation MTLModel (NSCoding) 56 | 57 | #pragma mark Versioning 58 | 59 | + (NSUInteger)modelVersion { 60 | return 0; 61 | } 62 | 63 | #pragma mark Encoding Behaviors 64 | 65 | + (NSDictionary *)encodingBehaviorsByPropertyKey { 66 | NSSet *propertyKeys = self.propertyKeys; 67 | NSMutableDictionary *behaviors = [[NSMutableDictionary alloc] initWithCapacity:propertyKeys.count]; 68 | 69 | for (NSString *key in propertyKeys) { 70 | objc_property_t property = class_getProperty(self, key.UTF8String); 71 | NSAssert(property != NULL, @"Could not find property \"%@\" on %@", key, self); 72 | 73 | mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); 74 | @onExit { 75 | free(attributes); 76 | }; 77 | 78 | MTLModelEncodingBehavior behavior = (attributes->weak ? MTLModelEncodingBehaviorConditional : MTLModelEncodingBehaviorUnconditional); 79 | behaviors[key] = @(behavior); 80 | } 81 | 82 | return behaviors; 83 | } 84 | 85 | + (NSDictionary *)allowedSecureCodingClassesByPropertyKey { 86 | NSDictionary *cachedClasses = objc_getAssociatedObject(self, MTLModelCachedAllowedClassesKey); 87 | if (cachedClasses != nil) return cachedClasses; 88 | 89 | // Get all property keys that could potentially be encoded. 90 | NSSet *propertyKeys = [self.encodingBehaviorsByPropertyKey keysOfEntriesPassingTest:^ BOOL (NSString *propertyKey, NSNumber *behavior, BOOL *stop) { 91 | return behavior.unsignedIntegerValue != MTLModelEncodingBehaviorExcluded; 92 | }]; 93 | 94 | NSMutableDictionary *allowedClasses = [[NSMutableDictionary alloc] initWithCapacity:propertyKeys.count]; 95 | 96 | for (NSString *key in propertyKeys) { 97 | objc_property_t property = class_getProperty(self, key.UTF8String); 98 | NSAssert(property != NULL, @"Could not find property \"%@\" on %@", key, self); 99 | 100 | mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); 101 | @onExit { 102 | free(attributes); 103 | }; 104 | 105 | // If the property is not of object or class type, assume that it's 106 | // a primitive which would be boxed into an NSValue. 107 | if (attributes->type[0] != '@' && attributes->type[0] != '#') { 108 | allowedClasses[key] = @[ NSValue.class ]; 109 | continue; 110 | } 111 | 112 | // Omit this property from the dictionary if its class isn't known. 113 | if (attributes->objectClass != nil) { 114 | allowedClasses[key] = @[ attributes->objectClass ]; 115 | } 116 | } 117 | 118 | // It doesn't really matter if we replace another thread's work, since we do 119 | // it atomically and the result should be the same. 120 | objc_setAssociatedObject(self, MTLModelCachedAllowedClassesKey, allowedClasses, OBJC_ASSOCIATION_COPY); 121 | 122 | return allowedClasses; 123 | } 124 | 125 | - (id)decodeValueForKey:(NSString *)key withCoder:(NSCoder *)coder modelVersion:(NSUInteger)modelVersion { 126 | NSParameterAssert(key != nil); 127 | NSParameterAssert(coder != nil); 128 | 129 | SEL selector = MTLSelectorWithCapitalizedKeyPattern("decode", key, "WithCoder:modelVersion:"); 130 | if ([self respondsToSelector:selector]) { 131 | IMP imp = [self methodForSelector:selector]; 132 | id (*function)(id, SEL, NSCoder *, NSUInteger) = (__typeof__(function))imp; 133 | id result = function(self, selector, coder, modelVersion); 134 | 135 | return result; 136 | } 137 | 138 | @try { 139 | if (coderRequiresSecureCoding(coder)) { 140 | NSArray *allowedClasses = self.class.allowedSecureCodingClassesByPropertyKey[key]; 141 | NSAssert(allowedClasses != nil, @"No allowed classes specified for securely decoding key \"%@\" on %@", key, self.class); 142 | 143 | return [coder decodeObjectOfClasses:[NSSet setWithArray:allowedClasses] forKey:key]; 144 | } else { 145 | return [coder decodeObjectForKey:key]; 146 | } 147 | } @catch (NSException *ex) { 148 | NSLog(@"*** Caught exception decoding value for key \"%@\" on class %@: %@", key, self.class, ex); 149 | @throw ex; 150 | } 151 | } 152 | 153 | #pragma mark NSCoding 154 | 155 | - (instancetype)initWithCoder:(NSCoder *)coder { 156 | BOOL requiresSecureCoding = coderRequiresSecureCoding(coder); 157 | NSNumber *version = nil; 158 | if (requiresSecureCoding) { 159 | version = [coder decodeObjectOfClass:NSNumber.class forKey:MTLModelVersionKey]; 160 | } else { 161 | version = [coder decodeObjectForKey:MTLModelVersionKey]; 162 | } 163 | 164 | if (version == nil) { 165 | NSLog(@"Warning: decoding an archive of %@ without a version, assuming 0", self.class); 166 | } else if (version.unsignedIntegerValue > self.class.modelVersion) { 167 | // Don't try to decode newer versions. 168 | return nil; 169 | } 170 | 171 | if (requiresSecureCoding) { 172 | verifyAllowedClassesByPropertyKey(self.class); 173 | } else { 174 | // Handle the old archive format. 175 | NSDictionary *externalRepresentation = [coder decodeObjectForKey:@"externalRepresentation"]; 176 | if (externalRepresentation != nil) { 177 | NSAssert([self.class methodForSelector:@selector(dictionaryValueFromArchivedExternalRepresentation:version:)] != [MTLModel methodForSelector:@selector(dictionaryValueFromArchivedExternalRepresentation:version:)], @"Decoded an old archive of %@ that contains an externalRepresentation, but +dictionaryValueFromArchivedExternalRepresentation:version: is not overridden to handle it", self.class); 178 | 179 | NSDictionary *dictionaryValue = [self.class dictionaryValueFromArchivedExternalRepresentation:externalRepresentation version:version.unsignedIntegerValue]; 180 | if (dictionaryValue == nil) return nil; 181 | 182 | NSError *error = nil; 183 | self = [self initWithDictionary:dictionaryValue error:&error]; 184 | if (self == nil) NSLog(@"*** Could not decode old %@ archive: %@", self.class, error); 185 | 186 | return self; 187 | } 188 | } 189 | 190 | NSSet *propertyKeys = self.class.propertyKeys; 191 | NSMutableDictionary *dictionaryValue = [[NSMutableDictionary alloc] initWithCapacity:propertyKeys.count]; 192 | 193 | for (NSString *key in propertyKeys) { 194 | id value = [self decodeValueForKey:key withCoder:coder modelVersion:version.unsignedIntegerValue]; 195 | if (value == nil) continue; 196 | 197 | dictionaryValue[key] = value; 198 | } 199 | 200 | NSError *error = nil; 201 | self = [self initWithDictionary:dictionaryValue error:&error]; 202 | if (self == nil) NSLog(@"*** Could not unarchive %@: %@", self.class, error); 203 | 204 | return self; 205 | } 206 | 207 | - (void)encodeWithCoder:(NSCoder *)coder { 208 | if (coderRequiresSecureCoding(coder)) verifyAllowedClassesByPropertyKey(self.class); 209 | 210 | [coder encodeObject:@(self.class.modelVersion) forKey:MTLModelVersionKey]; 211 | 212 | NSDictionary *encodingBehaviors = self.class.encodingBehaviorsByPropertyKey; 213 | [self.dictionaryValue enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { 214 | @try { 215 | // Skip nil values. 216 | if ([value isEqual:NSNull.null]) return; 217 | 218 | switch ([encodingBehaviors[key] unsignedIntegerValue]) { 219 | // This will also match a nil behavior. 220 | case MTLModelEncodingBehaviorExcluded: 221 | break; 222 | 223 | case MTLModelEncodingBehaviorUnconditional: 224 | [coder encodeObject:value forKey:key]; 225 | break; 226 | 227 | case MTLModelEncodingBehaviorConditional: 228 | [coder encodeConditionalObject:value forKey:key]; 229 | break; 230 | 231 | default: 232 | NSAssert(NO, @"Unrecognized encoding behavior %@ on class %@ for key \"%@\"", self.class, encodingBehaviors[key], key); 233 | } 234 | } @catch (NSException *ex) { 235 | NSLog(@"*** Caught exception encoding value for key \"%@\" on class %@: %@", key, self.class, ex); 236 | @throw ex; 237 | } 238 | }]; 239 | } 240 | 241 | #pragma mark NSSecureCoding 242 | 243 | + (BOOL)supportsSecureCoding { 244 | // Disable secure coding support by default, so subclasses are forced to 245 | // opt-in by conforming to the protocol and overriding this method. 246 | // 247 | // We only implement this method because XPC complains if a subclass tries 248 | // to implement it but does not override -initWithCoder:. See 249 | // https://github.com/github/Mantle/issues/74. 250 | return NO; 251 | } 252 | 253 | @end 254 | 255 | @implementation MTLModel (OldArchiveSupport) 256 | 257 | + (NSDictionary *)dictionaryValueFromArchivedExternalRepresentation:(NSDictionary *)externalRepresentation version:(NSUInteger)fromVersion { 258 | return nil; 259 | } 260 | 261 | @end 262 | -------------------------------------------------------------------------------- /Pods/Mantle/Mantle/MTLModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTLModel.m 3 | // Mantle 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-11. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import "NSError+MTLModelException.h" 10 | #import "MTLModel.h" 11 | #import 12 | #import 13 | #import "MTLReflection.h" 14 | #import 15 | 16 | // Used to cache the reflection performed in +propertyKeys. 17 | static void *MTLModelCachedPropertyKeysKey = &MTLModelCachedPropertyKeysKey; 18 | 19 | // Associated in +generateAndCachePropertyKeys with a set of all transitory 20 | // property keys. 21 | static void *MTLModelCachedTransitoryPropertyKeysKey = &MTLModelCachedTransitoryPropertyKeysKey; 22 | 23 | // Associated in +generateAndCachePropertyKeys with a set of all permanent 24 | // property keys. 25 | static void *MTLModelCachedPermanentPropertyKeysKey = &MTLModelCachedPermanentPropertyKeysKey; 26 | 27 | // Validates a value for an object and sets it if necessary. 28 | // 29 | // obj - The object for which the value is being validated. This value 30 | // must not be nil. 31 | // key - The name of one of `obj`s properties. This value must not be 32 | // nil. 33 | // value - The new value for the property identified by `key`. 34 | // forceUpdate - If set to `YES`, the value is being updated even if validating 35 | // it did not change it. 36 | // error - If not NULL, this may be set to any error that occurs during 37 | // validation 38 | // 39 | // Returns YES if `value` could be validated and set, or NO if an error 40 | // occurred. 41 | static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUpdate, NSError **error) { 42 | // Mark this as being autoreleased, because validateValue may return 43 | // a new object to be stored in this variable (and we don't want ARC to 44 | // double-free or leak the old or new values). 45 | __autoreleasing id validatedValue = value; 46 | 47 | @try { 48 | if (![obj validateValue:&validatedValue forKey:key error:error]) return NO; 49 | 50 | if (forceUpdate || value != validatedValue) { 51 | [obj setValue:validatedValue forKey:key]; 52 | } 53 | 54 | return YES; 55 | } @catch (NSException *ex) { 56 | NSLog(@"*** Caught exception setting key \"%@\" : %@", key, ex); 57 | 58 | // Fail fast in Debug builds. 59 | #if DEBUG 60 | @throw ex; 61 | #else 62 | if (error != NULL) { 63 | *error = [NSError mtl_modelErrorWithException:ex]; 64 | } 65 | 66 | return NO; 67 | #endif 68 | } 69 | } 70 | 71 | @interface MTLModel () 72 | 73 | // Inspects all properties of returned by +propertyKeys using 74 | // +storageBehaviorForPropertyWithKey and caches the results. 75 | + (void)generateAndCacheStorageBehaviors; 76 | 77 | // Returns a set of all property keys for which 78 | // +storageBehaviorForPropertyWithKey returned MTLPropertyStorageTransitory. 79 | + (NSSet *)transitoryPropertyKeys; 80 | 81 | // Returns a set of all property keys for which 82 | // +storageBehaviorForPropertyWithKey returned MTLPropertyStoragePermanent. 83 | + (NSSet *)permanentPropertyKeys; 84 | 85 | // Enumerates all properties of the receiver's class hierarchy, starting at the 86 | // receiver, and continuing up until (but not including) MTLModel. 87 | // 88 | // The given block will be invoked multiple times for any properties declared on 89 | // multiple classes in the hierarchy. 90 | + (void)enumeratePropertiesUsingBlock:(void (^)(objc_property_t property, BOOL *stop))block; 91 | 92 | @end 93 | 94 | @implementation MTLModel 95 | 96 | #pragma mark Lifecycle 97 | 98 | + (void)generateAndCacheStorageBehaviors { 99 | NSMutableSet *transitoryKeys = [NSMutableSet set]; 100 | NSMutableSet *permanentKeys = [NSMutableSet set]; 101 | 102 | for (NSString *propertyKey in self.propertyKeys) { 103 | switch ([self storageBehaviorForPropertyWithKey:propertyKey]) { 104 | case MTLPropertyStorageNone: 105 | break; 106 | 107 | case MTLPropertyStorageTransitory: 108 | [transitoryKeys addObject:propertyKey]; 109 | break; 110 | 111 | case MTLPropertyStoragePermanent: 112 | [permanentKeys addObject:propertyKey]; 113 | break; 114 | } 115 | } 116 | 117 | // It doesn't really matter if we replace another thread's work, since we do 118 | // it atomically and the result should be the same. 119 | objc_setAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey, transitoryKeys, OBJC_ASSOCIATION_COPY); 120 | objc_setAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey, permanentKeys, OBJC_ASSOCIATION_COPY); 121 | } 122 | 123 | + (instancetype)modelWithDictionary:(NSDictionary *)dictionary error:(NSError **)error { 124 | return [[self alloc] initWithDictionary:dictionary error:error]; 125 | } 126 | 127 | - (instancetype)init { 128 | // Nothing special by default, but we have a declaration in the header. 129 | return [super init]; 130 | } 131 | 132 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary error:(NSError **)error { 133 | self = [self init]; 134 | if (self == nil) return nil; 135 | 136 | for (NSString *key in dictionary) { 137 | // Mark this as being autoreleased, because validateValue may return 138 | // a new object to be stored in this variable (and we don't want ARC to 139 | // double-free or leak the old or new values). 140 | __autoreleasing id value = [dictionary objectForKey:key]; 141 | 142 | if ([value isEqual:NSNull.null]) value = nil; 143 | 144 | BOOL success = MTLValidateAndSetValue(self, key, value, YES, error); 145 | if (!success) return nil; 146 | } 147 | 148 | return self; 149 | } 150 | 151 | #pragma mark Reflection 152 | 153 | + (void)enumeratePropertiesUsingBlock:(void (^)(objc_property_t property, BOOL *stop))block { 154 | Class cls = self; 155 | BOOL stop = NO; 156 | 157 | while (!stop && ![cls isEqual:MTLModel.class]) { 158 | unsigned count = 0; 159 | objc_property_t *properties = class_copyPropertyList(cls, &count); 160 | 161 | cls = cls.superclass; 162 | if (properties == NULL) continue; 163 | 164 | @onExit { 165 | free(properties); 166 | }; 167 | 168 | for (unsigned i = 0; i < count; i++) { 169 | block(properties[i], &stop); 170 | if (stop) break; 171 | } 172 | } 173 | } 174 | 175 | + (NSSet *)propertyKeys { 176 | NSSet *cachedKeys = objc_getAssociatedObject(self, MTLModelCachedPropertyKeysKey); 177 | if (cachedKeys != nil) return cachedKeys; 178 | 179 | NSMutableSet *keys = [NSMutableSet set]; 180 | 181 | [self enumeratePropertiesUsingBlock:^(objc_property_t property, BOOL *stop) { 182 | NSString *key = @(property_getName(property)); 183 | 184 | if ([self storageBehaviorForPropertyWithKey:key] != MTLPropertyStorageNone) { 185 | [keys addObject:key]; 186 | } 187 | }]; 188 | 189 | // It doesn't really matter if we replace another thread's work, since we do 190 | // it atomically and the result should be the same. 191 | objc_setAssociatedObject(self, MTLModelCachedPropertyKeysKey, keys, OBJC_ASSOCIATION_COPY); 192 | 193 | return keys; 194 | } 195 | 196 | + (NSSet *)transitoryPropertyKeys { 197 | NSSet *transitoryPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey); 198 | 199 | if (transitoryPropertyKeys == nil) { 200 | [self generateAndCacheStorageBehaviors]; 201 | transitoryPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey); 202 | } 203 | 204 | return transitoryPropertyKeys; 205 | } 206 | 207 | + (NSSet *)permanentPropertyKeys { 208 | NSSet *permanentPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey); 209 | 210 | if (permanentPropertyKeys == nil) { 211 | [self generateAndCacheStorageBehaviors]; 212 | permanentPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey); 213 | } 214 | 215 | return permanentPropertyKeys; 216 | } 217 | 218 | - (NSDictionary *)dictionaryValue { 219 | NSSet *keys = [self.class.transitoryPropertyKeys setByAddingObjectsFromSet:self.class.permanentPropertyKeys]; 220 | 221 | return [self dictionaryWithValuesForKeys:keys.allObjects]; 222 | } 223 | 224 | + (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey { 225 | objc_property_t property = class_getProperty(self.class, propertyKey.UTF8String); 226 | 227 | if (property == NULL) return MTLPropertyStorageNone; 228 | 229 | mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); 230 | @onExit { 231 | free(attributes); 232 | }; 233 | 234 | BOOL hasGetter = [self instancesRespondToSelector:attributes->getter]; 235 | BOOL hasSetter = [self instancesRespondToSelector:attributes->setter]; 236 | if (!attributes->dynamic && attributes->ivar == NULL && !hasGetter && !hasSetter) { 237 | return MTLPropertyStorageNone; 238 | } else if (attributes->readonly && attributes->ivar == NULL) { 239 | if ([self isEqual:MTLModel.class]) { 240 | return MTLPropertyStorageNone; 241 | } else { 242 | // Check superclass in case the subclass redeclares a property that 243 | // falls through 244 | return [self.superclass storageBehaviorForPropertyWithKey:propertyKey]; 245 | } 246 | } else { 247 | return MTLPropertyStoragePermanent; 248 | } 249 | } 250 | 251 | #pragma mark Merging 252 | 253 | - (void)mergeValueForKey:(NSString *)key fromModel:(NSObject *)model { 254 | NSParameterAssert(key != nil); 255 | 256 | SEL selector = MTLSelectorWithCapitalizedKeyPattern("merge", key, "FromModel:"); 257 | if (![self respondsToSelector:selector]) { 258 | if (model != nil) { 259 | [self setValue:[model valueForKey:key] forKey:key]; 260 | } 261 | 262 | return; 263 | } 264 | 265 | IMP imp = [self methodForSelector:selector]; 266 | void (*function)(id, SEL, id) = (__typeof__(function))imp; 267 | function(self, selector, model); 268 | } 269 | 270 | - (void)mergeValuesForKeysFromModel:(id)model { 271 | NSSet *propertyKeys = model.class.propertyKeys; 272 | 273 | for (NSString *key in self.class.propertyKeys) { 274 | if (![propertyKeys containsObject:key]) continue; 275 | 276 | [self mergeValueForKey:key fromModel:model]; 277 | } 278 | } 279 | 280 | #pragma mark Validation 281 | 282 | - (BOOL)validate:(NSError **)error { 283 | for (NSString *key in self.class.propertyKeys) { 284 | id value = [self valueForKey:key]; 285 | 286 | BOOL success = MTLValidateAndSetValue(self, key, value, NO, error); 287 | if (!success) return NO; 288 | } 289 | 290 | return YES; 291 | } 292 | 293 | #pragma mark NSCopying 294 | 295 | - (instancetype)copyWithZone:(NSZone *)zone { 296 | MTLModel *copy = [[self.class allocWithZone:zone] init]; 297 | [copy setValuesForKeysWithDictionary:self.dictionaryValue]; 298 | return copy; 299 | } 300 | 301 | #pragma mark NSObject 302 | 303 | - (NSString *)description { 304 | NSDictionary *permanentProperties = [self dictionaryWithValuesForKeys:self.class.permanentPropertyKeys.allObjects]; 305 | 306 | return [NSString stringWithFormat:@"<%@: %p> %@", self.class, self, permanentProperties]; 307 | } 308 | 309 | - (NSUInteger)hash { 310 | NSUInteger value = 0; 311 | 312 | for (NSString *key in self.class.permanentPropertyKeys) { 313 | value ^= [[self valueForKey:key] hash]; 314 | } 315 | 316 | return value; 317 | } 318 | 319 | - (BOOL)isEqual:(MTLModel *)model { 320 | if (self == model) return YES; 321 | if (![model isMemberOfClass:self.class]) return NO; 322 | 323 | for (NSString *key in self.class.permanentPropertyKeys) { 324 | id selfValue = [self valueForKey:key]; 325 | id modelValue = [model valueForKey:key]; 326 | 327 | BOOL valuesEqual = ((selfValue == nil && modelValue == nil) || [selfValue isEqual:modelValue]); 328 | if (!valuesEqual) return NO; 329 | } 330 | 331 | return YES; 332 | } 333 | 334 | @end 335 | --------------------------------------------------------------------------------