├── .travis.yml
├── .gitignore
├── SHModelObject
├── en.lproj
│ └── InfoPlist.strings
├── SHAnotherModel.m
├── main.m
├── SHModelObject-Prefix.pch
├── SHAnotherModel.h
├── SHModelObject
│ ├── SHConstants.h
│ ├── SHModelSerialization.h
│ ├── SHModelObject.h
│ ├── SHRealmObject.h
│ ├── SHModelObject.m
│ └── SHRealmObject.m
├── Images.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── LaunchImage.launchimage
│ │ └── Contents.json
├── SHAppDelegate.h
├── SHTestModal.m
├── SHModelObject-Info.plist
├── SHTestModal.h
└── SHAppDelegate.m
├── Podfile
├── SHModelObjectTests
├── en.lproj
│ └── InfoPlist.strings
├── SHModelObjectTests-Info.plist
└── SHModalObjectTests.m
├── SHModelObject.xcodeproj
├── xcuserdata
│ ├── shanulhaq.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── SHModalObject.xcscheme
│ └── shan.haq.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── SHModelObject.xcscheme
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ ├── shan.haq.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── shanulhaq.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ ├── SHModalObject.xccheckout
│ │ └── SHModelObject.xccheckout
└── project.pbxproj
├── SHModelObject.xcworkspace
├── xcuserdata
│ ├── shanulhaq.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── WorkspaceSettings.xcsettings
│ └── shan.haq.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── contents.xcworkspacedata
└── xcshareddata
│ └── SHModelObject.xccheckout
├── Podfile.lock
├── CHANGELOG.md
├── LICENSE
├── SHModelObject.podspec
└── README.md
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | DerivedData
3 | Build
4 | Pods
--------------------------------------------------------------------------------
/SHModelObject/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '7.0'
2 |
3 | target 'SHModelObject' do
4 | pod 'Realm'
5 | end
6 |
7 |
--------------------------------------------------------------------------------
/SHModelObjectTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/xcuserdata/shanulhaq.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/SHModelObject.xcworkspace/xcuserdata/shanulhaq.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/SHModelObject.xcworkspace/xcuserdata/shan.haq.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grevolution/SHModelObject/HEAD/SHModelObject.xcworkspace/xcuserdata/shan.haq.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/xcuserdata/shan.haq.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grevolution/SHModelObject/HEAD/SHModelObject.xcodeproj/project.xcworkspace/xcuserdata/shan.haq.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/xcuserdata/shanulhaq.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grevolution/SHModelObject/HEAD/SHModelObject.xcodeproj/project.xcworkspace/xcuserdata/shanulhaq.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SHModelObject/SHAnotherModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // SHAnotherModel.m
3 | // SHModelObject
4 | //
5 | // Created by SHAN UL HAQ on 14/3/15.
6 | // Copyright (c) 2015 grevolution. All rights reserved.
7 | //
8 |
9 | #import "SHAnotherModel.h"
10 |
11 | @implementation SHAnotherModel
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SHModelObject.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Realm (1.0.1):
3 | - Realm/Headers (= 1.0.1)
4 | - Realm/Headers (1.0.1)
5 |
6 | DEPENDENCIES:
7 | - Realm
8 |
9 | SPEC CHECKSUMS:
10 | Realm: 2e15e39d35b08abb529e212ed5d8af107b5236c8
11 |
12 | PODFILE CHECKSUM: b1143668b7fe2a332a4de82369d518b567cb9515
13 |
14 | COCOAPODS: 1.0.0
15 |
--------------------------------------------------------------------------------
/SHModelObject/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SHModalObject
4 | //
5 | // Created by SHAN UL HAQ on 23/2/14.
6 | // Copyright (c) 2014 grevolution. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "SHAppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SHAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_3_0
10 | #warning "This project uses features only available in iOS SDK 3.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/SHModelObject.xcworkspace/xcuserdata/shanulhaq.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SHModelObject/SHAnotherModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // SHAnotherModel.h
3 | // SHModelObject
4 | //
5 | // Created by SHAN UL HAQ on 14/3/15.
6 | // Copyright (c) 2015 grevolution. All rights reserved.
7 | //
8 |
9 | #import "SHModelObject.h"
10 |
11 | @interface SHAnotherModel : SHModelObject
12 |
13 | @property (nonatomic) int modelId;
14 | @property (nonatomic, strong) NSString *modelName;
15 | @property (nonatomic, strong) NSString *modelType;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/xcuserdata/shanulhaq.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # `SHModelObject` Changelog
2 |
3 | ## 1.1.1
4 |
5 | 1. addition of new class `SHRealmObject` which is a subclass of `RLMObject` from [Realm](http://realm.io/).
6 |
7 | ## 1.0.8
8 |
9 | ### New Features
10 |
11 | 1. `SHModelObject` now supports automatic parsing of instance variables which are also of type `SHModelObject`
12 | 2. `SHModelObject` now supports parsing arrays of objects which are of type `SHModelObject` based on the mapping provided
13 |
14 | ### Refactoring
15 |
16 | 1. removed the use of mapping dictionary for date conversion. `SHModelObject` parses the dates based on the instance variable types.
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/xcuserdata/shan.haq.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SHModelObject.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | F2B4092C18BA16F400611B29
16 |
17 | primary
18 |
19 |
20 | F2B4094718BA16F500611B29
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/xcuserdata/shanulhaq.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SHModalObject.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | F2B4092C18BA16F400611B29
16 |
17 | primary
18 |
19 |
20 | F2B4094718BA16F500611B29
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SHModelObjectTests/SHModelObjectTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.grevolution.shmodalobject.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SHModelObjectTests/SHModalObjectTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // SHModalObjectTests.m
3 | // SHModalObjectTests
4 | //
5 | // Created by SHAN UL HAQ on 23/2/14.
6 | // Copyright (c) 2014 grevolution. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SHModalObjectTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation SHModalObjectTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
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 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHConstants.h:
--------------------------------------------------------------------------------
1 | //
2 | // SHConstants.h
3 | // SHModelObject
4 | //
5 | // Created by SHAN UL HAQ on 4/4/15.
6 | // Copyright (c) 2015 grevolution. All rights reserved.
7 | //
8 |
9 | #ifndef SHModelObject_SHConstants_h
10 | #define SHModelObject_SHConstants_h
11 |
12 | /**
13 | * Date option conversion enum to be passed to the serializer constructer
14 | */
15 | typedef enum {
16 | kDateConverstionFromNSStringToNSStringOption = 0, // do not convert, keep NSString as it is.
17 | kDateConverstionFromNSStringToNSDateOption = 1, // convert NSString to NSDate
18 | kDateConverstionFromNSStringToNSTimeIntervalOption = 2 // convert NSString to NSTimeInterval
19 | } kDateConversionOption;
20 |
21 | /**
22 | * enum for identifying the input date type.
23 | */
24 | typedef NS_ENUM(int, kInputDateFormat) {
25 | kInputDateFormatJSON = 1,
26 | kInputDateFormatDotNetSimple = 2,
27 | kInputDateFormatDotNetWithTimeZone = 3,
28 | kInputDateFormatCustom = -1,
29 | };
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/SHModelObject/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" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "29x29",
21 | "scale" : "1x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "29x29",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "ipad",
30 | "size" : "40x40",
31 | "scale" : "1x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "40x40",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "76x76",
41 | "scale" : "1x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "76x76",
46 | "scale" : "2x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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.
--------------------------------------------------------------------------------
/SHModelObject/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | },
18 | {
19 | "orientation" : "portrait",
20 | "idiom" : "ipad",
21 | "extent" : "full-screen",
22 | "minimum-system-version" : "7.0",
23 | "scale" : "1x"
24 | },
25 | {
26 | "orientation" : "landscape",
27 | "idiom" : "ipad",
28 | "extent" : "full-screen",
29 | "minimum-system-version" : "7.0",
30 | "scale" : "1x"
31 | },
32 | {
33 | "orientation" : "portrait",
34 | "idiom" : "ipad",
35 | "extent" : "full-screen",
36 | "minimum-system-version" : "7.0",
37 | "scale" : "2x"
38 | },
39 | {
40 | "orientation" : "landscape",
41 | "idiom" : "ipad",
42 | "extent" : "full-screen",
43 | "minimum-system-version" : "7.0",
44 | "scale" : "2x"
45 | }
46 | ],
47 | "info" : {
48 | "version" : 1,
49 | "author" : "xcode"
50 | }
51 | }
--------------------------------------------------------------------------------
/SHModelObject/SHAppDelegate.h:
--------------------------------------------------------------------------------
1 | // SHAppDelegate.h
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import
24 |
25 | @interface SHAppDelegate : UIResponder
26 |
27 | @property (strong, nonatomic) UIWindow *window;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/SHModelObject/SHTestModal.m:
--------------------------------------------------------------------------------
1 | // SHTestModal.m
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import "SHTestModal.h"
24 |
25 | @implementation SHTestModal
26 |
27 | - (void)serializeValue:(id)value withKey:(id)key
28 | {
29 | if([key isEqualToString:@"numberVALUE"]) {
30 | _numberValue = value;
31 | NSLog(@"did it for _numberValue : %@", _numberValue);
32 | } else {
33 | [super serializeValue:value withKey:key];
34 | }
35 | }
36 |
37 | @end
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.grevolution.shmodalobject.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0.8
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0.8
25 | LSRequiresIPhoneOS
26 |
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SHModelObject.xcworkspace/xcshareddata/SHModelObject.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 1D5875E1-22CF-45BC-B76F-5E8523155564
9 | IDESourceControlProjectName
10 | SHModelObject
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
14 | github.com:grevolution/SHModelObject.git
15 |
16 | IDESourceControlProjectPath
17 | SHModelObject.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
21 | ..
22 |
23 | IDESourceControlProjectURL
24 | github.com:grevolution/SHModelObject.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
36 | IDESourceControlWCCName
37 | SHModelObject
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/xcshareddata/SHModalObject.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | FC166833-3A12-4E9C-940B-26BBE2FD9049
9 | IDESourceControlProjectName
10 | SHModalObject
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 6A161B01-FC15-4A74-B068-2C490C0C2C68
14 | https://github.com/grevolution/SHModalObject.git
15 |
16 | IDESourceControlProjectPath
17 | SHModalObject.xcodeproj/project.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 6A161B01-FC15-4A74-B068-2C490C0C2C68
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/grevolution/SHModalObject.git
25 | IDESourceControlProjectVersion
26 | 110
27 | IDESourceControlProjectWCCIdentifier
28 | 6A161B01-FC15-4A74-B068-2C490C0C2C68
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 6A161B01-FC15-4A74-B068-2C490C0C2C68
36 | IDESourceControlWCCName
37 | SHModalObject
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.xcworkspace/xcshareddata/SHModelObject.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | BBC6A4B8-4768-465C-B90C-4197CE7B15FD
9 | IDESourceControlProjectName
10 | SHModelObject
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
14 | https://github.com/grevolution/SHModelObject.git
15 |
16 | IDESourceControlProjectPath
17 | SHModelObject.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/grevolution/SHModelObject.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | B5D04170A948972EE1EFA3B27A34E674C9EF57CA
36 | IDESourceControlWCCName
37 | SHModelObject
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SHModelObject.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "SHModelObject"
3 | s.version = "1.1.9"
4 |
5 | s.summary = "`SHModelObject` a utility class that reads NSDictionary and populates the instance variables and properties automatically."
6 |
7 | s.description = <<-DESC
8 | `SHModelObject` is a utility Modal Base Class that uses objective-c runtime to assign
9 | the values to instance variables and properties of the model class from an `NSDictionary`,
10 | Which is a basic usecase when using webservices that return JSON response.
11 | DESC
12 |
13 | s.homepage = "https://github.com/grevolution/SHModelObject"
14 | s.license = {:type => 'MIT'}
15 | s.author = { "Shan Ul Haq" => "g@grevolution.me" }
16 |
17 | s.platform = :ios, '7.0'
18 | s.source = { :git => "https://github.com/grevolution/SHModelObject.git", :tag => s.version }
19 |
20 | s.requires_arc = true
21 | #s.source_files = 'SHModelObject/SHModelObject/*.{h,m}'
22 | #s.exclude_files = 'Classes/Exclude'
23 | #s.dependency 'Realm'
24 |
25 | s.subspec 'Core' do |core|
26 | core.source_files = 'SHModelObject/SHModelObject/SHModelObject.{h,m}' , 'SHModelObject/SHModelObject/SHConstants.h' ,
27 | 'SHModelObject/SHModelObject/SHModelSerialization.h'
28 | core.exclude_files = 'SHModelObject/SHModelObject/SHRealmObject.{h,m}'
29 | core.platform = :ios
30 | end
31 |
32 | s.subspec 'Realm' do |realm|
33 | realm.source_files = 'SHModelObject/SHModelObject/SHRealmObject.{h,m}' , 'SHModelObject/SHModelObject/SHConstants.h' , 'SHModelObject/SHModelObject/SHModelSerialization.h'
34 | realm.platform = :ios, '7.0'
35 | realm.exclude_files = 'SHModelObject/SHModelObject/SHModelObject.{h,m}'
36 | realm.dependency 'Realm'
37 | end
38 |
39 | end
40 |
--------------------------------------------------------------------------------
/SHModelObject/SHTestModal.h:
--------------------------------------------------------------------------------
1 | // SHTestModal.h
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import "SHModelObject.h"
24 |
25 | @class SHAnotherModel;
26 |
27 | @interface SHTestModal : SHModelObject
28 |
29 | {
30 | NSString *_anotherStringValue;
31 | NSNumber *_intValue;
32 | NSInteger _integerValue;
33 | NSNumber *_numberValue;
34 | BOOL _remember;
35 | NSString *_doItMySelf;
36 |
37 | NSMutableArray *_myArray;
38 | NSMutableDictionary *_myDictionary;
39 | NSDate *time1;
40 | }
41 |
42 | @property (nonatomic, strong) NSString *stringValue;
43 | @property (nonatomic) int anotherIntValue;
44 | @property (nonatomic) NSInteger anotherIntegerValue;
45 | @property (nonatomic, strong) NSNumber *anotherNumberValue;
46 | @property (nonatomic, strong) SHAnotherModel *anotherModel;
47 | @property (nonatomic, strong) NSArray *arrayOfAnotherModels;
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHModelSerialization.h:
--------------------------------------------------------------------------------
1 | // SHModalSerialization.h
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import
24 |
25 | /**
26 | * The `SHModalSerialization` protocol is adopted by any class that will then implement how to serialize the key/value
27 | * pair passed to the class.
28 | */
29 | @protocol SHModelSerialization
30 |
31 | /**
32 | * This method will be implemented by the class that adopts this protocol and will define the logic for how to
33 | * serialize the key/value pair passed to the method. the overridden method must call [super serializeValue: withKey:]
34 | * to impelement the default logic for serialization for a specific key/value pair if it choose not to do any specific
35 | * implementation.
36 | *
37 | * @param value The value object from the NSDictionary object passed to the class
38 | * @param key The key object from the NSDictionary object passed to the class
39 | *
40 | */
41 | - (void) serializeValue:(id)value withKey:(id)key;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/xcuserdata/shan.haq.xcuserdatad/xcschemes/SHModelObject.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/xcuserdata/shanulhaq.xcuserdatad/xcschemes/SHModalObject.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/SHModelObject/SHAppDelegate.m:
--------------------------------------------------------------------------------
1 | // SHAppDelegate.m
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import "SHAppDelegate.h"
24 | #import "SHTestModal.h"
25 | #import "SHRealmObject.h"
26 | #import
27 | #import
28 |
29 | @class Car;
30 |
31 | RLM_ARRAY_TYPE(Car)
32 |
33 | @interface Person : SHRealmObject
34 | @property NSString *name;
35 | @property int age;
36 | @property RLMArray *cars;
37 | @end
38 |
39 | @implementation Person
40 | @end
41 |
42 | @interface Car : SHRealmObject
43 | @property NSString *model;
44 | @end
45 |
46 | @implementation Car
47 | @end
48 |
49 | @implementation SHAppDelegate
50 |
51 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
52 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
53 | // Override point for customization after application launch.
54 | self.window.backgroundColor = [UIColor whiteColor];
55 | [self.window makeKeyAndVisible];
56 | NSDictionary *aDictionary = @{
57 | @"string_value" : @"shan",
58 | @"another_string_value" : @"ul haq",
59 | @"INTVALUE" : @12,
60 | @"AnotherIntValue" : @23,
61 | @"integerValue" : @78,
62 | @"another_integer_value" : @98,
63 | @"numberVALUE" : @YES,
64 | @"another_numberVALUE" : @NO,
65 | @"remember" : @(false),
66 | @"do_it_my_self" : @"Yahooo",
67 | @"myArray" : @[ @"one", @2, @NO, @"four" ],
68 | @"_my_dictionary" : @{@"name" : @"correct name"},
69 | @"time1" : @"2014-04-11T23:59:00+08:00",
70 | @"time2" : @"2014-04-11T23:59:00+08:00",
71 | @"time3" : @"2014-04-11T23:59:00+08:00",
72 | @"anotherModel" : @{@"modelId" : @1, @"modelName" : @"My Model", @"modelType" : @"My Model Type"},
73 | @"arrayOfAnotherModels" : @[
74 | @{@"modelId" : @2, @"modelName" : @"My Model 2", @"modelType" : @"My Model Type 2"},
75 | @{@"modelId" : @3, @"modelName" : @"My Model 3", @"modelType" : @"My Model Type 3"},
76 | @{@"modelId" : @4, @"modelName" : @"My Model 4", @"modelType" : @"My Model Type 4"}
77 | ]
78 | };
79 |
80 | NSDictionary *mapping = @{ @"arrayOfAnotherModels" : @"SHAnotherModel" };
81 |
82 | SHTestModal *model = [SHTestModal objectWithDictionary:aDictionary
83 | dateConversionOption:kDateConverstionFromNSStringToNSTimeIntervalOption
84 | inputDateType:kInputDateFormatDotNetWithTimeZone
85 | mappings:mapping];
86 |
87 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
88 | NSString *documentsDirectoryPath = [paths objectAtIndex:0];
89 | NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:@"appData"];
90 |
91 | BOOL isArchived = [NSKeyedArchiver archiveRootObject:model toFile:filePath];
92 | SHTestModal *unarchived = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
93 |
94 | NSLog([model description], nil);
95 | NSLog([unarchived description], nil);
96 |
97 | // realm testing
98 | [[NSFileManager defaultManager] removeItemAtURL:[[[RLMRealm defaultRealm] configuration] fileURL] error:nil];
99 | RLMRealm *realm = [RLMRealm defaultRealm];
100 | [realm transactionWithBlock:^{
101 | NSDictionary *d = @{
102 | @"nAme" : @"Shan Ul Haq",
103 | @"_AGE" : @26,
104 | @"cars" : @[ @{@"moDEL" : @"Honda"}, @{@"model" : @"Toyota"} ]
105 | };
106 | Person *p = [Person objectWithDictionary:d mappings:@{ @"cars" : @"Car" }];
107 | [realm addObject:p];
108 | }];
109 |
110 | // Log all dogs and their owners using the "owners" inverse relationship
111 | RLMResults *allPersons = [Person allObjects];
112 | for (Person *person in allPersons) {
113 | NSLog(@" person name : %@", person.name);
114 | }
115 |
116 | // Log all dogs and their owners using the "owners" inverse relationship
117 | RLMResults *allCars = [Car allObjects];
118 | for (Car *car in allCars) {
119 | NSLog(@"car model : %@", car.model);
120 | }
121 |
122 | return YES;
123 | }
124 |
125 | - (void)applicationWillResignActive:(UIApplication *)application {
126 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of
127 | // temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application
128 | // and it begins the transition to the background state.
129 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use
130 | // this method to pause the game.
131 | }
132 |
133 | - (void)applicationDidEnterBackground:(UIApplication *)application {
134 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application
135 | // state information to restore your application to its current state in case it is terminated later.
136 | // If your application supports background execution, this method is called instead of applicationWillTerminate:
137 | // when the user quits.
138 | }
139 |
140 | - (void)applicationWillEnterForeground:(UIApplication *)application {
141 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes
142 | // made on entering the background.
143 | }
144 |
145 | - (void)applicationDidBecomeActive:(UIApplication *)application {
146 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application
147 | // was previously in the background, optionally refresh the user interface.
148 | }
149 |
150 | - (void)applicationWillTerminate:(UIApplication *)application {
151 | // Called when the application is about to terminate. Save data if appropriate. See also
152 | // applicationDidEnterBackground:.
153 | }
154 |
155 | @end
156 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SHModelObject
2 | =============
3 |
4 | `SHModelObject` is a utility model Base Class that uses objective-c runtime to assign the values to instance variables and properties of the model class from an `NSDictionary`, Which is a basic usecase when using webservices that return JSON response.
5 |
6 | [](https://travis-ci.org/grevolution/SHModelObject) [](https://img.shields.io/cocoapods/v/SHModelObject.svg) [](https://img.shields.io/cocoapods/l/SHModelObject.svg)
7 |
8 | Let say you have a WebService that serves you back the following Response:
9 |
10 | ```json
11 | {
12 | "user_name" : "Shan Ul Haq",
13 | "user_id" : 34567,
14 | "user_role" : "Author",
15 | "user_x_values" : [
16 | "abcd", 777, "efgh" , true, false
17 | ]
18 | }
19 | ```
20 |
21 | You parse this response using a JSON library and convert this response into a NSDictionary. Now another task is to populate following User model Object
22 |
23 | ```objective-c
24 | @interface User : NSObject {
25 | NSString *_userName;
26 | NSInteger _userId;
27 | NSString *userRole;
28 | }
29 |
30 | @property(nonatomic, strong) NSArray *userXValues;
31 |
32 | @end
33 | ```
34 |
35 | To populate an Object of User, you will have to write some initializer that will take a NSDictionary and will populate the `ivars` and `properties` of your model class one by one. and you will have to do this
36 | for all the model classes that you have in your project. you will be adding something like below to your class and implement the method.
37 |
38 | - (User *)initWithDictionary:(NSDictionary *)responseDictionary;
39 |
40 | Thats where `SHModelObject` comes in, its a Single class with basic purpose to reduce this effort and do the work for you. all you have to do is `subclass` your model class with `SHModelObject`, so the above class becomes:
41 |
42 |
43 | ```objective-c
44 | @interface User : SHModelObject {
45 | NSString *_userName;
46 | NSInteger _userId;
47 | NSString *userRole;
48 | }
49 |
50 | @property(nonatomic, strong) NSArray *userXValues;
51 |
52 | @end
53 | ```
54 |
55 | and thats it. `SHModelObject` has a basic initializer that will take the NSDictionary and will populate all the `ivars` and `properties` for you.
56 |
57 | just initialize the model with provided initializers and off you go.
58 |
59 | User *u = [[User alloc] initWithDictionary:responseDictionary];
60 |
61 | ##How `SHModelObject` knows which value to assing to which instance variable?
62 |
63 | SHModelObject compares the keys of NSDictionary with the `ivar` or `property` names in an efficient way. while comparing the names of keys with ivars it doesnt take `_`, `-` or ` ` into account (also the case doesnt matter). so
64 |
65 | `user_name` OR `USER_NAME` OR `USERNAME` OR `UserName` will match with `_userName` OR `userName` OR `UserName`
66 |
67 | you can override `- (void)serializeValue:(id)value withKey:(id)key` method if you want to a custom logic to parse a specific key/value pair. make sure to call [super serializeValue] for the values you want to parse by default.
68 |
69 | ```objective-c
70 | - (void)serializeValue:(id)value withKey:(id)key
71 | {
72 | if([key isEqualToString:@"numberVALUE"]) {
73 | _numberValue = value;
74 | } else {
75 | [super serializeValue:value withKey:key];
76 | }
77 | }
78 | ```
79 |
80 | ##Parsing .NET JSON Dates to NSDate or NSTimeInterval
81 |
82 | you can use `kDateConversionOption` to convert the .NET JSON Date Strings to either `NSDate` or `NSTimeInterval` or keep it as `NSString` and parse yourself and also you can define `kInputDateFormat` to specify your input date format (JSON format, .NET Simple or .NET with timezone)
83 |
84 |
85 | ##Parsing instance variables which are also a subclass of `SHModelObject`
86 |
87 | you dont have to do anything :). `SHModelObject` automatically handles it. checkout the sample code.
88 |
89 | for example, following JSON
90 |
91 | ```json
92 |
93 | {
94 | "name" : "Shan Ul Haq",
95 | "person_id" : 123,
96 | "image" : {
97 | "image_id" : 234,
98 | "image_url" : "http://image_url",
99 | "orientation" : "portrait"
100 | }
101 | }
102 |
103 | ```
104 | will be automatically parsed into following object:
105 |
106 | ```objective-c
107 | @interface Person : SHModelObject
108 |
109 | @property(nonatomic, strong) NSString *name;
110 | @property(nonatomic) int personId;
111 | @property(nonatomic, strong) Image *image;
112 |
113 | @end
114 | ```
115 | where Image object is also a `SHModelObject`
116 |
117 | ```objective-c
118 | @interface Image : SHModelObject
119 |
120 | @property(nonatomic) int imageId;
121 | @property(nonatomic, strong) NSString *imageUrl;
122 | @property(nonatomic, strong) NSString *orientation;
123 |
124 | @end
125 | ```
126 |
127 | ###Parsing arrays of objects which are a subclass of `SHModelObject`
128 |
129 | similar to parsing `SHModelObject` instance variables, arrays can be handled too. you need to specify the mapping which will define that the JSON array consist of which object type.
130 |
131 | for example, if you have following JSON
132 |
133 | ```json
134 | {
135 | "aKey" : "aValue",
136 | "arrayOfModels" : [
137 | {
138 | "modelId" : 2,
139 | "modelName" : "My Model 2",
140 | "modelType" : "My Model Type 2"
141 | },{
142 | "modelId" : 3,
143 | "modelName" : "My Model 3",
144 | "modelType" : "My Model Type 3"
145 | },{
146 | "modelId" : 4,
147 | "modelName" : "My Model 4",
148 | "modelType" : "My Model Type 4"
149 | }
150 | ]
151 | }
152 | }
153 | ```
154 |
155 | which translates to following objects.
156 |
157 | ```objective-c
158 | @interface MyObject : SHModelObject
159 |
160 | @property(nonatomic, strong) NSString *aKey;
161 | @property(nonatomic, strong) NSArray *arrayOfModels;
162 |
163 | @end
164 |
165 | @interface AModel : SHModelObject
166 |
167 | @property(nonatomic) int modelId;
168 | @property(nonatomic, strong) NSString *modelName;
169 | @property(nonatomic, strong) NSString *modelType;
170 |
171 | @end
172 | ```
173 |
174 | you can convert json like this:
175 |
176 | ```objective-c
177 | // key is the variable name and value is the class name.
178 | NSDictionary *mappingDictionary = @{@"arrayOfModels" : "AModel"};
179 |
180 | MyObject *myObject = [MyObject objectWithDictionary:dictionary mapping:mappingDictionary];
181 |
182 | ```
183 |
184 | ##SHRealmObject
185 |
186 | [Realm](http://realm.io/) support out of the box. `SHRealmObject` is a sublclass of `RLMObject` from Realm. If you want to use both SHModelObject to parse your JSON responses and have RLMObject to be used with Realm database. `SHRealmObject` is they class you need.
187 |
188 | `SHRealmObject` is identical in functionality as `SHModelObject` but also confirms with `RLMObject`. that means the it also confirms with the restriction that `RLMObject` class has. (e.g. you cannot use `NSDictionary` objects. and instead of using `NSArrays` you will use `RLMArray` objects).
189 |
190 | `RLMArray` objects will also be parsed automatically for you based on the mapping dictionary provided. (check out parsing arrays section above)
191 |
192 | Following is a simple example.
193 |
194 |
195 | ```objective-c
196 | @interface Person : SHRealmObject
197 |
198 | @property NSString *name;
199 | @property int age;
200 | @property RLMArray *cars;
201 |
202 | @end
203 |
204 | @implementation Person
205 | @end
206 |
207 | ////
208 |
209 | @interface Car : SHRealmObject
210 | @property NSString *model;
211 | @end
212 |
213 | @implementation Car
214 | @end
215 | ```
216 |
217 | and to add an object in Realm database.
218 |
219 | ```objective-c
220 | RLMRealm *realm = [RLMRealm defaultRealm];
221 | [realm transactionWithBlock:^{
222 | NSDictionary *d = @{
223 | @"nAme" : @"Shan Ul Haq",
224 | @"_AGE" : @26,
225 | @"cars" : @[ @{@"moDEL" : @"Honda"}, @{@"model" : @"Toyota"} ]
226 | };
227 | Person *p = [Person objectWithDictionary:d mappings:@{ @"cars" : @"Car" }];
228 | [realm addObject:p];
229 | }];
230 | ```
231 |
232 |
233 | ##How to Use it.
234 |
235 | 1- add the files
236 |
237 | **Using Cocoapods**
238 |
239 | - add `pod 'SHModelObject/Core'` in your Podfile if you just want to use `SHModelObject`
240 | - add `pod 'SHModelObject/Realm'` in your Podfile if you want to use `SHRealmObject` with Realm.
241 | - add `pod 'SHModelObject'` in your Podfile if you want to use both `SHModelObject` and `SHRealmObject`.
242 |
243 | **Manual**
244 |
245 | - Just add the classes into your project.
246 |
247 | 2- sublcass your models with `SHModelObject` or `SHRealmObject`
248 |
249 | 3- initialize using the povided initializers and pass the response NSDictionary ( initWithDictionary: and other variants )
250 |
251 | 4- override `serializeValue` if you want to parse a specific key/value your way.
252 |
253 | 5- thats it. off you go.
254 |
255 | ##Tasks Pending
256 |
257 | - [X] adding to cocoapods.
258 | - [X] adding support for custom instance variable types that are also subclasses of `SHModelObject`
259 | - [X] implementing `NSCoding` for archiving/unarchiving the model objects.
260 | - [X] adding support for handling arrays of custom `SHModelObject` objects.
261 | - [ ] implementing a deserializer for converting the object to NSDictionary.
262 |
263 | ##Contact Me
264 |
265 | Shan Ul Haq (http://grevolution.me)
266 |
267 | - g@grevolution.me
268 |
269 | - http://twitter.com/gfg5tek
270 |
271 | - http://sg.linkedin.com/in/grevolution/
272 |
273 | ##License
274 |
275 | `SHModelObject` is available under the MIT license. See the LICENSE file for more info.
276 |
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHModelObject.h:
--------------------------------------------------------------------------------
1 | // SHModelObject.h
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import
24 | #import "SHModelSerialization.h"
25 | #import "SHConstants.h"
26 |
27 | /**
28 | * The `SHModelObject` is a base class that uses objective-c runtime to populate a modal class instance variables
29 | * by passing a NSDictionary to it. The NSDictionary key is compared with the instance variable name and the value is
30 | * populated to the variable.
31 | */
32 | @interface SHModelObject : NSObject
33 |
34 | /**
35 | * class initializer
36 | *
37 | * @param dictionary dictionary containing key/value pairs for the object
38 | *
39 | * @return object of type instancetype populated with the values from `dictionary`
40 | */
41 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
42 |
43 | /**
44 | * class initializer
45 | *
46 | * @param dictionary dictionary containing key/value pairs for the object
47 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
48 | *type.
49 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
50 | *
51 | * @return object of type instancetype populated with the values from `dictionary`
52 | */
53 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
54 | dateConversionOption:(kDateConversionOption)option
55 | inputDateType:(kInputDateFormat)inputDateType
56 | mappings:(NSDictionary *)mapping;
57 |
58 | /**
59 | * class initializer
60 | *
61 | * @param dictionary dictionary containing key/value pairs for the object
62 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
63 | *type.
64 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
65 | *the systemTimeZone to create the formatter
66 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
67 | *
68 | * @return object of type instancetype populated with the values from `dictionary`
69 | */
70 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
71 | dateConversionOption:(kDateConversionOption)option
72 | inputDateFormat:(NSString *)inputDateFormat
73 | mappings:(NSDictionary *)mapping;
74 |
75 | /**
76 | * class initializer
77 | *
78 | * @param dictionary dictionary containing key/value pairs for the object
79 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
80 | *type.
81 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
82 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
83 | *
84 | * @return object of type instancetype populated with the values from `dictionary`
85 | */
86 |
87 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
88 | dateConversionOption:(kDateConversionOption)option
89 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
90 | mappings:(NSDictionary *)mapping;
91 |
92 | /**
93 | * static variant of class initializer with nil check for the dictionary passed
94 | *
95 | * @param dictionary dictionary containing key/value pairs for the object
96 | *
97 | * @return object of type instancetype populated with the values from `dictionary`
98 | */
99 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary;
100 |
101 | /**
102 | * static variant of class initializer with nil check for the dictionary passed and mapping dictionary
103 | * this will use the default date conversion options (kDateConverstionFromNSStringToNSStringOption and
104 | * kInputDateFormatJSON)
105 | *
106 | * @param dictionary dictionary containing key/value pairs for the object
107 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
108 | *
109 | * @return object of type instancetype populated with the values from `dictionary`
110 | */
111 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary mappings:(NSDictionary *)mapping;
112 |
113 | /**
114 | * static variant of class initializer with nil check for the dictionary passed
115 | *
116 | * @param dictionary dictionary containing key/value pairs for the object
117 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
118 | *type.
119 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
120 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
121 | *
122 | * @return object of type instancetype populated with the values from `dictionary`
123 | */
124 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
125 | dateConversionOption:(kDateConversionOption)option
126 | inputDateType:(kInputDateFormat)inputDateType
127 | mappings:(NSDictionary *)mapping;
128 |
129 | /**
130 | * static variant of class initializer with nil check for the dictionary passed
131 | *
132 | * @param dictionary dictionary containing key/value pairs for the object
133 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
134 | *type.
135 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
136 | *the systemTimeZone to create the formatter
137 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
138 | *
139 | * @return object of type instancetype populated with the values from `dictionary`
140 | */
141 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
142 | dateConversionOption:(kDateConversionOption)option
143 | inputDateFormat:(NSString *)inputDateFormat
144 | mappings:(NSDictionary *)mapping;
145 |
146 | /**
147 | * static variant of class initializer with nil check for the dictionary passed
148 | *
149 | * @param dictionary dictionary containing key/value pairs for the object
150 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
151 | *type.
152 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
153 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
154 | *
155 | * @return object of type instancetype populated with the values from `dictionary`
156 | */
157 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
158 | dateConversionOption:(kDateConversionOption)option
159 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
160 | mappings:(NSDictionary *)mapping;
161 |
162 | /**
163 | * update the instance with new dictionary values
164 | *
165 | * @param dictionary dictionary containing key/value pairs for the object
166 | *
167 | * @return object of type instancetype populated with the values from `dictionary`
168 | */
169 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary;
170 |
171 | /**
172 | * update the instance with new dictionary values
173 | *
174 | * @param dictionary dictionary containing key/value pairs for the object
175 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
176 | *type.
177 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
178 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
179 | *
180 | * @return object of type instancetype populated with the values from `dictionary`
181 | */
182 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
183 | dateConversionOption:(kDateConversionOption)option
184 | inputDateType:(kInputDateFormat)inputDateType
185 | mappings:(NSDictionary *)mapping;
186 |
187 | /**
188 | * update the instance with new dictionary values
189 | *
190 | * @param dictionary dictionary containing key/value pairs for the object
191 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
192 | *type.
193 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
194 | *the systemTimeZone to create the formatter
195 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
196 | *
197 | * @return object of type instancetype populated with the values from `dictionary`
198 | */
199 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
200 | dateConversionOption:(kDateConversionOption)option
201 | inputDateFormat:(NSString *)inputDateFormat
202 | mappings:(NSDictionary *)mapping;
203 |
204 | /**
205 | * update the instance with new dictionary values
206 | *
207 | * @param dictionary dictionary containing key/value pairs for the object
208 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
209 | *type.
210 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
211 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
212 | *
213 | * @return object of type instancetype populated with the values from `dictionary`
214 | */
215 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
216 | dateConversionOption:(kDateConversionOption)option
217 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
218 | mappings:(NSDictionary *)mapping;
219 |
220 | @end
221 |
222 | @interface NSString (Additions)
223 |
224 | - (BOOL)contains:(NSString *)needle;
225 |
226 | @end
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHRealmObject.h:
--------------------------------------------------------------------------------
1 | // SHRealmObject.h
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import
24 | #import "SHModelSerialization.h"
25 | #import
26 | #import "SHConstants.h"
27 |
28 | /**
29 | * The `SHRealmObject` is a base class that uses objective-c runtime to populate a modal class instance variables
30 | * by passing a NSDictionary to it. The NSDictionary key is compared with the instance variable name and the value is
31 | * populated to the variable.
32 | */
33 | @interface SHRealmObject : RLMObject
34 |
35 | /**
36 | * class initializer
37 | *
38 | * @param dictionary dictionary containing key/value pairs for the object
39 | *
40 | * @return object of type instancetype populated with the values from `dictionary`
41 | */
42 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
43 |
44 | /**
45 | * class initializer
46 | *
47 | * @param dictionary dictionary containing key/value pairs for the object
48 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
49 | *type.
50 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
51 | *
52 | * @return object of type instancetype populated with the values from `dictionary`
53 | */
54 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
55 | dateConversionOption:(kDateConversionOption)option
56 | inputDateType:(kInputDateFormat)inputDateType
57 | mappings:(NSDictionary *)mapping;
58 |
59 | /**
60 | * class initializer
61 | *
62 | * @param dictionary dictionary containing key/value pairs for the object
63 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
64 | *type.
65 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
66 | *the systemTimeZone to create the formatter
67 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
68 | *
69 | * @return object of type instancetype populated with the values from `dictionary`
70 | */
71 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
72 | dateConversionOption:(kDateConversionOption)option
73 | inputDateFormat:(NSString *)inputDateFormat
74 | mappings:(NSDictionary *)mapping;
75 |
76 | /**
77 | * class initializer
78 | *
79 | * @param dictionary dictionary containing key/value pairs for the object
80 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
81 | *type.
82 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
83 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
84 | *
85 | * @return object of type instancetype populated with the values from `dictionary`
86 | */
87 |
88 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
89 | dateConversionOption:(kDateConversionOption)option
90 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
91 | mappings:(NSDictionary *)mapping;
92 |
93 |
94 | /**
95 | * static variant of class initializer with nil check for the dictionary passed
96 | *
97 | * @param dictionary dictionary containing key/value pairs for the object
98 | *
99 | * @return object of type instancetype populated with the values from `dictionary`
100 | */
101 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary;
102 |
103 | /**
104 | * static variant of class initializer with nil check for the dictionary passed and mapping dictionary
105 | * this will use the default date conversion options (kDateConverstionFromNSStringToNSStringOption and
106 | * kInputDateFormatJSON)
107 | *
108 | * @param dictionary dictionary containing key/value pairs for the object
109 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
110 | *
111 | * @return object of type instancetype populated with the values from `dictionary`
112 | */
113 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary mappings:(NSDictionary *)mapping;
114 |
115 | /**
116 | * static variant of class initializer with nil check for the dictionary passed
117 | *
118 | * @param dictionary dictionary containing key/value pairs for the object
119 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
120 | *type.
121 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
122 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
123 | *
124 | * @return object of type instancetype populated with the values from `dictionary`
125 | */
126 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
127 | dateConversionOption:(kDateConversionOption)option
128 | inputDateType:(kInputDateFormat)inputDateType
129 | mappings:(NSDictionary *)mapping;
130 |
131 | /**
132 | * static variant of class initializer with nil check for the dictionary passed
133 | *
134 | * @param dictionary dictionary containing key/value pairs for the object
135 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
136 | *type.
137 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
138 | *the systemTimeZone to create the formatter
139 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
140 | *
141 | * @return object of type instancetype populated with the values from `dictionary`
142 | */
143 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
144 | dateConversionOption:(kDateConversionOption)option
145 | inputDateFormat:(NSString *)inputDateFormat
146 | mappings:(NSDictionary *)mapping;
147 |
148 | /**
149 | * static variant of class initializer with nil check for the dictionary passed
150 | *
151 | * @param dictionary dictionary containing key/value pairs for the object
152 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
153 | *type.
154 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
155 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
156 | *
157 | * @return object of type instancetype populated with the values from `dictionary`
158 | */
159 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
160 | dateConversionOption:(kDateConversionOption)option
161 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
162 | mappings:(NSDictionary *)mapping;
163 |
164 |
165 | /**
166 | * update the instance with new dictionary values
167 | *
168 | * @param dictionary dictionary containing key/value pairs for the object
169 | *
170 | * @return object of type instancetype populated with the values from `dictionary`
171 | */
172 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary;
173 |
174 | /**
175 | * update the instance with new dictionary values
176 | *
177 | * @param dictionary dictionary containing key/value pairs for the object
178 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
179 | *type.
180 | * @param inputDateType `kInputDateFormat` to determine what what is the input format of the date.
181 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
182 | *
183 | * @return object of type instancetype populated with the values from `dictionary`
184 | */
185 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
186 | dateConversionOption:(kDateConversionOption)option
187 | inputDateType:(kInputDateFormat)inputDateType
188 | mappings:(NSDictionary *)mapping;
189 |
190 | /**
191 | * update the instance with new dictionary values
192 | *
193 | * @param dictionary dictionary containing key/value pairs for the object
194 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
195 | *type.
196 | * @param inputDateFormat NSDateFormatter format specifier which will be used to format the input date. this will use
197 | *the systemTimeZone to create the formatter
198 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
199 | *
200 | * @return object of type instancetype populated with the values from `dictionary`
201 | */
202 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
203 | dateConversionOption:(kDateConversionOption)option
204 | inputDateFormat:(NSString *)inputDateFormat
205 | mappings:(NSDictionary *)mapping;
206 |
207 | /**
208 | * update the instance with new dictionary values
209 | *
210 | * @param dictionary dictionary containing key/value pairs for the object
211 | * @param option `kDateConverstionOption` to determine what to do when the value from dictionary is a DOT.NET Date
212 | *type.
213 | * @param inputDateFormatter NSDateFormatter object which will be used to format the input date.
214 | * @param mapping dictionary to define the mappings for date conversion and array <-> object.
215 | *
216 | * @return object of type instancetype populated with the values from `dictionary`
217 | */
218 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
219 | dateConversionOption:(kDateConversionOption)option
220 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
221 | mappings:(NSDictionary *)mapping;
222 |
223 | @end
224 |
225 | @interface NSString (Additions)
226 |
227 | - (BOOL)contains:(NSString *)needle;
228 |
229 | @end
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHModelObject.m:
--------------------------------------------------------------------------------
1 | // SHModelObject.m
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import "SHModelObject.h"
24 | #import
25 |
26 | /**
27 | * trims a given NSString
28 | *
29 | * @param val the NSString to be trimmed
30 | *
31 | * @return trimmed NSString
32 | */
33 | #define TRIM_STRING(val) [val stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
34 |
35 | /**
36 | * checks if a NSString is valid
37 | *
38 | * @param val a NSString to be checked
39 | *
40 | * @return `YES` or `NO` based on the validity of the NSString
41 | */
42 | #define IS_VALID_STRING(val) \
43 | (val != nil) && [val length] != 0 && ([TRIM_STRING(val) length] != 0) && ![val isEqualToString:@"(null)"]
44 |
45 | // pattern to strip from the dictionary key and ivarname for comparision
46 | #define PATTERN_TO_STRIP @"-_ "
47 |
48 | static NSDateFormatter *_simpleDateFormatter;
49 | static NSDateFormatter *_timezoneDateFormatter;
50 | static NSDateFormatter *_customFormatter;
51 |
52 | @implementation SHModelObject {
53 | Ivar *_ivars;
54 | unsigned int _outCount;
55 | kDateConversionOption _converstionOption;
56 | kInputDateFormat _inputDateFormat;
57 | NSDictionary *_mappings;
58 | NSString *_customInputDateFormatString;
59 | }
60 |
61 | #pragma mark - Factory methods for object creation
62 | //
63 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary {
64 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
65 | return nil;
66 | }
67 |
68 | if ([dictionary isKindOfClass:[NSNull class]]) {
69 | return nil;
70 | }
71 | return [[[self class] alloc] initWithDictionary:dictionary];
72 | }
73 |
74 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary mappings:(NSDictionary *)mapping {
75 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
76 | return nil;
77 | }
78 |
79 | if ([dictionary isKindOfClass:[NSNull class]]) {
80 | return nil;
81 | }
82 | return [self objectWithDictionary:dictionary
83 | dateConversionOption:kDateConverstionFromNSStringToNSDateOption
84 | inputDateType:kInputDateFormatJSON
85 | mappings:mapping];
86 | }
87 |
88 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
89 | dateConversionOption:(kDateConversionOption)option
90 | inputDateType:(kInputDateFormat)inputDateType
91 | mappings:(NSDictionary *)mapping {
92 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
93 | return nil;
94 | }
95 |
96 | if ([dictionary isKindOfClass:[NSNull class]]) {
97 | return nil;
98 | }
99 | return [[[self class] alloc] initWithDictionary:dictionary
100 | dateConversionOption:option
101 | inputDateType:inputDateType
102 | mappings:mapping];
103 | }
104 |
105 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
106 | dateConversionOption:(kDateConversionOption)option
107 | inputDateFormat:(NSString *)inputDateFormat
108 | mappings:(NSDictionary *)mapping {
109 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
110 | return nil;
111 | }
112 |
113 | if ([dictionary isKindOfClass:[NSNull class]]) {
114 | return nil;
115 | }
116 | return [[[self class] alloc] initWithDictionary:dictionary
117 | dateConversionOption:option
118 | inputDateFormat:inputDateFormat
119 | mappings:mapping];
120 | }
121 |
122 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
123 | dateConversionOption:(kDateConversionOption)option
124 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
125 | mappings:(NSDictionary *)mapping {
126 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
127 | return nil;
128 | }
129 |
130 | if ([dictionary isKindOfClass:[NSNull class]]) {
131 | return nil;
132 | }
133 | return [[[self class] alloc] initWithDictionary:dictionary
134 | dateConversionOption:option
135 | inputDateFormatter:inputDateFormatter
136 | mappings:mapping];
137 | }
138 |
139 | //
140 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
141 | {
142 | if ((self = [super init])) {
143 | return [self updateWithDictionary:dictionary
144 | dateConversionOption:kDateConverstionFromNSStringToNSStringOption
145 | inputDateType:kInputDateFormatJSON
146 | mappings:nil];
147 | }
148 | return self;
149 | }
150 |
151 | //
152 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
153 | dateConversionOption:(kDateConversionOption)option
154 | inputDateType:(kInputDateFormat)inputDateType
155 | mappings:(NSDictionary *)mapping {
156 | if ((self = [super init])) {
157 | return [self updateWithDictionary:dictionary
158 | dateConversionOption:option
159 | inputDateType:inputDateType
160 | mappings:mapping];
161 | }
162 | return self;
163 | }
164 |
165 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
166 | dateConversionOption:(kDateConversionOption)option
167 | inputDateFormat:(NSString *)inputDateFormat
168 | mappings:(NSDictionary *)mapping {
169 | if ((self = [super init])) {
170 | return [self updateWithDictionary:dictionary
171 | dateConversionOption:option
172 | inputDateFormat:inputDateFormat
173 | mappings:mapping];
174 | }
175 | return self;
176 | }
177 |
178 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
179 | dateConversionOption:(kDateConversionOption)option
180 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
181 | mappings:(NSDictionary *)mapping {
182 | if ((self = [super init])) {
183 | return [self updateWithDictionary:dictionary
184 | dateConversionOption:option
185 | inputDateFormatter:inputDateFormatter
186 | mappings:mapping];
187 | }
188 | return self;
189 | }
190 |
191 | // NSCoding
192 | - (NSArray *)propertyNames {
193 | NSMutableArray *array = [NSMutableArray array];
194 |
195 | // List of ivars
196 | id class = objc_getClass([NSStringFromClass([self class]) UTF8String]);
197 | _ivars = class_copyIvarList(class, &_outCount);
198 |
199 | // If it match our ivar name, then set it
200 | for (unsigned int i = 0; i < _outCount; i++) {
201 | Ivar ivar = _ivars[i];
202 | NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
203 | [array addObject:ivarName];
204 | }
205 |
206 | free(_ivars);
207 | _ivars = NULL;
208 | return array;
209 | }
210 |
211 | - (id)initWithCoder:(NSCoder *)aDecoder {
212 | if ((self = [self init])) {
213 | // Loop through the properties
214 | for (NSString *key in [self propertyNames]) {
215 | // Decode the property, and use the KVC setValueForKey: method to set it
216 | id value = [aDecoder decodeObjectForKey:key];
217 | [self setValue:value forKey:key];
218 | }
219 | }
220 | return self;
221 | }
222 |
223 | - (void)encodeWithCoder:(NSCoder *)aCoder {
224 | // Loop through the properties
225 | for (NSString *key in [self propertyNames]) {
226 | // Use the KVC valueForKey: method to get the property and then encode it
227 | id value = [self valueForKey:key];
228 | [aCoder encodeObject:value forKey:key];
229 | }
230 | }
231 |
232 | //
233 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary {
234 | // List of ivars
235 | id class = objc_getClass([NSStringFromClass([self class]) UTF8String]);
236 | _ivars = class_copyIvarList(class, &_outCount);
237 |
238 | // For each top-level property in the dictionary
239 | NSEnumerator *enumerator = [dictionary keyEnumerator];
240 | id key;
241 | while ((key = [enumerator nextObject])) {
242 | id value = [dictionary objectForKey:key];
243 | [self serializeValue:value withKey:key];
244 | }
245 |
246 | free(_ivars);
247 | _ivars = NULL;
248 |
249 | return self;
250 | }
251 |
252 | //
253 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
254 | dateConversionOption:(kDateConversionOption)option
255 | inputDateType:(kInputDateFormat)inputDateType
256 | mappings:(NSDictionary *)mapping {
257 | _converstionOption = option;
258 | _inputDateFormat = inputDateType;
259 | _mappings = mapping;
260 |
261 | if (nil == _simpleDateFormatter) {
262 | _simpleDateFormatter = [[NSDateFormatter alloc] init];
263 | [_simpleDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
264 | }
265 |
266 | if (nil == _timezoneDateFormatter) {
267 | _timezoneDateFormatter = [[NSDateFormatter alloc] init];
268 | [_timezoneDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
269 | }
270 |
271 | return [self updateWithDictionary:dictionary];
272 | }
273 |
274 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
275 | dateConversionOption:(kDateConversionOption)option
276 | inputDateFormat:(NSString *)inputDateFormat
277 | mappings:(NSDictionary *)mapping {
278 | _converstionOption = option;
279 | _inputDateFormat = kInputDateFormatCustom;
280 | _customInputDateFormatString = inputDateFormat;
281 | if (_customInputDateFormatString && !_customFormatter) {
282 | _customFormatter = [[NSDateFormatter alloc] init];
283 | [_customFormatter setDateFormat:_customInputDateFormatString];
284 | }
285 | _mappings = mapping;
286 |
287 | return [self updateWithDictionary:dictionary];
288 | }
289 |
290 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
291 | dateConversionOption:(kDateConversionOption)option
292 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
293 | mappings:(NSDictionary *)mapping {
294 | _converstionOption = option;
295 | _inputDateFormat = kInputDateFormatCustom;
296 | _customFormatter = inputDateFormatter;
297 | _mappings = mapping;
298 |
299 | return [self updateWithDictionary:dictionary];
300 | }
301 |
302 | #pragma mark - SHModalSerialization protocol methods
303 |
304 | - (void)serializeValue:(id)value withKey:(id)key {
305 | // check for NSNull or nil for key
306 | if ([key isKindOfClass:[NSNull class]] || nil == key) {
307 | return;
308 | }
309 |
310 | // check for NSNull or nil for value
311 | if ([value isKindOfClass:[NSNull class]] || nil == value) {
312 | return;
313 | }
314 |
315 | // If it match our ivar name, then set it
316 | for (unsigned int i = 0; i < _outCount; i++) {
317 | Ivar ivar = _ivars[i];
318 | NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
319 | NSString *ivarType = [NSString stringWithCString:ivar_getTypeEncoding(ivar) encoding:NSUTF8StringEncoding];
320 |
321 | if ([self matchesPattern:key ivar:ivarName] == NO) {
322 | continue;
323 | }
324 |
325 | // it will be NSString, NSNumber, NSArray, NSDictionary or NSNull
326 | if ([value isKindOfClass:[NSString class]]) {
327 |
328 | /*
329 | converting the .NET JSON Date representation to either NSDate, NSTimeInterval or keeping it as
330 | NSString. if somebody wants a different conversion, please simplye override the method and parse the
331 | value and set for yourself and make sure you call [super serializeValue: key:] for all other values so
332 | that they are parsed correctly.
333 | */
334 | switch (_converstionOption) {
335 | case kDateConverstionFromNSStringToNSDateOption: {
336 | if ([ivarType contains:@"NSDate"]) {
337 | switch (_inputDateFormat) {
338 | case kInputDateFormatJSON: {
339 | value = (NSDate *)[self dateFromDotNetJSONString:value];
340 | } break;
341 | case kInputDateFormatDotNetSimple: {
342 | value = (NSDate *)[_simpleDateFormatter dateFromString:value];
343 | } break;
344 | case kInputDateFormatDotNetWithTimeZone: {
345 | value = (NSDate *)[_timezoneDateFormatter dateFromString:value];
346 | } break;
347 | case kInputDateFormatCustom: {
348 | value = (NSDate *)[_customFormatter dateFromString:value];
349 | } break;
350 | default: { value = (NSDate *)[self dateFromDotNetJSONString:value]; } break;
351 | }
352 | }
353 | } break;
354 | case kDateConverstionFromNSStringToNSTimeIntervalOption: {
355 | if (![ivarType contains:@"@"]) {
356 | switch (_inputDateFormat) {
357 | case kInputDateFormatJSON: {
358 | value = @([[self dateFromDotNetJSONString:value] timeIntervalSince1970]);
359 | } break;
360 | case kInputDateFormatDotNetSimple: {
361 | value = @([[_simpleDateFormatter dateFromString:value] timeIntervalSince1970]);
362 | } break;
363 | case kInputDateFormatDotNetWithTimeZone: {
364 | value = @([[_timezoneDateFormatter dateFromString:value] timeIntervalSince1970]);
365 | } break;
366 | case kInputDateFormatCustom: {
367 | value = @([[_customFormatter dateFromString:value] timeIntervalSince1970]);
368 | } break;
369 | default: {
370 | value = @([[self dateFromDotNetJSONString:value] timeIntervalSince1970]);
371 | } break;
372 | }
373 | }
374 | } break;
375 | case kDateConverstionFromNSStringToNSStringOption: {
376 | if (![ivarType contains:NSStringFromClass([NSString class])]) {
377 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSString");
378 | }
379 | }
380 | }
381 | } else if ([value isKindOfClass:[NSNumber class]] && ![ivarType contains:@"NSNumber"]) {
382 | // special case, where NSNumber can be stored into the primitive types. just need to chceck that iVar is not
383 | // an object.
384 | if ([ivarType contains:@"@"]) {
385 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSNumber");
386 | }
387 | } else if ([value isKindOfClass:[NSDictionary class]]) {
388 | NSString *typeName = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
389 | typeName = [typeName stringByReplacingOccurrencesOfString:@"\"" withString:@""];
390 | Class objectClass = NSClassFromString(typeName);
391 | BOOL isSHModelObject = [self isSHModelObject:objectClass];
392 | if (isSHModelObject) {
393 | value = [objectClass objectWithDictionary:value];
394 | } else if (![ivarType contains:@"Dictionary"]) {
395 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSDictionary or NSMutableDictionary");
396 | }
397 | } else if ([value isKindOfClass:[NSArray class]]) {
398 | if (![ivarType contains:@"Array"]) {
399 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSArray or NSMutableArray");
400 | }
401 |
402 | id availableMappingClass = _mappings[key];
403 | if (availableMappingClass && [availableMappingClass isKindOfClass:[NSString class]]) {
404 | // mapping string available.
405 | Class objectClass = NSClassFromString(availableMappingClass);
406 | BOOL isSHModelObject = [self isSHModelObject:objectClass];
407 | if (isSHModelObject) {
408 | NSMutableArray *valueArray = [NSMutableArray arrayWithCapacity:[value count]];
409 | for (id item in value) {
410 | // item should be a dictionary
411 | if ([item isKindOfClass:[NSDictionary class]]) {
412 | id itemObject = [objectClass objectWithDictionary:item mappings:_mappings];
413 | if (itemObject) {
414 | [valueArray addObject:itemObject];
415 | }
416 | } else {
417 | NSLog(@"object %@ is not a NSDictionary object, skipping.", [item description]);
418 | }
419 | }
420 | value = valueArray;
421 | }
422 | }
423 | }
424 |
425 | [self setValue:value forKey:ivarName];
426 | }
427 | }
428 |
429 | - (BOOL)isSHModelObject:(Class) class {
430 | if (class == nil)
431 | return NO;
432 | if (class == [SHModelObject class]) {
433 | return YES;
434 | }
435 | return [self isSHModelObject:[class superclass]];
436 | }
437 |
438 | #pragma mark - NSObject overriden methods
439 |
440 | //
441 | -
442 | (NSString *)description {
443 | return [NSString stringWithFormat:@"<%@ %p>", NSStringFromClass([self class]), self];
444 | }
445 |
446 | #pragma mark - SHModalSerializer helper functions
447 |
448 | - (BOOL)matchesPattern:(NSString *)key ivar:(NSString *)ivarName {
449 | if (nil == key || nil == ivarName) {
450 | return NO;
451 | }
452 |
453 | if ((!IS_VALID_STRING(key)) || (!IS_VALID_STRING(ivarName))) {
454 | return NO;
455 | }
456 |
457 | NSMutableString *prettyKey = [NSMutableString stringWithCapacity:key.length];
458 | NSMutableString *prettyIvar = [NSMutableString stringWithCapacity:ivarName.length];
459 |
460 | NSScanner *scannerForKey = [NSScanner scannerWithString:key];
461 | NSScanner *scannerForIvar = [NSScanner scannerWithString:ivarName];
462 |
463 | scannerForKey.caseSensitive = NO;
464 | scannerForIvar.caseSensitive = NO;
465 |
466 | NSCharacterSet *stripChars = [[NSCharacterSet characterSetWithCharactersInString:PATTERN_TO_STRIP] invertedSet];
467 | while ([scannerForKey isAtEnd] == NO) {
468 | NSString *buffer;
469 | if ([scannerForKey scanCharactersFromSet:stripChars intoString:&buffer]) {
470 | [prettyKey appendString:buffer];
471 |
472 | } else {
473 | [scannerForKey setScanLocation:([scannerForKey scanLocation] + 1)];
474 | }
475 | }
476 |
477 | while ([scannerForIvar isAtEnd] == NO) {
478 | NSString *buffer;
479 | if ([scannerForIvar scanCharactersFromSet:stripChars intoString:&buffer]) {
480 | [prettyIvar appendString:buffer];
481 | } else {
482 | [scannerForIvar setScanLocation:([scannerForIvar scanLocation] + 1)];
483 | }
484 | }
485 |
486 | return ([[prettyKey lowercaseString] isEqualToString:[prettyIvar lowercaseString]]);
487 | }
488 |
489 | - (NSDate *)dateFromDotNetJSONString:(NSString *)string {
490 | if (!string) {
491 | return nil;
492 | }
493 | static NSRegularExpression *dateRegEx = nil;
494 | static dispatch_once_t onceToken;
495 | dispatch_once(&onceToken, ^{
496 | dateRegEx = [[NSRegularExpression alloc] initWithPattern:@"^\\/date\\((-?\\d++)(?:([+-])(\\d{2})(\\d{2}))?\\)\\/$"
497 | options:NSRegularExpressionCaseInsensitive
498 | error:nil];
499 | });
500 | NSTextCheckingResult *regexResult =
501 | [dateRegEx firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
502 |
503 | if (regexResult) {
504 | // milliseconds
505 | NSTimeInterval seconds = [[string substringWithRange:[regexResult rangeAtIndex:1]] doubleValue] / 1000.0;
506 | // timezone offset
507 | if ([regexResult rangeAtIndex:2].location != NSNotFound) {
508 | NSString *sign = [string substringWithRange:[regexResult rangeAtIndex:2]];
509 | // hours
510 | seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:3]]] doubleValue] * 60.0 * 60.0;
511 | // minutes
512 | seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:4]]] doubleValue] * 60.0;
513 | }
514 |
515 | return [NSDate dateWithTimeIntervalSince1970:seconds];
516 | }
517 | return nil;
518 | }
519 |
520 | @end
521 |
522 | #pragma mark - NSString+Additions
523 |
524 | @implementation NSString (Additions)
525 |
526 | - (BOOL)contains:(NSString *)needle;
527 | {
528 | NSRange range = [self rangeOfString:needle options:NSCaseInsensitiveSearch];
529 | return (range.length == needle.length && range.location != NSNotFound);
530 | }
531 |
532 | @end
533 |
--------------------------------------------------------------------------------
/SHModelObject/SHModelObject/SHRealmObject.m:
--------------------------------------------------------------------------------
1 | // SHRealmObject.m
2 | //
3 | // Copyright (c) 2014 Shan Ul Haq (http://grevolution.me)
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 | #import "SHRealmObject.h"
24 | #import
25 | #import
26 |
27 | /**
28 | * trims a given NSString
29 | *
30 | * @param val the NSString to be trimmed
31 | *
32 | * @return trimmed NSString
33 | */
34 | #define TRIM_STRING(val) [val stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
35 |
36 | /**
37 | * checks if a NSString is valid
38 | *
39 | * @param val a NSString to be checked
40 | *
41 | * @return `YES` or `NO` based on the validity of the NSString
42 | */
43 | #define IS_VALID_STRING(val) \
44 | (val != nil) && [val length] != 0 && ([TRIM_STRING(val) length] != 0) && ![val isEqualToString:@"(null)"]
45 |
46 | // pattern to strip from the dictionary key and ivarname for comparision
47 | #define PATTERN_TO_STRIP @"-_ "
48 |
49 | static NSDateFormatter *_simpleDateFormatter;
50 | static NSDateFormatter *_timezoneDateFormatter;
51 | static NSDateFormatter *_customFormatter;
52 |
53 | @implementation SHRealmObject {
54 | Ivar *_ivars;
55 | unsigned int _outCount;
56 | kDateConversionOption _converstionOption;
57 | kInputDateFormat _inputDateFormat;
58 | NSDictionary *_mappings;
59 | NSString *_customInputDateFormatString;
60 | }
61 |
62 | #pragma mark - Factory methods for object creation
63 | //
64 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary {
65 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
66 | return nil;
67 | }
68 |
69 | if ([dictionary isKindOfClass:[NSNull class]]) {
70 | return nil;
71 | }
72 | return [[[self class] alloc] initWithDictionary:dictionary];
73 | }
74 |
75 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary mappings:(NSDictionary *)mapping {
76 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
77 | return nil;
78 | }
79 |
80 | if ([dictionary isKindOfClass:[NSNull class]]) {
81 | return nil;
82 | }
83 | return [self objectWithDictionary:dictionary
84 | dateConversionOption:kDateConverstionFromNSStringToNSDateOption
85 | inputDateType:kInputDateFormatJSON
86 | mappings:mapping];
87 | }
88 |
89 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
90 | dateConversionOption:(kDateConversionOption)option
91 | inputDateType:(kInputDateFormat)inputDateType
92 | mappings:(NSDictionary *)mapping {
93 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
94 | return nil;
95 | }
96 |
97 | if ([dictionary isKindOfClass:[NSNull class]]) {
98 | return nil;
99 | }
100 | return [[[self class] alloc] initWithDictionary:dictionary
101 | dateConversionOption:option
102 | inputDateType:inputDateType
103 | mappings:mapping];
104 | }
105 |
106 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
107 | dateConversionOption:(kDateConversionOption)option
108 | inputDateFormat:(NSString *)inputDateFormat
109 | mappings:(NSDictionary *)mapping {
110 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
111 | return nil;
112 | }
113 |
114 | if ([dictionary isKindOfClass:[NSNull class]]) {
115 | return nil;
116 | }
117 | return [[[self class] alloc] initWithDictionary:dictionary
118 | dateConversionOption:option
119 | inputDateFormat:inputDateFormat
120 | mappings:mapping];
121 | }
122 |
123 | + (instancetype)objectWithDictionary:(NSDictionary *)dictionary
124 | dateConversionOption:(kDateConversionOption)option
125 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
126 | mappings:(NSDictionary *)mapping {
127 | if (nil == dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
128 | return nil;
129 | }
130 |
131 | if ([dictionary isKindOfClass:[NSNull class]]) {
132 | return nil;
133 | }
134 | return [[[self class] alloc] initWithDictionary:dictionary
135 | dateConversionOption:option
136 | inputDateFormatter:inputDateFormatter
137 | mappings:mapping];
138 | }
139 |
140 | //
141 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
142 | {
143 | if ((self = [super init])) {
144 | return [self updateWithDictionary:dictionary
145 | dateConversionOption:kDateConverstionFromNSStringToNSStringOption
146 | inputDateType:kInputDateFormatJSON
147 | mappings:nil];
148 | }
149 | return self;
150 | }
151 |
152 | //
153 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
154 | dateConversionOption:(kDateConversionOption)option
155 | inputDateType:(kInputDateFormat)inputDateType
156 | mappings:(NSDictionary *)mapping {
157 | if ((self = [super init])) {
158 | return [self updateWithDictionary:dictionary
159 | dateConversionOption:option
160 | inputDateType:inputDateType
161 | mappings:mapping];
162 | }
163 | return self;
164 | }
165 |
166 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
167 | dateConversionOption:(kDateConversionOption)option
168 | inputDateFormat:(NSString *)inputDateFormat
169 | mappings:(NSDictionary *)mapping {
170 | if ((self = [super init])) {
171 | return [self updateWithDictionary:dictionary
172 | dateConversionOption:option
173 | inputDateFormat:inputDateFormat
174 | mappings:mapping];
175 | }
176 | return self;
177 | }
178 |
179 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary
180 | dateConversionOption:(kDateConversionOption)option
181 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
182 | mappings:(NSDictionary *)mapping {
183 | if ((self = [super init])) {
184 | return [self updateWithDictionary:dictionary
185 | dateConversionOption:option
186 | inputDateFormatter:inputDateFormatter
187 | mappings:mapping];
188 | }
189 | return self;
190 | }
191 |
192 | // NSCoding
193 | - (NSArray *)propertyNames {
194 | NSMutableArray *array = [NSMutableArray array];
195 |
196 | // List of ivars
197 | NSString *selfClassName = NSStringFromClass([self class]);
198 | NSString *actualClassName = [[selfClassName componentsSeparatedByString:@"_"] lastObject];
199 | id class = objc_getClass([actualClassName UTF8String]);
200 | _ivars = class_copyIvarList(class, &_outCount);
201 |
202 | // If it match our ivar name, then set it
203 | for (unsigned int i = 0; i < _outCount; i++) {
204 | Ivar ivar = _ivars[i];
205 | NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
206 | [array addObject:ivarName];
207 | }
208 |
209 | free(_ivars);
210 | _ivars = NULL;
211 | return array;
212 | }
213 |
214 | - (id)initWithCoder:(NSCoder *)aDecoder {
215 | if ((self = [self init])) {
216 | // Loop through the properties
217 | for (NSString *key in [self propertyNames]) {
218 | // Decode the property, and use the KVC setValueForKey: method to set it
219 | id value = [aDecoder decodeObjectForKey:key];
220 | [self setValue:value forKey:key];
221 | }
222 | }
223 | return self;
224 | }
225 |
226 | - (void)encodeWithCoder:(NSCoder *)aCoder {
227 | // Loop through the properties
228 | for (NSString *key in [self propertyNames]) {
229 | // Use the KVC valueForKey: method to get the property and then encode it
230 | id value = [self valueForKey:key];
231 | [aCoder encodeObject:value forKey:key];
232 | }
233 | }
234 |
235 | //
236 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary {
237 | // List of ivars
238 | NSString *selfClassName = NSStringFromClass([self class]);
239 | NSString *actualClassName = [[selfClassName componentsSeparatedByString:@"_"] lastObject];
240 | id class = objc_getClass([actualClassName UTF8String]);
241 | _ivars = class_copyIvarList(class, &_outCount);
242 |
243 | // For each top-level property in the dictionary
244 | NSEnumerator *enumerator = [dictionary keyEnumerator];
245 | id key;
246 | while ((key = [enumerator nextObject])) {
247 | id value = [dictionary objectForKey:key];
248 | [self serializeValue:value withKey:key];
249 | }
250 |
251 | free(_ivars);
252 | _ivars = NULL;
253 |
254 | return self;
255 | }
256 |
257 | //
258 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
259 | dateConversionOption:(kDateConversionOption)option
260 | inputDateType:(kInputDateFormat)inputDateType
261 | mappings:(NSDictionary *)mapping {
262 | _converstionOption = option;
263 | _inputDateFormat = inputDateType;
264 | _mappings = mapping;
265 |
266 | if (nil == _simpleDateFormatter) {
267 | _simpleDateFormatter = [[NSDateFormatter alloc] init];
268 | [_simpleDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
269 | }
270 |
271 | if (nil == _timezoneDateFormatter) {
272 | _timezoneDateFormatter = [[NSDateFormatter alloc] init];
273 | [_timezoneDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
274 | }
275 |
276 | return [self updateWithDictionary:dictionary];
277 | }
278 |
279 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
280 | dateConversionOption:(kDateConversionOption)option
281 | inputDateFormat:(NSString *)inputDateFormat
282 | mappings:(NSDictionary *)mapping {
283 | _converstionOption = option;
284 | _inputDateFormat = kInputDateFormatCustom;
285 | _customInputDateFormatString = inputDateFormat;
286 | if (_customInputDateFormatString && !_customFormatter) {
287 | _customFormatter = [[NSDateFormatter alloc] init];
288 | [_customFormatter setDateFormat:_customInputDateFormatString];
289 | }
290 | _mappings = mapping;
291 |
292 | return [self updateWithDictionary:dictionary];
293 | }
294 |
295 | - (instancetype)updateWithDictionary:(NSDictionary *)dictionary
296 | dateConversionOption:(kDateConversionOption)option
297 | inputDateFormatter:(NSDateFormatter *)inputDateFormatter
298 | mappings:(NSDictionary *)mapping {
299 | _converstionOption = option;
300 | _inputDateFormat = kInputDateFormatCustom;
301 | _customFormatter = inputDateFormatter;
302 | _mappings = mapping;
303 |
304 | return [self updateWithDictionary:dictionary];
305 | }
306 |
307 | #pragma mark - SHModalSerialization protocol methods
308 |
309 | - (void)serializeValue:(id)value withKey:(id)key {
310 | // check for NSNull or nil for key
311 | if ([key isKindOfClass:[NSNull class]] || nil == key) {
312 | return;
313 | }
314 |
315 | // check for NSNull or nil for value
316 | if ([value isKindOfClass:[NSNull class]] || nil == value) {
317 | return;
318 | }
319 |
320 | // If it match our ivar name, then set it
321 | for (unsigned int i = 0; i < _outCount; i++) {
322 | Ivar ivar = _ivars[i];
323 | NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
324 | NSString *ivarType = [NSString stringWithCString:ivar_getTypeEncoding(ivar) encoding:NSUTF8StringEncoding];
325 |
326 | if ([self matchesPattern:key ivar:ivarName] == NO) {
327 | continue;
328 | }
329 |
330 | // it will be NSString, NSNumber, NSArray, NSDictionary or NSNull
331 | if ([value isKindOfClass:[NSString class]]) {
332 |
333 | /*
334 | converting the .NET JSON Date representation to either NSDate, NSTimeInterval or keeping it as
335 | NSString. if somebody wants a different conversion, please simplye override the method and parse the
336 | value and set for yourself and make sure you call [super serializeValue: key:] for all other values so
337 | that they are parsed correctly.
338 | */
339 | switch (_converstionOption) {
340 | case kDateConverstionFromNSStringToNSDateOption: {
341 | if ([ivarType contains:@"NSDate"]) {
342 | switch (_inputDateFormat) {
343 | case kInputDateFormatJSON: {
344 | value = (NSDate *)[self dateFromDotNetJSONString:value];
345 | } break;
346 | case kInputDateFormatDotNetSimple: {
347 | value = (NSDate *)[_simpleDateFormatter dateFromString:value];
348 | } break;
349 | case kInputDateFormatDotNetWithTimeZone: {
350 | value = (NSDate *)[_timezoneDateFormatter dateFromString:value];
351 | } break;
352 | case kInputDateFormatCustom: {
353 | value = (NSDate *)[_customFormatter dateFromString:value];
354 | } break;
355 |
356 | default: { value = (NSDate *)[self dateFromDotNetJSONString:value]; } break;
357 | }
358 | }
359 | } break;
360 | case kDateConverstionFromNSStringToNSTimeIntervalOption: {
361 | if (![ivarType contains:@"@"]) {
362 | switch (_inputDateFormat) {
363 | case kInputDateFormatJSON: {
364 | value = @([[self dateFromDotNetJSONString:value] timeIntervalSince1970]);
365 | } break;
366 | case kInputDateFormatDotNetSimple: {
367 | value = @([[_simpleDateFormatter dateFromString:value] timeIntervalSince1970]);
368 | } break;
369 | case kInputDateFormatDotNetWithTimeZone: {
370 | value = @([[_timezoneDateFormatter dateFromString:value] timeIntervalSince1970]);
371 | } break;
372 | case kInputDateFormatCustom: {
373 | value = @([[_customFormatter dateFromString:value] timeIntervalSince1970]);
374 | } break;
375 | default: {
376 | value = @([[self dateFromDotNetJSONString:value] timeIntervalSince1970]);
377 | } break;
378 | }
379 | }
380 | } break;
381 | case kDateConverstionFromNSStringToNSStringOption: {
382 | if (![ivarType contains:NSStringFromClass([NSString class])]) {
383 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSString");
384 | }
385 | }
386 | }
387 | } else if ([value isKindOfClass:[NSNumber class]] && ![ivarType contains:@"NSNumber"]) {
388 | // special case, where NSNumber can be stored into the primitive types. just need to chceck that iVar is not
389 | // an object.
390 | if ([ivarType contains:@"@"]) {
391 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSNumber");
392 | }
393 | } else if ([value isKindOfClass:[NSDictionary class]]) {
394 | NSString *typeName = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
395 | typeName = [typeName stringByReplacingOccurrencesOfString:@"\"" withString:@""];
396 | Class objectClass = NSClassFromString(typeName);
397 | BOOL isSHRealmObject = [self isSHRealmObject:objectClass];
398 | if (isSHRealmObject) {
399 | value = [objectClass objectWithDictionary:value];
400 | } else if (![ivarType contains:@"Dictionary"]) {
401 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSDictionary or NSMutableDictionary");
402 | }
403 | } else if ([value isKindOfClass:[NSArray class]]) {
404 | if (![ivarType contains:@"Array"]) {
405 | NSAssert(false, @"the types do not match : %@ vs %@", ivarType, @"NSArray or NSMutableArray");
406 | }
407 |
408 | id availableMappingClass = _mappings[key];
409 | if (availableMappingClass && [availableMappingClass isKindOfClass:[NSString class]]) {
410 | // mapping string available.
411 | Class objectClass = NSClassFromString(availableMappingClass);
412 | BOOL isSHRealmObject = [self isSHRealmObject:objectClass];
413 | if (isSHRealmObject) {
414 |
415 | NSString *propName = [ivarName substringFromIndex:1];
416 | id realmArray = ((id (*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(propName));
417 | for (id item in value) {
418 | // item should be a dictionary
419 | if ([item isKindOfClass:[NSDictionary class]]) {
420 | id itemObject = [objectClass objectWithDictionary:item mappings:_mappings];
421 | if (itemObject) {
422 | if ([realmArray respondsToSelector:@selector(addObject:)]) {
423 | [realmArray addObject:itemObject];
424 | }
425 | }
426 | } else {
427 | NSLog(@"object %@ is not a NSDictionary object, skipping.", [item description]);
428 | }
429 | }
430 | }
431 | }
432 | return;
433 | }
434 | [self setValue:value forKey:ivarName];
435 | }
436 | }
437 |
438 | - (BOOL)isSHRealmObject:(Class) class {
439 | if (class == nil)
440 | return NO;
441 | if (class == [SHRealmObject class]) {
442 | return YES;
443 | }
444 | return [self isSHRealmObject:[class superclass]];
445 | }
446 |
447 | #pragma mark - NSObject overriden methods
448 |
449 | //
450 | -
451 | (NSString *)description {
452 | return [NSString stringWithFormat:@"<%@ %p>", NSStringFromClass([self class]), self];
453 | }
454 |
455 | #pragma mark - SHModalSerializer helper functions
456 |
457 | - (BOOL)matchesPattern:(NSString *)key ivar:(NSString *)ivarName {
458 | if (nil == key || nil == ivarName) {
459 | return NO;
460 | }
461 |
462 | if ((!IS_VALID_STRING(key)) || (!IS_VALID_STRING(ivarName))) {
463 | return NO;
464 | }
465 |
466 | NSMutableString *prettyKey = [NSMutableString stringWithCapacity:key.length];
467 | NSMutableString *prettyIvar = [NSMutableString stringWithCapacity:ivarName.length];
468 |
469 | NSScanner *scannerForKey = [NSScanner scannerWithString:key];
470 | NSScanner *scannerForIvar = [NSScanner scannerWithString:ivarName];
471 |
472 | scannerForKey.caseSensitive = NO;
473 | scannerForIvar.caseSensitive = NO;
474 |
475 | NSCharacterSet *stripChars = [[NSCharacterSet characterSetWithCharactersInString:PATTERN_TO_STRIP] invertedSet];
476 | while ([scannerForKey isAtEnd] == NO) {
477 | NSString *buffer;
478 | if ([scannerForKey scanCharactersFromSet:stripChars intoString:&buffer]) {
479 | [prettyKey appendString:buffer];
480 |
481 | } else {
482 | [scannerForKey setScanLocation:([scannerForKey scanLocation] + 1)];
483 | }
484 | }
485 |
486 | while ([scannerForIvar isAtEnd] == NO) {
487 | NSString *buffer;
488 | if ([scannerForIvar scanCharactersFromSet:stripChars intoString:&buffer]) {
489 | [prettyIvar appendString:buffer];
490 | } else {
491 | [scannerForIvar setScanLocation:([scannerForIvar scanLocation] + 1)];
492 | }
493 | }
494 |
495 | return ([[prettyKey lowercaseString] isEqualToString:[prettyIvar lowercaseString]]);
496 | }
497 |
498 | - (NSDate *)dateFromDotNetJSONString:(NSString *)string {
499 | if (!string) {
500 | return nil;
501 | }
502 | static NSRegularExpression *dateRegEx = nil;
503 | static dispatch_once_t onceToken;
504 | dispatch_once(&onceToken, ^{
505 | dateRegEx =
506 | [[NSRegularExpression alloc] initWithPattern:@"^\\/date\\((-?\\d++)(?:([+-])(\\d{2})(\\d{2}))?\\)\\/$"
507 | options:NSRegularExpressionCaseInsensitive
508 | error:nil];
509 | });
510 | NSTextCheckingResult *regexResult =
511 | [dateRegEx firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
512 |
513 | if (regexResult) {
514 | // milliseconds
515 | NSTimeInterval seconds = [[string substringWithRange:[regexResult rangeAtIndex:1]] doubleValue] / 1000.0;
516 | // timezone offset
517 | if ([regexResult rangeAtIndex:2].location != NSNotFound) {
518 | NSString *sign = [string substringWithRange:[regexResult rangeAtIndex:2]];
519 | // hours
520 | seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:3]]] doubleValue] * 60.0 * 60.0;
521 | // minutes
522 | seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:4]]] doubleValue] * 60.0;
523 | }
524 |
525 | return [NSDate dateWithTimeIntervalSince1970:seconds];
526 | }
527 | return nil;
528 | }
529 |
530 | @end
531 |
532 | #pragma mark - NSString+Additions
533 |
534 | @implementation NSString (Additions)
535 |
536 | - (BOOL)contains:(NSString *)needle;
537 | {
538 | NSRange range = [self rangeOfString:needle options:NSCaseInsensitiveSearch];
539 | return (range.length == needle.length && range.location != NSNotFound);
540 | }
541 |
542 | @end
543 |
--------------------------------------------------------------------------------
/SHModelObject.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 66D76422E11513B26933E1D3 /* libPods-SHModelObject.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F0DD241F9FB35F3F93B212D7 /* libPods-SHModelObject.a */; };
11 | F23ED34A1ACECF1100DECB41 /* SHModelObject.m in Sources */ = {isa = PBXBuildFile; fileRef = F23ED3491ACECF1100DECB41 /* SHModelObject.m */; };
12 | F244007518DACD6B0078B6B0 /* SHRealmObject.m in Sources */ = {isa = PBXBuildFile; fileRef = F244006F18DACD6B0078B6B0 /* SHRealmObject.m */; };
13 | F244007618DACD6B0078B6B0 /* SHAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F244007118DACD6B0078B6B0 /* SHAppDelegate.m */; };
14 | F244007718DACD6B0078B6B0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F244007218DACD6B0078B6B0 /* Images.xcassets */; };
15 | F2B4093118BA16F400611B29 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4093018BA16F400611B29 /* Foundation.framework */; };
16 | F2B4093318BA16F400611B29 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4093218BA16F400611B29 /* CoreGraphics.framework */; };
17 | F2B4093518BA16F400611B29 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4093418BA16F400611B29 /* UIKit.framework */; };
18 | F2B4093B18BA16F400611B29 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F2B4093918BA16F400611B29 /* InfoPlist.strings */; };
19 | F2B4093D18BA16F400611B29 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B4093C18BA16F400611B29 /* main.m */; };
20 | F2B4094A18BA16F500611B29 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4094918BA16F500611B29 /* XCTest.framework */; };
21 | F2B4094B18BA16F500611B29 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4093018BA16F400611B29 /* Foundation.framework */; };
22 | F2B4094C18BA16F500611B29 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2B4093418BA16F400611B29 /* UIKit.framework */; };
23 | F2B4095418BA16F500611B29 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F2B4095218BA16F500611B29 /* InfoPlist.strings */; };
24 | F2B4095618BA16F500611B29 /* SHModalObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B4095518BA16F500611B29 /* SHModalObjectTests.m */; };
25 | F2FA97791AB40312002B972D /* SHAnotherModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F2FA97781AB40312002B972D /* SHAnotherModel.m */; };
26 | F2FA977C1AB40377002B972D /* SHTestModal.m in Sources */ = {isa = PBXBuildFile; fileRef = F2FA977B1AB40377002B972D /* SHTestModal.m */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXContainerItemProxy section */
30 | F2B4094D18BA16F500611B29 /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = F2B4092518BA16F400611B29 /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = F2B4092C18BA16F400611B29;
35 | remoteInfo = SHModalObject;
36 | };
37 | /* End PBXContainerItemProxy section */
38 |
39 | /* Begin PBXFileReference section */
40 | 2E37114A22AF21385F13CD70 /* Pods-SHModelObject.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SHModelObject.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SHModelObject/Pods-SHModelObject.debug.xcconfig"; sourceTree = ""; };
41 | A11D18FAC0D2005DF68AFF60 /* Pods-SHModelObject.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SHModelObject.release.xcconfig"; path = "Pods/Target Support Files/Pods-SHModelObject/Pods-SHModelObject.release.xcconfig"; sourceTree = ""; };
42 | F0DD241F9FB35F3F93B212D7 /* libPods-SHModelObject.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SHModelObject.a"; sourceTree = BUILT_PRODUCTS_DIR; };
43 | F23ED3481ACECF1100DECB41 /* SHModelObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHModelObject.h; sourceTree = ""; };
44 | F23ED3491ACECF1100DECB41 /* SHModelObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHModelObject.m; sourceTree = ""; };
45 | F23ED34B1ACF64F400DECB41 /* SHConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHConstants.h; sourceTree = ""; };
46 | F244006E18DACD6B0078B6B0 /* SHRealmObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHRealmObject.h; sourceTree = ""; };
47 | F244006F18DACD6B0078B6B0 /* SHRealmObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHRealmObject.m; sourceTree = ""; };
48 | F244007018DACD6B0078B6B0 /* SHModelSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHModelSerialization.h; sourceTree = ""; };
49 | F244007118DACD6B0078B6B0 /* SHAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHAppDelegate.m; sourceTree = ""; };
50 | F244007218DACD6B0078B6B0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
51 | F244007318DACD6B0078B6B0 /* SHAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHAppDelegate.h; sourceTree = ""; };
52 | F2B4092D18BA16F400611B29 /* SHModelObject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SHModelObject.app; sourceTree = BUILT_PRODUCTS_DIR; };
53 | F2B4093018BA16F400611B29 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
54 | F2B4093218BA16F400611B29 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
55 | F2B4093418BA16F400611B29 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
56 | F2B4093818BA16F400611B29 /* SHModelObject-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SHModelObject-Info.plist"; sourceTree = ""; };
57 | F2B4093A18BA16F400611B29 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
58 | F2B4093C18BA16F400611B29 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
59 | F2B4093E18BA16F400611B29 /* SHModelObject-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SHModelObject-Prefix.pch"; sourceTree = ""; };
60 | F2B4094818BA16F500611B29 /* SHModelObjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SHModelObjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
61 | F2B4094918BA16F500611B29 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
62 | F2B4095118BA16F500611B29 /* SHModelObjectTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SHModelObjectTests-Info.plist"; sourceTree = ""; };
63 | F2B4095318BA16F500611B29 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
64 | F2B4095518BA16F500611B29 /* SHModalObjectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SHModalObjectTests.m; sourceTree = ""; };
65 | F2FA97771AB40312002B972D /* SHAnotherModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHAnotherModel.h; sourceTree = ""; };
66 | F2FA97781AB40312002B972D /* SHAnotherModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHAnotherModel.m; sourceTree = ""; };
67 | F2FA977A1AB40377002B972D /* SHTestModal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHTestModal.h; sourceTree = ""; };
68 | F2FA977B1AB40377002B972D /* SHTestModal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHTestModal.m; sourceTree = ""; };
69 | /* End PBXFileReference section */
70 |
71 | /* Begin PBXFrameworksBuildPhase section */
72 | F2B4092A18BA16F400611B29 /* Frameworks */ = {
73 | isa = PBXFrameworksBuildPhase;
74 | buildActionMask = 2147483647;
75 | files = (
76 | F2B4093318BA16F400611B29 /* CoreGraphics.framework in Frameworks */,
77 | F2B4093518BA16F400611B29 /* UIKit.framework in Frameworks */,
78 | F2B4093118BA16F400611B29 /* Foundation.framework in Frameworks */,
79 | 66D76422E11513B26933E1D3 /* libPods-SHModelObject.a in Frameworks */,
80 | );
81 | runOnlyForDeploymentPostprocessing = 0;
82 | };
83 | F2B4094518BA16F500611B29 /* Frameworks */ = {
84 | isa = PBXFrameworksBuildPhase;
85 | buildActionMask = 2147483647;
86 | files = (
87 | F2B4094A18BA16F500611B29 /* XCTest.framework in Frameworks */,
88 | F2B4094C18BA16F500611B29 /* UIKit.framework in Frameworks */,
89 | F2B4094B18BA16F500611B29 /* Foundation.framework in Frameworks */,
90 | );
91 | runOnlyForDeploymentPostprocessing = 0;
92 | };
93 | /* End PBXFrameworksBuildPhase section */
94 |
95 | /* Begin PBXGroup section */
96 | 9CC53B38E18E241B9ED13283 /* Pods */ = {
97 | isa = PBXGroup;
98 | children = (
99 | 2E37114A22AF21385F13CD70 /* Pods-SHModelObject.debug.xcconfig */,
100 | A11D18FAC0D2005DF68AFF60 /* Pods-SHModelObject.release.xcconfig */,
101 | );
102 | name = Pods;
103 | sourceTree = "";
104 | };
105 | F244006D18DACD6B0078B6B0 /* SHModelObject */ = {
106 | isa = PBXGroup;
107 | children = (
108 | F23ED3481ACECF1100DECB41 /* SHModelObject.h */,
109 | F23ED3491ACECF1100DECB41 /* SHModelObject.m */,
110 | F244006E18DACD6B0078B6B0 /* SHRealmObject.h */,
111 | F244006F18DACD6B0078B6B0 /* SHRealmObject.m */,
112 | F244007018DACD6B0078B6B0 /* SHModelSerialization.h */,
113 | F23ED34B1ACF64F400DECB41 /* SHConstants.h */,
114 | );
115 | path = SHModelObject;
116 | sourceTree = "";
117 | };
118 | F2B4092418BA16F400611B29 = {
119 | isa = PBXGroup;
120 | children = (
121 | F2B4093618BA16F400611B29 /* SHModelObject */,
122 | F2B4094F18BA16F500611B29 /* SHModelObjectTests */,
123 | F2B4092F18BA16F400611B29 /* Frameworks */,
124 | F2B4092E18BA16F400611B29 /* Products */,
125 | 9CC53B38E18E241B9ED13283 /* Pods */,
126 | );
127 | sourceTree = "";
128 | };
129 | F2B4092E18BA16F400611B29 /* Products */ = {
130 | isa = PBXGroup;
131 | children = (
132 | F2B4092D18BA16F400611B29 /* SHModelObject.app */,
133 | F2B4094818BA16F500611B29 /* SHModelObjectTests.xctest */,
134 | );
135 | name = Products;
136 | sourceTree = "";
137 | };
138 | F2B4092F18BA16F400611B29 /* Frameworks */ = {
139 | isa = PBXGroup;
140 | children = (
141 | F2B4093018BA16F400611B29 /* Foundation.framework */,
142 | F2B4093218BA16F400611B29 /* CoreGraphics.framework */,
143 | F2B4093418BA16F400611B29 /* UIKit.framework */,
144 | F2B4094918BA16F500611B29 /* XCTest.framework */,
145 | F0DD241F9FB35F3F93B212D7 /* libPods-SHModelObject.a */,
146 | );
147 | name = Frameworks;
148 | sourceTree = "";
149 | };
150 | F2B4093618BA16F400611B29 /* SHModelObject */ = {
151 | isa = PBXGroup;
152 | children = (
153 | F244006D18DACD6B0078B6B0 /* SHModelObject */,
154 | F244007118DACD6B0078B6B0 /* SHAppDelegate.m */,
155 | F244007318DACD6B0078B6B0 /* SHAppDelegate.h */,
156 | F244007218DACD6B0078B6B0 /* Images.xcassets */,
157 | F2B4093718BA16F400611B29 /* Supporting Files */,
158 | F2FA977A1AB40377002B972D /* SHTestModal.h */,
159 | F2FA977B1AB40377002B972D /* SHTestModal.m */,
160 | F2FA97771AB40312002B972D /* SHAnotherModel.h */,
161 | F2FA97781AB40312002B972D /* SHAnotherModel.m */,
162 | );
163 | path = SHModelObject;
164 | sourceTree = "";
165 | };
166 | F2B4093718BA16F400611B29 /* Supporting Files */ = {
167 | isa = PBXGroup;
168 | children = (
169 | F2B4093818BA16F400611B29 /* SHModelObject-Info.plist */,
170 | F2B4093918BA16F400611B29 /* InfoPlist.strings */,
171 | F2B4093C18BA16F400611B29 /* main.m */,
172 | F2B4093E18BA16F400611B29 /* SHModelObject-Prefix.pch */,
173 | );
174 | name = "Supporting Files";
175 | sourceTree = "";
176 | };
177 | F2B4094F18BA16F500611B29 /* SHModelObjectTests */ = {
178 | isa = PBXGroup;
179 | children = (
180 | F2B4095518BA16F500611B29 /* SHModalObjectTests.m */,
181 | F2B4095018BA16F500611B29 /* Supporting Files */,
182 | );
183 | path = SHModelObjectTests;
184 | sourceTree = "";
185 | };
186 | F2B4095018BA16F500611B29 /* Supporting Files */ = {
187 | isa = PBXGroup;
188 | children = (
189 | F2B4095118BA16F500611B29 /* SHModelObjectTests-Info.plist */,
190 | F2B4095218BA16F500611B29 /* InfoPlist.strings */,
191 | );
192 | name = "Supporting Files";
193 | sourceTree = "";
194 | };
195 | /* End PBXGroup section */
196 |
197 | /* Begin PBXNativeTarget section */
198 | F2B4092C18BA16F400611B29 /* SHModelObject */ = {
199 | isa = PBXNativeTarget;
200 | buildConfigurationList = F2B4095918BA16F500611B29 /* Build configuration list for PBXNativeTarget "SHModelObject" */;
201 | buildPhases = (
202 | 76C12C901F41E58794DEA0B3 /* 📦 Check Pods Manifest.lock */,
203 | F2B4092918BA16F400611B29 /* Sources */,
204 | F2B4092A18BA16F400611B29 /* Frameworks */,
205 | F2B4092B18BA16F400611B29 /* Resources */,
206 | D220DA26D629C2FF6DDD81B5 /* 📦 Embed Pods Frameworks */,
207 | B01D7BF1DBBA78C75C6A004B /* 📦 Copy Pods Resources */,
208 | );
209 | buildRules = (
210 | );
211 | dependencies = (
212 | );
213 | name = SHModelObject;
214 | productName = SHModalObject;
215 | productReference = F2B4092D18BA16F400611B29 /* SHModelObject.app */;
216 | productType = "com.apple.product-type.application";
217 | };
218 | F2B4094718BA16F500611B29 /* SHModelObjectTests */ = {
219 | isa = PBXNativeTarget;
220 | buildConfigurationList = F2B4095C18BA16F500611B29 /* Build configuration list for PBXNativeTarget "SHModelObjectTests" */;
221 | buildPhases = (
222 | F2B4094418BA16F500611B29 /* Sources */,
223 | F2B4094518BA16F500611B29 /* Frameworks */,
224 | F2B4094618BA16F500611B29 /* Resources */,
225 | );
226 | buildRules = (
227 | );
228 | dependencies = (
229 | F2B4094E18BA16F500611B29 /* PBXTargetDependency */,
230 | );
231 | name = SHModelObjectTests;
232 | productName = SHModalObjectTests;
233 | productReference = F2B4094818BA16F500611B29 /* SHModelObjectTests.xctest */;
234 | productType = "com.apple.product-type.bundle.unit-test";
235 | };
236 | /* End PBXNativeTarget section */
237 |
238 | /* Begin PBXProject section */
239 | F2B4092518BA16F400611B29 /* Project object */ = {
240 | isa = PBXProject;
241 | attributes = {
242 | CLASSPREFIX = SH;
243 | LastUpgradeCheck = 0500;
244 | ORGANIZATIONNAME = grevolution;
245 | };
246 | buildConfigurationList = F2B4092818BA16F400611B29 /* Build configuration list for PBXProject "SHModelObject" */;
247 | compatibilityVersion = "Xcode 3.2";
248 | developmentRegion = English;
249 | hasScannedForEncodings = 0;
250 | knownRegions = (
251 | en,
252 | );
253 | mainGroup = F2B4092418BA16F400611B29;
254 | productRefGroup = F2B4092E18BA16F400611B29 /* Products */;
255 | projectDirPath = "";
256 | projectRoot = "";
257 | targets = (
258 | F2B4092C18BA16F400611B29 /* SHModelObject */,
259 | F2B4094718BA16F500611B29 /* SHModelObjectTests */,
260 | );
261 | };
262 | /* End PBXProject section */
263 |
264 | /* Begin PBXResourcesBuildPhase section */
265 | F2B4092B18BA16F400611B29 /* Resources */ = {
266 | isa = PBXResourcesBuildPhase;
267 | buildActionMask = 2147483647;
268 | files = (
269 | F2B4093B18BA16F400611B29 /* InfoPlist.strings in Resources */,
270 | F244007718DACD6B0078B6B0 /* Images.xcassets in Resources */,
271 | );
272 | runOnlyForDeploymentPostprocessing = 0;
273 | };
274 | F2B4094618BA16F500611B29 /* Resources */ = {
275 | isa = PBXResourcesBuildPhase;
276 | buildActionMask = 2147483647;
277 | files = (
278 | F2B4095418BA16F500611B29 /* InfoPlist.strings in Resources */,
279 | );
280 | runOnlyForDeploymentPostprocessing = 0;
281 | };
282 | /* End PBXResourcesBuildPhase section */
283 |
284 | /* Begin PBXShellScriptBuildPhase section */
285 | 76C12C901F41E58794DEA0B3 /* 📦 Check Pods Manifest.lock */ = {
286 | isa = PBXShellScriptBuildPhase;
287 | buildActionMask = 2147483647;
288 | files = (
289 | );
290 | inputPaths = (
291 | );
292 | name = "📦 Check Pods Manifest.lock";
293 | outputPaths = (
294 | );
295 | runOnlyForDeploymentPostprocessing = 0;
296 | shellPath = /bin/sh;
297 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
298 | showEnvVarsInLog = 0;
299 | };
300 | B01D7BF1DBBA78C75C6A004B /* 📦 Copy Pods Resources */ = {
301 | isa = PBXShellScriptBuildPhase;
302 | buildActionMask = 2147483647;
303 | files = (
304 | );
305 | inputPaths = (
306 | );
307 | name = "📦 Copy Pods Resources";
308 | outputPaths = (
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | shellPath = /bin/sh;
312 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SHModelObject/Pods-SHModelObject-resources.sh\"\n";
313 | showEnvVarsInLog = 0;
314 | };
315 | D220DA26D629C2FF6DDD81B5 /* 📦 Embed Pods Frameworks */ = {
316 | isa = PBXShellScriptBuildPhase;
317 | buildActionMask = 2147483647;
318 | files = (
319 | );
320 | inputPaths = (
321 | );
322 | name = "📦 Embed Pods Frameworks";
323 | outputPaths = (
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | shellPath = /bin/sh;
327 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SHModelObject/Pods-SHModelObject-frameworks.sh\"\n";
328 | showEnvVarsInLog = 0;
329 | };
330 | /* End PBXShellScriptBuildPhase section */
331 |
332 | /* Begin PBXSourcesBuildPhase section */
333 | F2B4092918BA16F400611B29 /* Sources */ = {
334 | isa = PBXSourcesBuildPhase;
335 | buildActionMask = 2147483647;
336 | files = (
337 | F2FA97791AB40312002B972D /* SHAnotherModel.m in Sources */,
338 | F23ED34A1ACECF1100DECB41 /* SHModelObject.m in Sources */,
339 | F2B4093D18BA16F400611B29 /* main.m in Sources */,
340 | F244007518DACD6B0078B6B0 /* SHRealmObject.m in Sources */,
341 | F244007618DACD6B0078B6B0 /* SHAppDelegate.m in Sources */,
342 | F2FA977C1AB40377002B972D /* SHTestModal.m in Sources */,
343 | );
344 | runOnlyForDeploymentPostprocessing = 0;
345 | };
346 | F2B4094418BA16F500611B29 /* Sources */ = {
347 | isa = PBXSourcesBuildPhase;
348 | buildActionMask = 2147483647;
349 | files = (
350 | F2B4095618BA16F500611B29 /* SHModalObjectTests.m in Sources */,
351 | );
352 | runOnlyForDeploymentPostprocessing = 0;
353 | };
354 | /* End PBXSourcesBuildPhase section */
355 |
356 | /* Begin PBXTargetDependency section */
357 | F2B4094E18BA16F500611B29 /* PBXTargetDependency */ = {
358 | isa = PBXTargetDependency;
359 | target = F2B4092C18BA16F400611B29 /* SHModelObject */;
360 | targetProxy = F2B4094D18BA16F500611B29 /* PBXContainerItemProxy */;
361 | };
362 | /* End PBXTargetDependency section */
363 |
364 | /* Begin PBXVariantGroup section */
365 | F2B4093918BA16F400611B29 /* InfoPlist.strings */ = {
366 | isa = PBXVariantGroup;
367 | children = (
368 | F2B4093A18BA16F400611B29 /* en */,
369 | );
370 | name = InfoPlist.strings;
371 | sourceTree = "";
372 | };
373 | F2B4095218BA16F500611B29 /* InfoPlist.strings */ = {
374 | isa = PBXVariantGroup;
375 | children = (
376 | F2B4095318BA16F500611B29 /* en */,
377 | );
378 | name = InfoPlist.strings;
379 | sourceTree = "";
380 | };
381 | /* End PBXVariantGroup section */
382 |
383 | /* Begin XCBuildConfiguration section */
384 | F2B4095718BA16F500611B29 /* Debug */ = {
385 | isa = XCBuildConfiguration;
386 | buildSettings = {
387 | ALWAYS_SEARCH_USER_PATHS = NO;
388 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
390 | CLANG_CXX_LIBRARY = "libc++";
391 | CLANG_ENABLE_MODULES = YES;
392 | CLANG_ENABLE_OBJC_ARC = YES;
393 | CLANG_WARN_BOOL_CONVERSION = YES;
394 | CLANG_WARN_CONSTANT_CONVERSION = YES;
395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
396 | CLANG_WARN_EMPTY_BODY = YES;
397 | CLANG_WARN_ENUM_CONVERSION = YES;
398 | CLANG_WARN_INT_CONVERSION = YES;
399 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
401 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
402 | COPY_PHASE_STRIP = NO;
403 | GCC_C_LANGUAGE_STANDARD = gnu99;
404 | GCC_DYNAMIC_NO_PIC = NO;
405 | GCC_OPTIMIZATION_LEVEL = 0;
406 | GCC_PREPROCESSOR_DEFINITIONS = (
407 | "DEBUG=1",
408 | "$(inherited)",
409 | );
410 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
413 | GCC_WARN_UNDECLARED_SELECTOR = YES;
414 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
415 | GCC_WARN_UNUSED_FUNCTION = YES;
416 | GCC_WARN_UNUSED_VARIABLE = YES;
417 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
418 | ONLY_ACTIVE_ARCH = YES;
419 | SDKROOT = iphoneos;
420 | TARGETED_DEVICE_FAMILY = "1,2";
421 | };
422 | name = Debug;
423 | };
424 | F2B4095818BA16F500611B29 /* Release */ = {
425 | isa = XCBuildConfiguration;
426 | buildSettings = {
427 | ALWAYS_SEARCH_USER_PATHS = NO;
428 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
429 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
430 | CLANG_CXX_LIBRARY = "libc++";
431 | CLANG_ENABLE_MODULES = YES;
432 | CLANG_ENABLE_OBJC_ARC = YES;
433 | CLANG_WARN_BOOL_CONVERSION = YES;
434 | CLANG_WARN_CONSTANT_CONVERSION = YES;
435 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
436 | CLANG_WARN_EMPTY_BODY = YES;
437 | CLANG_WARN_ENUM_CONVERSION = YES;
438 | CLANG_WARN_INT_CONVERSION = YES;
439 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
440 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
441 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
442 | COPY_PHASE_STRIP = YES;
443 | ENABLE_NS_ASSERTIONS = NO;
444 | GCC_C_LANGUAGE_STANDARD = gnu99;
445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
447 | GCC_WARN_UNDECLARED_SELECTOR = YES;
448 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
449 | GCC_WARN_UNUSED_FUNCTION = YES;
450 | GCC_WARN_UNUSED_VARIABLE = YES;
451 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
452 | SDKROOT = iphoneos;
453 | TARGETED_DEVICE_FAMILY = "1,2";
454 | VALIDATE_PRODUCT = YES;
455 | };
456 | name = Release;
457 | };
458 | F2B4095A18BA16F500611B29 /* Debug */ = {
459 | isa = XCBuildConfiguration;
460 | baseConfigurationReference = 2E37114A22AF21385F13CD70 /* Pods-SHModelObject.debug.xcconfig */;
461 | buildSettings = {
462 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
463 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
464 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
465 | GCC_PREFIX_HEADER = "SHModelObject/SHModelObject-Prefix.pch";
466 | INFOPLIST_FILE = "SHModelObject/SHModelObject-Info.plist";
467 | PRODUCT_NAME = SHModelObject;
468 | WRAPPER_EXTENSION = app;
469 | };
470 | name = Debug;
471 | };
472 | F2B4095B18BA16F500611B29 /* Release */ = {
473 | isa = XCBuildConfiguration;
474 | baseConfigurationReference = A11D18FAC0D2005DF68AFF60 /* Pods-SHModelObject.release.xcconfig */;
475 | buildSettings = {
476 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
477 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
478 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
479 | GCC_PREFIX_HEADER = "SHModelObject/SHModelObject-Prefix.pch";
480 | INFOPLIST_FILE = "SHModelObject/SHModelObject-Info.plist";
481 | PRODUCT_NAME = SHModelObject;
482 | WRAPPER_EXTENSION = app;
483 | };
484 | name = Release;
485 | };
486 | F2B4095D18BA16F500611B29 /* Debug */ = {
487 | isa = XCBuildConfiguration;
488 | buildSettings = {
489 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
490 | FRAMEWORK_SEARCH_PATHS = (
491 | "$(SDKROOT)/Developer/Library/Frameworks",
492 | "$(inherited)",
493 | "$(DEVELOPER_FRAMEWORKS_DIR)",
494 | );
495 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
496 | GCC_PREFIX_HEADER = "SHModalObject/SHModalObject-Prefix.pch";
497 | GCC_PREPROCESSOR_DEFINITIONS = (
498 | "DEBUG=1",
499 | "$(inherited)",
500 | );
501 | INFOPLIST_FILE = "SHModalObjectTests/SHModelObjectTests-Info.plist";
502 | PRODUCT_NAME = SHModelObjectTests;
503 | WRAPPER_EXTENSION = xctest;
504 | };
505 | name = Debug;
506 | };
507 | F2B4095E18BA16F500611B29 /* Release */ = {
508 | isa = XCBuildConfiguration;
509 | buildSettings = {
510 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
511 | FRAMEWORK_SEARCH_PATHS = (
512 | "$(SDKROOT)/Developer/Library/Frameworks",
513 | "$(inherited)",
514 | "$(DEVELOPER_FRAMEWORKS_DIR)",
515 | );
516 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
517 | GCC_PREFIX_HEADER = "SHModalObject/SHModalObject-Prefix.pch";
518 | INFOPLIST_FILE = "SHModalObjectTests/SHModelObjectTests-Info.plist";
519 | PRODUCT_NAME = SHModelObjectTests;
520 | WRAPPER_EXTENSION = xctest;
521 | };
522 | name = Release;
523 | };
524 | /* End XCBuildConfiguration section */
525 |
526 | /* Begin XCConfigurationList section */
527 | F2B4092818BA16F400611B29 /* Build configuration list for PBXProject "SHModelObject" */ = {
528 | isa = XCConfigurationList;
529 | buildConfigurations = (
530 | F2B4095718BA16F500611B29 /* Debug */,
531 | F2B4095818BA16F500611B29 /* Release */,
532 | );
533 | defaultConfigurationIsVisible = 0;
534 | defaultConfigurationName = Release;
535 | };
536 | F2B4095918BA16F500611B29 /* Build configuration list for PBXNativeTarget "SHModelObject" */ = {
537 | isa = XCConfigurationList;
538 | buildConfigurations = (
539 | F2B4095A18BA16F500611B29 /* Debug */,
540 | F2B4095B18BA16F500611B29 /* Release */,
541 | );
542 | defaultConfigurationIsVisible = 0;
543 | defaultConfigurationName = Release;
544 | };
545 | F2B4095C18BA16F500611B29 /* Build configuration list for PBXNativeTarget "SHModelObjectTests" */ = {
546 | isa = XCConfigurationList;
547 | buildConfigurations = (
548 | F2B4095D18BA16F500611B29 /* Debug */,
549 | F2B4095E18BA16F500611B29 /* Release */,
550 | );
551 | defaultConfigurationIsVisible = 0;
552 | defaultConfigurationName = Release;
553 | };
554 | /* End XCConfigurationList section */
555 | };
556 | rootObject = F2B4092518BA16F400611B29 /* Project object */;
557 | }
558 |
--------------------------------------------------------------------------------