├── .gitignore
├── .travis.yml
├── DocumentAssets
└── YTXRestfulModel01_1_X_X.png
├── Example
├── Podfile
├── Podfile.lock
├── Tests
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── YTXTestAFNetworkingRemoteCollection.h
│ ├── YTXTestAFNetworkingRemoteCollection.m
│ ├── YTXTestAFNetworkingRemoteModel.h
│ ├── YTXTestAFNetworkingRemoteModel.m
│ ├── YTXTestHumanModel.h
│ ├── YTXTestHumanModel.m
│ ├── YTXTestStudentCollection.h
│ ├── YTXTestStudentCollection.m
│ ├── YTXTestStudentModel.h
│ ├── YTXTestStudentModel.m
│ ├── YTXTestTeacherModel.h
│ ├── YTXTestTeacherModel.m
│ ├── db.json
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── service.json
│ ├── test_YTXRestfulModelAFNetworkingRemote.m
│ ├── test_YTXRestfulModelDB.m
│ └── test_YTXRestfulModelUserDefaultSpec.m
├── YTXRestfulModel.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── YTXRestfulModel-Example.xcscheme
└── YTXRestfulModel.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
├── Pod
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── Model
│ ├── YTXRestfulCollection.h
│ ├── YTXRestfulCollection.m
│ ├── YTXRestfulModel.h
│ └── YTXRestfulModel.m
│ ├── Protocol
│ ├── YTXRestfulModelDBProtocol.h
│ ├── YTXRestfulModelProtocol.h
│ ├── YTXRestfulModelRemoteProtocol.h
│ └── YTXRestfulModelStorageProtocol.h
│ ├── RACSupport
│ ├── YTXRestfulCollection+RACSupport.h
│ ├── YTXRestfulCollection+RACSupport.m
│ ├── YTXRestfulModel+RACSupport.h
│ ├── YTXRestfulModel+RACSupport.m
│ └── YTXRestfulModelRACSupport.h
│ └── Sync
│ ├── AFNetworkingRemoteSync
│ ├── AFNetworkingRemoteSync.h
│ └── AFNetworkingRemoteSync.m
│ ├── FMDBSync
│ ├── Category
│ │ ├── NSArray+YTXRestfulModelFMDBSync.h
│ │ ├── NSArray+YTXRestfulModelFMDBSync.m
│ │ ├── NSDate+YTXRestfulModelFMDBSync.h
│ │ ├── NSDate+YTXRestfulModelFMDBSync.m
│ │ ├── NSDictionary+YTXRestfulModelFMDBSync.h
│ │ ├── NSDictionary+YTXRestfulModelFMDBSync.m
│ │ ├── NSNumber+YTXRestfulModelFMDBSync.h
│ │ ├── NSNumber+YTXRestfulModelFMDBSync.m
│ │ ├── NSObject+YTXRestfulModelFMDBSync.h
│ │ ├── NSObject+YTXRestfulModelFMDBSync.m
│ │ ├── NSString+YTXRestfulModelFMDBSync.h
│ │ ├── NSString+YTXRestfulModelFMDBSync.m
│ │ ├── NSValue+YTXRestfulModelFMDBSync.h
│ │ └── NSValue+YTXRestfulModelFMDBSync.m
│ ├── YTXRestfulModelFMDBSync.h
│ └── YTXRestfulModelFMDBSync.m
│ └── UserDefaultStorageSync
│ ├── YTXRestfulModelUserDefaultStorageSync.h
│ └── YTXRestfulModelUserDefaultStorageSync.m
├── README.md
├── YTXRestfulModel.podspec
├── _Pods.xcodeproj
├── buildpod.sh
└── lint.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | Carthage
26 | # We recommend against adding the Pods directory to your .gitignore. However
27 | # you should judge for yourself, the pros and cons are mentioned at:
28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29 | #
30 | # Note: if you ignore the Pods directory, make sure to uncomment
31 | # `pod install` in .travis.yml
32 | #
33 | Pods/
34 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | language: objective-c
6 | osx_image: xcode7.2
7 | cache: cocoapods
8 | podfile: Example/Podfile
9 | before_install:
10 | - npm install -g json-server
11 | before_script:
12 | - gem install cocoapods --no-document -v 0.39.0 # Since Travis is not always on latest version
13 | - pod install --project-directory=Example
14 | script:
15 | - cd Example/Tests; json-server db.json & cd ../..
16 | - pwd
17 | - set -o pipefail && xcodebuild test -workspace Example/YTXRestfulModel.xcworkspace -scheme YTXRestfulModel-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=iPhone 6s,OS=9.2'| xcpretty
18 | - pod lib lint
--------------------------------------------------------------------------------
/DocumentAssets/YTXRestfulModel01_1_X_X.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baidao/YTXRestfulModel/1272d03b9d6675c1e2f14858bf0dc752b12f2a14/DocumentAssets/YTXRestfulModel01_1_X_X.png
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | target 'YTXRestfulModel_Tests' do
4 | pod "YTXRestfulModel", :path => "../", :subspecs => ["RACSupport", "AFNetworkingRemoteSync", "FMDBSync", "UserDefaultStorageSync"]
5 | pod 'Kiwi'
6 | end
7 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - AFNetworking (2.6.3):
3 | - AFNetworking/NSURLConnection (= 2.6.3)
4 | - AFNetworking/NSURLSession (= 2.6.3)
5 | - AFNetworking/Reachability (= 2.6.3)
6 | - AFNetworking/Security (= 2.6.3)
7 | - AFNetworking/Serialization (= 2.6.3)
8 | - AFNetworking/UIKit (= 2.6.3)
9 | - AFNetworking/NSURLConnection (2.6.3):
10 | - AFNetworking/Reachability
11 | - AFNetworking/Security
12 | - AFNetworking/Serialization
13 | - AFNetworking/NSURLSession (2.6.3):
14 | - AFNetworking/Reachability
15 | - AFNetworking/Security
16 | - AFNetworking/Serialization
17 | - AFNetworking/Reachability (2.6.3)
18 | - AFNetworking/Security (2.6.3)
19 | - AFNetworking/Serialization (2.6.3)
20 | - AFNetworking/UIKit (2.6.3):
21 | - AFNetworking/NSURLConnection
22 | - AFNetworking/NSURLSession
23 | - FMDB (2.6.2):
24 | - FMDB/standard (= 2.6.2)
25 | - FMDB/standard (2.6.2)
26 | - Kiwi (2.4.0)
27 | - Mantle (1.5.7):
28 | - Mantle/extobjc (= 1.5.7)
29 | - Mantle/extobjc (1.5.7)
30 | - ReactiveCocoa (2.3.1):
31 | - ReactiveCocoa/UI (= 2.3.1)
32 | - ReactiveCocoa/Core (2.3.1):
33 | - ReactiveCocoa/no-arc
34 | - ReactiveCocoa/no-arc (2.3.1)
35 | - ReactiveCocoa/UI (2.3.1):
36 | - ReactiveCocoa/Core
37 | - YTXRestfulModel/AFNetworkingRemoteSync (1.2.1):
38 | - AFNetworking (~> 2.6.3)
39 | - YTXRestfulModel/Default
40 | - YTXRestfulModel/Default (1.2.1):
41 | - Mantle (~> 1.5.7)
42 | - YTXRestfulModel/FMDBSync (1.2.1):
43 | - FMDB (~> 2.6)
44 | - YTXRestfulModel/Default
45 | - YTXRestfulModel/RACSupport (1.2.1):
46 | - ReactiveCocoa (~> 2.3.1)
47 | - YTXRestfulModel/Default
48 | - YTXRestfulModel/UserDefaultStorageSync (1.2.1):
49 | - YTXRestfulModel/Default
50 |
51 | DEPENDENCIES:
52 | - Kiwi
53 | - YTXRestfulModel/AFNetworkingRemoteSync (from `../`)
54 | - YTXRestfulModel/FMDBSync (from `../`)
55 | - YTXRestfulModel/RACSupport (from `../`)
56 | - YTXRestfulModel/UserDefaultStorageSync (from `../`)
57 |
58 | EXTERNAL SOURCES:
59 | YTXRestfulModel:
60 | :path: ../
61 |
62 | SPEC CHECKSUMS:
63 | AFNetworking: cb8d14a848e831097108418f5d49217339d4eb60
64 | FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a
65 | Kiwi: f49c9d54b28917df5928fe44968a39ed198cb8a8
66 | Mantle: 4af47cf9547a4d0ad145a48cd0be3b411a5ae2b8
67 | ReactiveCocoa: 3fe9b233ca6db810e86681b5749488564c1179a1
68 | YTXRestfulModel: 8c8b7a4c43af31c1ba6352e5782f4b122e531e51
69 |
70 | PODFILE CHECKSUM: b5cdcff3bd5d02bd4ef6d6ada4c385f3358ba536
71 |
72 | COCOAPODS: 1.0.1
73 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Prefix.pch:
--------------------------------------------------------------------------------
1 | // The contents of this file are implicitly included at the beginning of every test case source file.
2 |
3 | #ifdef __OBJC__
4 |
5 |
6 | #endif
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestAFNetworkingRemoteCollection.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestCollection.h
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 1/25/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "YTXTestAFNetworkingRemoteModel.h"
12 |
13 | @interface YTXTestAFNetworkingRemoteCollection : YTXRestfulCollection
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestAFNetworkingRemoteCollection.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestCollection.m
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 1/25/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestAFNetworkingRemoteCollection.h"
10 |
11 | #import
12 |
13 | #import
14 | #import
15 |
16 |
17 | @implementation YTXTestAFNetworkingRemoteCollection
18 |
19 | + (instancetype) shared
20 | {
21 | static YTXTestAFNetworkingRemoteCollection * collection;
22 | static dispatch_once_t onceToken;
23 | dispatch_once(&onceToken, ^{
24 | collection = [[[self class] alloc] init];
25 | });
26 | return collection;
27 | }
28 |
29 | - (instancetype)init
30 | {
31 | if (self = [super initWithModelClass: [YTXTestAFNetworkingRemoteModel class]]) {
32 | self.remoteSync = [AFNetworkingRemoteSync new];
33 | self.remoteSync.url = [NSURL URLWithString:@"http://localhost:3000/users"];
34 | }
35 | return self;
36 | }
37 |
38 | - (NSArray *)transformerProxyOfResponse:(id)response {
39 | return [MTLJSONAdapter modelsOfClass:[self modelClass] fromJSONArray:response error:nil];
40 | }
41 |
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestAFNetworkingRemoteModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestModel.h
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 1/25/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface YTXTestAFNetworkingRemoteModel : YTXRestfulModel
12 |
13 | @property (nonnull, nonatomic, strong) NSNumber *keyId;
14 | @property (nonnull, nonatomic, strong) NSNumber *userId; //可选属性为nullable 不可选为nonnull
15 | @property (nonnull, nonatomic, strong) NSString *title;
16 | @property (nonnull, nonatomic, strong) NSString *body;
17 |
18 | @end
19 |
20 | @interface YTXTestAFNetworkingRemoteToDoModel : YTXRestfulModel
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestAFNetworkingRemoteModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestModel.m
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 1/25/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestAFNetworkingRemoteModel.h"
10 |
11 | #import
12 |
13 | #import
14 | #import
15 |
16 | @implementation YTXTestAFNetworkingRemoteModel
17 |
18 | //可以重写init方法 改变sync的初始值
19 |
20 | + (instancetype) shared
21 | {
22 | static YTXTestAFNetworkingRemoteModel * model;
23 | static dispatch_once_t onceToken;
24 | dispatch_once(&onceToken, ^{
25 | model = [[[self class] alloc] init];
26 | });
27 | return model;
28 | }
29 |
30 | + (NSDictionary *)JSONKeyPathsByPropertyKey
31 | {
32 | return @{@"keyId": @"id"};
33 | }
34 |
35 | + (NSString *)primaryKey
36 | {
37 | return @"keyId";
38 | }
39 |
40 | - (instancetype)init {
41 | if (self = [super init]) {
42 | self.remoteSync = [AFNetworkingRemoteSync syncWithPrimaryKey:[[self class] syncPrimaryKey]];
43 | self.remoteSync.urlHookBlock = ^NSURL * _Nonnull{
44 | return [NSURL URLWithString:@"http://localhost:3000/users"];
45 | };
46 | }
47 | return self;
48 | }
49 |
50 | //mantle Transoformer
51 | + (MTLValueTransformer *) bodyJSONTransformer
52 | {
53 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString * body) {
54 | return body;
55 | } reverseBlock:^(NSString * body) {
56 | return body;
57 | }];
58 | }
59 |
60 |
61 | @end
62 |
63 | @implementation YTXTestAFNetworkingRemoteToDoModel
64 |
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestHumanModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestHumanModel.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/2/25.
6 | // Copyright © 2016年 caojun. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface YTXTestHumanModel : YTXRestfulModel
12 |
13 | @property (nonnull, nonatomic, copy) NSNumber * identify;
14 | @property (nonnull, nonatomic, copy) NSString * name;
15 | @property (nonnull, nonatomic, strong) NSDate * birthday;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestHumanModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestHumanModel.m
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/2/25.
6 | // Copyright © 2016年 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestHumanModel.h"
10 |
11 | @implementation YTXTestHumanModel
12 |
13 | + (BOOL) autoCreateTable
14 | {
15 | return YES;
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestStudentCollection.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestStudentCollection.h
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 3/3/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface YTXTestStudentCollection : YTXRestfulCollection
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestStudentCollection.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestStudentCollection.m
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 3/3/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestStudentCollection.h"
10 | #import "YTXTestStudentModel.h"
11 |
12 | #import
13 | #import
14 |
15 | @implementation YTXTestStudentCollection
16 |
17 | + (instancetype) shared
18 | {
19 | static YTXTestStudentCollection * collection;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | collection = [[[self class] alloc] init];
23 | });
24 | return collection;
25 | }
26 |
27 | - (instancetype)init
28 | {
29 | if (self = [super initWithModelClass: [YTXTestStudentModel class]]) {
30 | }
31 | return self;
32 | }
33 |
34 | - (NSArray *)transformerProxyOfResponse:(id)response {
35 | return [MTLJSONAdapter modelsOfClass:[self modelClass] fromJSONArray:response error:nil];
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestStudentModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestSubModel.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/2/25.
6 | // Copyright © 2016年 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestHumanModel.h"
10 |
11 | typedef NS_ENUM(NSUInteger, Gender) {
12 | GenderMale,
13 | GenderFemale
14 | };
15 |
16 | @interface YTXTestStudentModel : YTXTestHumanModel
17 |
18 | @property (nonnull, nonatomic, strong ,readonly) NSString *IQ;
19 | @property (nonnull, nonatomic, strong) NSArray * friendNames;
20 | @property (nonnull, nonatomic, strong) NSDictionary * properties;
21 | @property (nonnull, nonatomic, strong) NSDate * startSchoolDate;
22 | @property (nonatomic, assign) NSUInteger age;
23 | @property (nonatomic, assign) BOOL stupid;
24 | @property (nonatomic, assign) float floatNumber;
25 | @property (nonatomic, assign) Gender gender;
26 | @property (nonatomic, assign) double score;
27 | @property (nonatomic, assign) CGPoint point;
28 |
29 | @property (nonnull, nonatomic, strong) NSNumber *teacherId;
30 |
31 | + (nullable NSNumber *) newMigrationVersion;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestStudentModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestStudentModel.m
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/2/25.
6 | // Copyright © 2016年 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestStudentModel.h"
10 |
11 | #import
12 | #import
13 | #import
14 | #import
15 |
16 | @implementation YTXTestStudentModel
17 |
18 | + (instancetype) shared
19 | {
20 | static YTXTestStudentModel * model;
21 | static dispatch_once_t onceToken;
22 | dispatch_once(&onceToken, ^{
23 | model = [[[self class] alloc] init];
24 | });
25 | return model;
26 | }
27 |
28 | - (instancetype)init
29 | {
30 | if (self = [super init]) {
31 | _IQ = @"100";
32 | }
33 | return self;
34 | }
35 |
36 | + (NSDictionary *)JSONKeyPathsByPropertyKey
37 | {
38 | return @{@"identify": @"id"};
39 | }
40 |
41 | + (NSString *)primaryKey
42 | {
43 | return @"identify";
44 | }
45 |
46 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey
47 | {
48 | NSMutableDictionary * tmpDictionary = [super tableKeyPathsByPropertyKey];
49 |
50 | YTXRestfulModelDBSerializingModel * genderStruct = tmpDictionary[@"gender"];
51 | genderStruct.defaultValue = [@(GenderFemale) sqliteValue];
52 | tmpDictionary[@"gender"] = genderStruct;
53 |
54 | YTXRestfulModelDBSerializingModel * scoreStruct = tmpDictionary[@"score"];
55 | scoreStruct.unique = YES;
56 | tmpDictionary[@"score"] = scoreStruct;
57 |
58 | YTXRestfulModelDBSerializingModel * teacherIdStruct = tmpDictionary[@"teacherId"];
59 | teacherIdStruct.defaultValue = [@1 sqliteValue];
60 | teacherIdStruct.foreignClassName = @"YTXTestTeacherModel";
61 | tmpDictionary[@"teacherId"] = teacherIdStruct;
62 |
63 | return tmpDictionary;
64 | }
65 |
66 | + (nullable NSNumber *) currentMigrationVersion
67 | {
68 | return @0;
69 | }
70 |
71 | + (BOOL) autoAlterTable
72 | {
73 | return NO;
74 | }
75 |
76 | + (BOOL) autoCreateTable
77 | {
78 | return YES;
79 | }
80 |
81 | + (void) migrationsMethodWithSync:(nonnull id)sync;
82 | {
83 | YTXRestfulModelDBMigrationEntity *migration = [YTXRestfulModelDBMigrationEntity new];
84 | migration.version = @1;
85 | migration.block = ^(_Nonnull id db, NSError * _Nullable * _Nullable error) {
86 | YTXRestfulModelDBSerializingModel *runtimePStruct = [YTXRestfulModelDBSerializingModel new];
87 | runtimePStruct.objectClass = @"NSString";
88 | runtimePStruct.columnName = @"runtimeP";
89 | runtimePStruct.modelName = @"runtimeP";
90 | runtimePStruct.isPrimaryKey = NO;
91 | runtimePStruct.autoincrement = NO;
92 | runtimePStruct.unique = NO;
93 | [sync createColumnWithDB:db structSync:runtimePStruct error:error];
94 | };
95 | [sync migrate:migration];
96 | }
97 |
98 | + (MTLValueTransformer *)startSchoolDateJSONTransformer {
99 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSNumber *timestamp) {
100 | return [NSDate dateWithTimeIntervalSince1970: timestamp.longLongValue / 1000];
101 | } reverseBlock:^(NSDate *date) {
102 | return @((SInt64)(date.timeIntervalSince1970 * 1000));
103 | }];
104 | }
105 |
106 | + (MTLValueTransformer *)birthdayJSONTransformer {
107 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSNumber *timestamp) {
108 | return [NSDate dateWithTimeIntervalSince1970: timestamp.longLongValue / 1000];
109 | } reverseBlock:^(NSDate *date) {
110 | return @((SInt64)(date.timeIntervalSince1970 * 1000));
111 | }];
112 | }
113 |
114 | + (nullable NSNumber *) newMigrationVersion
115 | {
116 | return @1;
117 | }
118 |
119 | @end
120 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestTeacherModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestTeacherModel.h
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 3/2/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestHumanModel.h"
10 |
11 | @interface YTXTestTeacherModel : YTXTestHumanModel
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/Tests/YTXTestTeacherModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXTestTeacherModel.m
3 | // YTXRestfulModel
4 | //
5 | // Created by Chuan on 3/2/16.
6 | // Copyright © 2016 caojun. All rights reserved.
7 | //
8 |
9 | #import "YTXTestTeacherModel.h"
10 | #import
11 |
12 | @implementation YTXTestTeacherModel
13 |
14 | + (instancetype) shared
15 | {
16 | static YTXTestTeacherModel * model;
17 | static dispatch_once_t onceToken;
18 | dispatch_once(&onceToken, ^{
19 | model = [[[self class] alloc] init];
20 | });
21 | return model;
22 | }
23 |
24 | + (NSDictionary *)JSONKeyPathsByPropertyKey
25 | {
26 | return @{@"identify": @"id"};
27 | }
28 |
29 | + (NSString *)primaryKey
30 | {
31 | return @"identify";
32 | }
33 |
34 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey
35 | {
36 | NSMutableDictionary * tmpDictionary = [super tableKeyPathsByPropertyKey];
37 |
38 | YTXRestfulModelDBSerializingModel * nameStruct = tmpDictionary[@"name"];
39 |
40 | nameStruct.defaultValue = [@"Edward" sqliteValue];
41 |
42 | tmpDictionary[@"name"] = nameStruct;
43 |
44 | return tmpDictionary;
45 | }
46 |
47 | + (nullable NSNumber *) currentMigrationVersion
48 | {
49 | return @0;
50 | }
51 |
52 | + (nullable NSNumber *) newMigrationVersion
53 | {
54 | return @1;
55 | }
56 |
57 | + (BOOL) autoAlterTable
58 | {
59 | return YES;
60 | }
61 |
62 | + (BOOL) autoCreateTable
63 | {
64 | return YES;
65 | }
66 |
67 | + (BOOL) isPrimaryKeyAutoincrement
68 | {
69 | return NO;
70 | }
71 |
72 | + (nonnull NSMutableDictionary *> *) _tableKeyPathsByPropertyKeyMapRuntime
73 | {
74 | static NSMutableDictionary *> * map;
75 |
76 | if (map == nil) {
77 | map = [NSMutableDictionary dictionary];
78 | }
79 |
80 | return map;
81 | }
82 |
83 | @end
84 |
--------------------------------------------------------------------------------
/Example/Tests/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "posts": [
3 | {
4 | "body": "改过了",
5 | "id": 1,
6 | "title": "ytx test hahahaha",
7 | "userId": 1
8 | },
9 | {
10 | "body": "teststeststesettsetsetttsetttest",
11 | "title": "ytx test hahahaha",
12 | "userId": 1,
13 | "id": 2
14 | },
15 | {
16 | "body": "teststeststesettsetsetttsetttest",
17 | "title": "ytx test hahahaha",
18 | "userId": 1,
19 | "id": 3
20 | },
21 | {
22 | "body": "I Love You",
23 | "title": "同一个",
24 | "userId": 1,
25 | "id": 4
26 | },
27 | {
28 | "body": "I Love You",
29 | "title": "同一个",
30 | "userId": 1,
31 | "id": 5
32 | },
33 | {
34 | "body": "I Love You",
35 | "title": "同一个",
36 | "userId": 1,
37 | "id": 6
38 | },
39 | {
40 | "body": "I Love You",
41 | "title": "同一个",
42 | "userId": 1,
43 | "id": 7
44 | },
45 | {
46 | "body": "I Love You",
47 | "dbSync": "",
48 | "title": "同一个",
49 | "userId": 1,
50 | "id": 8
51 | },
52 | {
53 | "body": "I Love You",
54 | "dbSync": "",
55 | "title": "同一个",
56 | "userId": 1,
57 | "id": 9
58 | },
59 | {
60 | "body": "I Love You",
61 | "dbSync": "",
62 | "title": "同一个",
63 | "userId": 1,
64 | "id": 10
65 | },
66 | {
67 | "body": "I Love You",
68 | "title": "Hello World",
69 | "userId": 1,
70 | "id": 11
71 | },
72 | {
73 | "id": 12
74 | },
75 | {
76 | "title": "更新了",
77 | "id": 13
78 | },
79 | {
80 | "id": 14
81 | },
82 | {
83 | "body": "I Love You",
84 | "id": 15
85 | },
86 | {
87 | "title": "同一个",
88 | "id": 16
89 | },
90 | {
91 | "title": "通过hook改了",
92 | "id": 17
93 | },
94 | {
95 | "title": "通过hook改了",
96 | "id": 18
97 | },
98 | {
99 | "title": "hook的优先级低于方法传入参数和model属性",
100 | "id": 19
101 | },
102 | {
103 | "id": 20
104 | },
105 | {
106 | "title": "更新了",
107 | "id": 21
108 | },
109 | {
110 | "id": 22
111 | },
112 | {
113 | "body": "I Love You",
114 | "id": 23
115 | },
116 | {
117 | "title": "同一个",
118 | "id": 24
119 | },
120 | {
121 | "title": "通过hook改了",
122 | "id": 25
123 | },
124 | {
125 | "title": "通过hook改了",
126 | "id": 26
127 | },
128 | {
129 | "title": "hook的优先级低于方法传入参数和model属性",
130 | "id": 27
131 | },
132 | {
133 | "title": "通过hook改了",
134 | "id": 28
135 | },
136 | {
137 | "title": "通过hook改了",
138 | "id": 29
139 | },
140 | {
141 | "title": "hook的优先级低于方法传入参数和model属性",
142 | "id": 30
143 | },
144 | {
145 | "title": "通过hook改了",
146 | "id": 31
147 | },
148 | {
149 | "title": "通过hook改了",
150 | "id": 32
151 | },
152 | {
153 | "title": "hook的优先级低于方法传入参数和model属性",
154 | "id": 33
155 | },
156 | {
157 | "title": "通过hook改了",
158 | "id": 34
159 | },
160 | {
161 | "title": "通过hook改了",
162 | "id": 35
163 | },
164 | {
165 | "title": "hook的优先级低于方法传入参数和model属性",
166 | "id": 36
167 | },
168 | {
169 | "title": "通过hook改了",
170 | "id": 37
171 | },
172 | {
173 | "title": "通过hook改了",
174 | "id": 38
175 | },
176 | {
177 | "title": "hook的优先级低于方法传入参数和model属性",
178 | "id": 39
179 | },
180 | {
181 | "title": "通过hook改了",
182 | "id": 40
183 | },
184 | {
185 | "title": "通过hook改了",
186 | "id": 41
187 | },
188 | {
189 | "title": "hook的优先级低于方法传入参数和model属性",
190 | "id": 42
191 | },
192 | {
193 | "title": "通过hook改了",
194 | "id": 43
195 | },
196 | {
197 | "title": "通过hook改了",
198 | "id": 44
199 | },
200 | {
201 | "title": "hook的优先级低于方法传入参数和model属性",
202 | "id": 45
203 | },
204 | {
205 | "title": "通过hook改了",
206 | "id": 46
207 | },
208 | {
209 | "title": "通过hook改了",
210 | "id": 47
211 | },
212 | {
213 | "title": "hook的优先级低于方法传入参数和model属性",
214 | "id": 48
215 | },
216 | {
217 | "title": "通过hook改了",
218 | "id": 49
219 | },
220 | {
221 | "title": "通过hook改了",
222 | "id": 50
223 | },
224 | {
225 | "title": "hook的优先级低于方法传入参数和model属性",
226 | "id": 51
227 | },
228 | {
229 | "title": "通过hook改了",
230 | "id": 52
231 | },
232 | {
233 | "title": "hook的优先级低于方法传入参数和model属性",
234 | "id": 53
235 | },
236 | {
237 | "title": "通过hook改了",
238 | "id": 54
239 | },
240 | {
241 | "title": "通过hook改了",
242 | "id": 55
243 | },
244 | {
245 | "title": "通过hook改了",
246 | "id": 56
247 | },
248 | {
249 | "title": "hook的优先级低于方法传入参数和model属性",
250 | "id": 57
251 | },
252 | {
253 | "title": "通过hook改了",
254 | "id": 58
255 | },
256 | {
257 | "title": "通过hook改了",
258 | "id": 59
259 | },
260 | {
261 | "title": "hook的优先级低于方法传入参数和model属性",
262 | "id": 60
263 | },
264 | {
265 | "title": "通过hook改了",
266 | "id": 61
267 | },
268 | {
269 | "title": "通过hook改了",
270 | "id": 62
271 | },
272 | {
273 | "title": "hook的优先级低于方法传入参数和model属性",
274 | "id": 63
275 | },
276 | {
277 | "title": "通过hook改了",
278 | "id": 64
279 | },
280 | {
281 | "title": "通过hook改了",
282 | "id": 65
283 | },
284 | {
285 | "title": "hook的优先级低于方法传入参数和model属性",
286 | "id": 66
287 | },
288 | {
289 | "title": "通过hook改了",
290 | "id": 67
291 | },
292 | {
293 | "title": "通过hook改了",
294 | "id": 68
295 | },
296 | {
297 | "title": "hook的优先级低于方法传入参数和model属性",
298 | "id": 69
299 | },
300 | {
301 | "title": "通过hook改了",
302 | "id": 70
303 | },
304 | {
305 | "title": "通过hook改了",
306 | "id": 71
307 | },
308 | {
309 | "title": "hook的优先级低于方法传入参数和model属性",
310 | "id": 72
311 | },
312 | {
313 | "title": "通过hook改了",
314 | "id": 73
315 | },
316 | {
317 | "title": "通过hook改了",
318 | "id": 74
319 | },
320 | {
321 | "title": "hook的优先级低于方法传入参数和model属性",
322 | "id": 75
323 | },
324 | {
325 | "title": "通过hook改了",
326 | "id": 76
327 | },
328 | {
329 | "title": "通过hook改了",
330 | "id": 77
331 | },
332 | {
333 | "title": "hook的优先级低于方法传入参数和model属性",
334 | "id": 78
335 | },
336 | {
337 | "title": "通过hook改了",
338 | "id": 79
339 | },
340 | {
341 | "title": "通过hook改了",
342 | "id": 80
343 | },
344 | {
345 | "title": "hook的优先级低于方法传入参数和model属性",
346 | "id": 81
347 | },
348 | {
349 | "title": "通过hook改了",
350 | "id": 82
351 | },
352 | {
353 | "title": "通过hook改了",
354 | "id": 83
355 | },
356 | {
357 | "title": "hook的优先级低于方法传入参数和model属性",
358 | "id": 84
359 | },
360 | {
361 | "title": "通过hook改了",
362 | "id": 85
363 | },
364 | {
365 | "title": "通过hook改了",
366 | "id": 86
367 | },
368 | {
369 | "title": "hook的优先级低于方法传入参数和model属性",
370 | "id": 87
371 | },
372 | {
373 | "title": "CaoJun",
374 | "id": 88
375 | },
376 | {
377 | "title": "CaoJun",
378 | "id": 89
379 | },
380 | {
381 | "title": "CaoJun",
382 | "id": 90
383 | },
384 | {
385 | "title": "通过hook改了",
386 | "id": 91
387 | },
388 | {
389 | "title": "通过hook改了",
390 | "id": 92
391 | },
392 | {
393 | "title": "hook的优先级低于方法传入参数和model属性",
394 | "id": 93
395 | },
396 | {
397 | "title": "CaoJun",
398 | "id": 94
399 | },
400 | {
401 | "title": "CaoJun",
402 | "id": 95
403 | },
404 | {
405 | "title": "CaoJun",
406 | "id": 96
407 | },
408 | {
409 | "title": "通过hook改了",
410 | "id": 97
411 | },
412 | {
413 | "title": "通过hook改了",
414 | "id": 98
415 | },
416 | {
417 | "title": "hook的优先级低于方法传入参数和model属性",
418 | "id": 99
419 | },
420 | {
421 | "title": "CaoJun",
422 | "id": 100
423 | },
424 | {
425 | "title": "CaoJun",
426 | "id": 101
427 | },
428 | {
429 | "title": "CaoJun",
430 | "id": 102
431 | },
432 | {
433 | "title": "通过hook改了",
434 | "id": 103
435 | },
436 | {
437 | "title": "通过hook改了",
438 | "id": 104
439 | },
440 | {
441 | "title": "hook的优先级低于方法传入参数和model属性",
442 | "id": 105
443 | },
444 | {
445 | "title": "CaoJun",
446 | "id": 106
447 | },
448 | {
449 | "title": "CaoJun",
450 | "id": 107
451 | },
452 | {
453 | "title": "CaoJun",
454 | "id": 108
455 | },
456 | {
457 | "title": "通过hook改了",
458 | "id": 109
459 | },
460 | {
461 | "title": "通过hook改了",
462 | "id": 110
463 | },
464 | {
465 | "title": "hook的优先级低于方法传入参数和model属性",
466 | "id": 111
467 | },
468 | {
469 | "title": "通过hook改了",
470 | "id": 112
471 | },
472 | {
473 | "title": "通过hook改了",
474 | "id": 113
475 | },
476 | {
477 | "title": "hook的优先级低于方法传入参数和model属性",
478 | "id": 114
479 | },
480 | {
481 | "title": "CaoJun",
482 | "id": 115
483 | },
484 | {
485 | "title": "CaoJun",
486 | "id": 116
487 | },
488 | {
489 | "title": "通过hook改了",
490 | "id": 117
491 | },
492 | {
493 | "title": "通过hook改了",
494 | "id": 118
495 | },
496 | {
497 | "title": "hook的优先级低于方法传入参数和model属性",
498 | "id": 119
499 | },
500 | {
501 | "title": "CaoJun",
502 | "id": 120
503 | },
504 | {
505 | "title": "CaoJun",
506 | "id": 121
507 | },
508 | {
509 | "title": "CaoJun",
510 | "id": 122
511 | },
512 | {
513 | "title": "CaoJun",
514 | "id": 123
515 | },
516 | {
517 | "title": "CaoJun",
518 | "id": 124
519 | }
520 | ],
521 | "comments": [
522 | {
523 | "id": 1,
524 | "body": "some comment",
525 | "postId": 1
526 | }
527 | ],
528 | "users": [
529 | {
530 | "body": "改过了",
531 | "id": 1,
532 | "title": "ytx test hahahaha",
533 | "userId": 1
534 | },
535 | {
536 | "body": "teststeststesettsetsetttsetttest",
537 | "title": "ytx test hahahaha",
538 | "userId": 1,
539 | "id": 2
540 | },
541 | {
542 | "body": "teststeststesettsetsetttsetttest",
543 | "title": "ytx test hahahaha",
544 | "userId": 1,
545 | "id": 3
546 | },
547 | {
548 | "body": "I Love You",
549 | "title": "同一个",
550 | "userId": 1,
551 | "id": 4
552 | },
553 | {
554 | "body": "I Love You",
555 | "title": "同一个",
556 | "userId": 1,
557 | "id": 5
558 | },
559 | {
560 | "body": "I Love You",
561 | "title": "同一个",
562 | "userId": 1,
563 | "id": 6
564 | },
565 | {
566 | "body": "I Love You",
567 | "title": "同一个",
568 | "userId": 1,
569 | "id": 7
570 | },
571 | {
572 | "body": "I Love You",
573 | "dbSync": "",
574 | "title": "同一个",
575 | "userId": 1,
576 | "id": 8
577 | },
578 | {
579 | "body": "I Love You",
580 | "dbSync": "",
581 | "title": "同一个",
582 | "userId": 1,
583 | "id": 9
584 | },
585 | {
586 | "body": "I Love You",
587 | "dbSync": "",
588 | "title": "同一个",
589 | "userId": 1,
590 | "id": 10
591 | },
592 | {
593 | "body": "I Love You",
594 | "title": "Hello World",
595 | "userId": 1,
596 | "id": 11
597 | },
598 | {
599 | "id": 12
600 | },
601 | {
602 | "title": "更新了",
603 | "id": 13
604 | },
605 | {
606 | "id": 14
607 | },
608 | {
609 | "body": "I Love You",
610 | "id": 15
611 | },
612 | {
613 | "title": "同一个",
614 | "id": 16
615 | },
616 | {
617 | "title": "通过hook改了",
618 | "id": 17
619 | },
620 | {
621 | "title": "通过hook改了",
622 | "id": 18
623 | },
624 | {
625 | "title": "hook的优先级低于方法传入参数和model属性",
626 | "id": 19
627 | },
628 | {
629 | "id": 20
630 | },
631 | {
632 | "title": "更新了",
633 | "id": 21
634 | },
635 | {
636 | "id": 22
637 | },
638 | {
639 | "body": "I Love You",
640 | "id": 23
641 | },
642 | {
643 | "title": "同一个",
644 | "id": 24
645 | },
646 | {
647 | "title": "通过hook改了",
648 | "id": 25
649 | },
650 | {
651 | "title": "通过hook改了",
652 | "id": 26
653 | },
654 | {
655 | "title": "hook的优先级低于方法传入参数和model属性",
656 | "id": 27
657 | },
658 | {
659 | "id": 28
660 | },
661 | {
662 | "title": "通过hook改了",
663 | "id": 29
664 | },
665 | {
666 | "title": "hook的优先级低于方法传入参数和model属性",
667 | "id": 30
668 | },
669 | {
670 | "title": "通过hook改了",
671 | "id": 31
672 | },
673 | {
674 | "title": "通过hook改了",
675 | "id": 32
676 | },
677 | {
678 | "title": "通过hook改了",
679 | "id": 33
680 | },
681 | {
682 | "title": "hook的优先级低于方法传入参数和model属性",
683 | "id": 34
684 | },
685 | {
686 | "title": "通过hook改了",
687 | "id": 35
688 | },
689 | {
690 | "title": "hook的优先级低于方法传入参数和model属性",
691 | "id": 36
692 | },
693 | {
694 | "title": "通过hook改了",
695 | "id": 37
696 | },
697 | {
698 | "title": "通过hook改了",
699 | "id": 38
700 | },
701 | {
702 | "title": "通过hook改了",
703 | "id": 39
704 | },
705 | {
706 | "title": "hook的优先级低于方法传入参数和model属性",
707 | "id": 40
708 | },
709 | {
710 | "title": "通过hook改了",
711 | "id": 41
712 | },
713 | {
714 | "title": "通过hook改了",
715 | "id": 42
716 | },
717 | {
718 | "title": "hook的优先级低于方法传入参数和model属性",
719 | "id": 43
720 | },
721 | {
722 | "title": "通过hook改了",
723 | "id": 44
724 | },
725 | {
726 | "title": "hook的优先级低于方法传入参数和model属性",
727 | "id": 45
728 | },
729 | {
730 | "title": "通过hook改了",
731 | "id": 46
732 | },
733 | {
734 | "title": "通过hook改了",
735 | "id": 47
736 | },
737 | {
738 | "title": "通过hook改了",
739 | "id": 48
740 | },
741 | {
742 | "title": "hook的优先级低于方法传入参数和model属性",
743 | "id": 49
744 | },
745 | {
746 | "title": "通过hook改了",
747 | "id": 50
748 | },
749 | {
750 | "title": "hook的优先级低于方法传入参数和model属性",
751 | "id": 51
752 | },
753 | {
754 | "title": "通过hook改了",
755 | "id": 52
756 | },
757 | {
758 | "title": "hook的优先级低于方法传入参数和model属性",
759 | "id": 53
760 | },
761 | {
762 | "title": "通过hook改了",
763 | "id": 54
764 | },
765 | {
766 | "title": "通过hook改了",
767 | "id": 55
768 | },
769 | {
770 | "title": "通过hook改了",
771 | "id": 56
772 | },
773 | {
774 | "title": "通过hook改了",
775 | "id": 57
776 | },
777 | {
778 | "title": "hook的优先级低于方法传入参数和model属性",
779 | "id": 58
780 | },
781 | {
782 | "title": "通过hook改了",
783 | "id": 59
784 | },
785 | {
786 | "title": "通过hook改了",
787 | "id": 60
788 | },
789 | {
790 | "title": "hook的优先级低于方法传入参数和model属性",
791 | "id": 61
792 | },
793 | {
794 | "title": "通过hook改了",
795 | "id": 62
796 | },
797 | {
798 | "title": "hook的优先级低于方法传入参数和model属性",
799 | "id": 63
800 | },
801 | {
802 | "title": "通过hook改了",
803 | "id": 64
804 | },
805 | {
806 | "title": "通过hook改了",
807 | "id": 65
808 | },
809 | {
810 | "title": "通过hook改了",
811 | "id": 66
812 | },
813 | {
814 | "title": "hook的优先级低于方法传入参数和model属性",
815 | "id": 67
816 | },
817 | {
818 | "title": "通过hook改了",
819 | "id": 68
820 | },
821 | {
822 | "title": "hook的优先级低于方法传入参数和model属性",
823 | "id": 69
824 | },
825 | {
826 | "title": "通过hook改了",
827 | "id": 70
828 | },
829 | {
830 | "title": "通过hook改了",
831 | "id": 71
832 | },
833 | {
834 | "title": "通过hook改了",
835 | "id": 72
836 | },
837 | {
838 | "title": "hook的优先级低于方法传入参数和model属性",
839 | "id": 73
840 | },
841 | {
842 | "title": "通过hook改了",
843 | "id": 74
844 | },
845 | {
846 | "title": "hook的优先级低于方法传入参数和model属性",
847 | "id": 75
848 | },
849 | {
850 | "title": "通过hook改了",
851 | "id": 76
852 | },
853 | {
854 | "title": "通过hook改了",
855 | "id": 77
856 | },
857 | {
858 | "title": "通过hook改了",
859 | "id": 78
860 | },
861 | {
862 | "title": "hook的优先级低于方法传入参数和model属性",
863 | "id": 79
864 | },
865 | {
866 | "title": "通过hook改了",
867 | "id": 80
868 | },
869 | {
870 | "title": "hook的优先级低于方法传入参数和model属性",
871 | "id": 81
872 | },
873 | {
874 | "title": "通过hook改了",
875 | "id": 82
876 | },
877 | {
878 | "title": "通过hook改了",
879 | "id": 83
880 | },
881 | {
882 | "title": "通过hook改了",
883 | "id": 84
884 | },
885 | {
886 | "title": "hook的优先级低于方法传入参数和model属性",
887 | "id": 85
888 | },
889 | {
890 | "title": "通过hook改了",
891 | "id": 86
892 | },
893 | {
894 | "title": "hook的优先级低于方法传入参数和model属性",
895 | "id": 87
896 | },
897 | {
898 | "title": "通过hook改了",
899 | "id": 88
900 | },
901 | {
902 | "title": "通过hook改了",
903 | "id": 89
904 | },
905 | {
906 | "title": "通过hook改了",
907 | "id": 90
908 | },
909 | {
910 | "title": "hook的优先级低于方法传入参数和model属性",
911 | "id": 91
912 | },
913 | {
914 | "title": "通过hook改了",
915 | "id": 92
916 | },
917 | {
918 | "title": "通过hook改了",
919 | "id": 93
920 | },
921 | {
922 | "title": "hook的优先级低于方法传入参数和model属性",
923 | "id": 94
924 | },
925 | {
926 | "title": "通过hook改了",
927 | "id": 95
928 | },
929 | {
930 | "title": "hook的优先级低于方法传入参数和model属性",
931 | "id": 96
932 | },
933 | {
934 | "title": "通过hook改了",
935 | "id": 97
936 | },
937 | {
938 | "title": "通过hook改了",
939 | "id": 98
940 | },
941 | {
942 | "title": "hook的优先级低于方法传入参数和model属性",
943 | "id": 99
944 | },
945 | {
946 | "title": "通过hook改了",
947 | "id": 100
948 | },
949 | {
950 | "title": "通过hook改了",
951 | "id": 101
952 | },
953 | {
954 | "title": "通过hook改了",
955 | "id": 102
956 | },
957 | {
958 | "title": "hook的优先级低于方法传入参数和model属性",
959 | "id": 103
960 | },
961 | {
962 | "title": "通过hook改了",
963 | "id": 104
964 | },
965 | {
966 | "title": "通过hook改了",
967 | "id": 105
968 | },
969 | {
970 | "title": "hook的优先级低于方法传入参数和model属性",
971 | "id": 106
972 | },
973 | {
974 | "title": "通过hook改了",
975 | "id": 107
976 | },
977 | {
978 | "title": "通过hook改了",
979 | "id": 108
980 | },
981 | {
982 | "title": "hook的优先级低于方法传入参数和model属性",
983 | "id": 109
984 | },
985 | {
986 | "title": "通过hook改了",
987 | "id": 110
988 | },
989 | {
990 | "title": "通过hook改了",
991 | "id": 111
992 | },
993 | {
994 | "title": "hook的优先级低于方法传入参数和model属性",
995 | "id": 112
996 | },
997 | {
998 | "title": "通过hook改了",
999 | "id": 113
1000 | },
1001 | {
1002 | "title": "hook的优先级低于方法传入参数和model属性",
1003 | "id": 114
1004 | },
1005 | {
1006 | "title": "通过hook改了",
1007 | "id": 115
1008 | },
1009 | {
1010 | "title": "CaoJun",
1011 | "id": 116
1012 | },
1013 | {
1014 | "title": "CaoJun",
1015 | "id": 117
1016 | },
1017 | {
1018 | "title": "通过hook改了",
1019 | "id": 118
1020 | },
1021 | {
1022 | "title": "hook的优先级低于方法传入参数和model属性",
1023 | "id": 119
1024 | },
1025 | {
1026 | "title": "通过hook改了",
1027 | "id": 120
1028 | },
1029 | {
1030 | "title": "CaoJun",
1031 | "id": 121
1032 | },
1033 | {
1034 | "title": "CaoJun",
1035 | "id": 122
1036 | },
1037 | {
1038 | "title": "通过hook改了",
1039 | "id": 123
1040 | },
1041 | {
1042 | "title": "通过hook改了",
1043 | "id": 124
1044 | },
1045 | {
1046 | "title": "hook的优先级低于方法传入参数和model属性",
1047 | "id": 125
1048 | },
1049 | {
1050 | "title": "CaoJun",
1051 | "id": 126
1052 | },
1053 | {
1054 | "title": "CaoJun",
1055 | "id": 127
1056 | },
1057 | {
1058 | "title": "通过hook改了",
1059 | "id": 128
1060 | },
1061 | {
1062 | "title": "通过hook改了",
1063 | "id": 129
1064 | },
1065 | {
1066 | "title": "hook的优先级低于方法传入参数和model属性",
1067 | "id": 130
1068 | },
1069 | {
1070 | "title": "CaoJun",
1071 | "id": 131
1072 | },
1073 | {
1074 | "title": "CaoJun",
1075 | "id": 132
1076 | },
1077 | {
1078 | "title": "通过hook改了",
1079 | "id": 133
1080 | },
1081 | {
1082 | "title": "通过hook改了",
1083 | "id": 134
1084 | },
1085 | {
1086 | "title": "hook的优先级低于方法传入参数和model属性",
1087 | "id": 135
1088 | },
1089 | {
1090 | "title": "CaoJun",
1091 | "id": 136
1092 | },
1093 | {
1094 | "title": "CaoJun",
1095 | "id": 137
1096 | },
1097 | {
1098 | "title": "通过hook改了",
1099 | "id": 138
1100 | },
1101 | {
1102 | "title": "hook的优先级低于方法传入参数和model属性",
1103 | "id": 139
1104 | },
1105 | {
1106 | "title": "通过hook改了",
1107 | "id": 140
1108 | },
1109 | {
1110 | "title": "hook的优先级低于方法传入参数和model属性",
1111 | "id": 141
1112 | },
1113 | {
1114 | "title": "通过hook改了",
1115 | "id": 142
1116 | },
1117 | {
1118 | "title": "通过hook改了",
1119 | "id": 143
1120 | },
1121 | {
1122 | "title": "通过hook改了",
1123 | "id": 144
1124 | },
1125 | {
1126 | "title": "通过hook改了",
1127 | "id": 145
1128 | },
1129 | {
1130 | "title": "hook的优先级低于方法传入参数和model属性",
1131 | "id": 146
1132 | },
1133 | {
1134 | "title": "通过hook改了",
1135 | "id": 147
1136 | },
1137 | {
1138 | "title": "hook的优先级低于方法传入参数和model属性",
1139 | "id": 148
1140 | },
1141 | {
1142 | "title": "通过hook改了",
1143 | "id": 149
1144 | }
1145 | ],
1146 | "todos": [
1147 | {
1148 | "id": 1,
1149 | "body": "some comment",
1150 | "userId": 1
1151 | }
1152 | ],
1153 | "profile": {
1154 | "name": "typicode"
1155 | }
1156 | }
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/Tests/service.json:
--------------------------------------------------------------------------------
1 | {
2 | "domains": {
3 | "test": {
4 | "jsonPlaceholder": "http://jsonplaceholder.typicode.com/"
5 | },
6 | "localhost": {
7 | "jsonPlaceholder": "http://localhost:3000/"
8 | }
9 | },
10 | "service": {
11 | "restful": {
12 | "posts": {
13 | "domain": "jsonPlaceholder",
14 | "path": "posts"
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Example/YTXRestfulModel.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0CB946391C716F0E009B83A7 /* test_YTXRestfulModelUserDefaultSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CB946381C716F0E009B83A7 /* test_YTXRestfulModelUserDefaultSpec.m */; };
11 | 1867C4C81C7EEDBF00D900E9 /* test_YTXRestfulModelDB.m in Sources */ = {isa = PBXBuildFile; fileRef = 1867C4C71C7EEDBF00D900E9 /* test_YTXRestfulModelDB.m */; };
12 | 1867C4CB1C7EF01000D900E9 /* YTXTestStudentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1867C4CA1C7EF01000D900E9 /* YTXTestStudentModel.m */; };
13 | 1867C4CE1C7EF62A00D900E9 /* YTXTestHumanModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1867C4CD1C7EF62A00D900E9 /* YTXTestHumanModel.m */; };
14 | 18E9FFF61C702CA500143B68 /* db.json in Resources */ = {isa = PBXBuildFile; fileRef = 18E9FFF51C702CA500143B68 /* db.json */; };
15 | 4A9D60319D9EC81A8EF6A839 /* libPods-YTXRestfulModel_Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF3994A9A34C6C481609B709 /* libPods-YTXRestfulModel_Tests.a */; };
16 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
17 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
18 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
19 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
20 | 621EE9721C88013C0033A211 /* YTXTestStudentCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 621EE9711C88013C0033A211 /* YTXTestStudentCollection.m */; };
21 | 624C05911C55EDC200C40CE6 /* service.json in Resources */ = {isa = PBXBuildFile; fileRef = 624C05901C55EDC200C40CE6 /* service.json */; };
22 | 625D8E311C868DD8003A6F81 /* YTXTestTeacherModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 625D8E301C868DD8003A6F81 /* YTXTestTeacherModel.m */; };
23 | 62CD75A81C89814400AA6A16 /* test_YTXRestfulModelAFNetworkingRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 62CD75A71C89814400AA6A16 /* test_YTXRestfulModelAFNetworkingRemote.m */; };
24 | 62CD75AD1C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 62CD75AA1C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.m */; };
25 | 62CD75B11C8985C000AA6A16 /* YTXTestAFNetworkingRemoteModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 62CD75B01C8985C000AA6A16 /* YTXTestAFNetworkingRemoteModel.m */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXFileReference section */
29 | 0888F830D92D08408493FB13 /* Pods-YTXRestfulModel_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YTXRestfulModel_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-YTXRestfulModel_Tests/Pods-YTXRestfulModel_Tests.release.xcconfig"; sourceTree = ""; };
30 | 0CB946381C716F0E009B83A7 /* test_YTXRestfulModelUserDefaultSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = test_YTXRestfulModelUserDefaultSpec.m; sourceTree = ""; };
31 | 181817C21C843B1D00745529 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
32 | 1867C4C71C7EEDBF00D900E9 /* test_YTXRestfulModelDB.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = test_YTXRestfulModelDB.m; sourceTree = ""; };
33 | 1867C4C91C7EF01000D900E9 /* YTXTestStudentModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestStudentModel.h; sourceTree = ""; };
34 | 1867C4CA1C7EF01000D900E9 /* YTXTestStudentModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestStudentModel.m; sourceTree = ""; };
35 | 1867C4CC1C7EF62A00D900E9 /* YTXTestHumanModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestHumanModel.h; sourceTree = ""; };
36 | 1867C4CD1C7EF62A00D900E9 /* YTXTestHumanModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestHumanModel.m; sourceTree = ""; };
37 | 18E9FFF51C702CA500143B68 /* db.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = db.json; sourceTree = ""; };
38 | 44BA7F8968B8D7FBB1291584 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
39 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
40 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
41 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
42 | 6003F5AE195388D20070C39A /* YTXRestfulModel_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YTXRestfulModel_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
44 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; };
45 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
46 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; };
47 | 621EE9701C88013C0033A211 /* YTXTestStudentCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestStudentCollection.h; sourceTree = ""; };
48 | 621EE9711C88013C0033A211 /* YTXTestStudentCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestStudentCollection.m; sourceTree = ""; };
49 | 624C05901C55EDC200C40CE6 /* service.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = service.json; sourceTree = ""; };
50 | 625D8E2F1C868DD8003A6F81 /* YTXTestTeacherModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestTeacherModel.h; sourceTree = ""; };
51 | 625D8E301C868DD8003A6F81 /* YTXTestTeacherModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestTeacherModel.m; sourceTree = ""; };
52 | 62CD75A71C89814400AA6A16 /* test_YTXRestfulModelAFNetworkingRemote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = test_YTXRestfulModelAFNetworkingRemote.m; sourceTree = ""; };
53 | 62CD75A91C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestAFNetworkingRemoteCollection.h; sourceTree = ""; };
54 | 62CD75AA1C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestAFNetworkingRemoteCollection.m; sourceTree = ""; };
55 | 62CD75AF1C8985AD00AA6A16 /* YTXTestAFNetworkingRemoteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YTXTestAFNetworkingRemoteModel.h; sourceTree = ""; };
56 | 62CD75B01C8985C000AA6A16 /* YTXTestAFNetworkingRemoteModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YTXTestAFNetworkingRemoteModel.m; sourceTree = ""; };
57 | B49B4CC15A25D49DB32DA99D /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
58 | C00D7C8B97513F9E766D02BD /* YTXRestfulModel.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = YTXRestfulModel.podspec; path = ../YTXRestfulModel.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
59 | C6176AB77AD238DD4C8DD2B5 /* Pods-YTXRestfulModel_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YTXRestfulModel_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-YTXRestfulModel_Tests/Pods-YTXRestfulModel_Tests.debug.xcconfig"; sourceTree = ""; };
60 | DF3994A9A34C6C481609B709 /* libPods-YTXRestfulModel_Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-YTXRestfulModel_Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
61 | /* End PBXFileReference section */
62 |
63 | /* Begin PBXFrameworksBuildPhase section */
64 | 6003F5AB195388D20070C39A /* Frameworks */ = {
65 | isa = PBXFrameworksBuildPhase;
66 | buildActionMask = 2147483647;
67 | files = (
68 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
69 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
70 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
71 | 4A9D60319D9EC81A8EF6A839 /* libPods-YTXRestfulModel_Tests.a in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXFrameworksBuildPhase section */
76 |
77 | /* Begin PBXGroup section */
78 | 6003F581195388D10070C39A = {
79 | isa = PBXGroup;
80 | children = (
81 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
82 | 6003F5B5195388D20070C39A /* Tests */,
83 | 6003F58C195388D20070C39A /* Frameworks */,
84 | 6003F58B195388D20070C39A /* Products */,
85 | CB32C1DAB34DE4955450843B /* Pods */,
86 | );
87 | sourceTree = "";
88 | };
89 | 6003F58B195388D20070C39A /* Products */ = {
90 | isa = PBXGroup;
91 | children = (
92 | 6003F5AE195388D20070C39A /* YTXRestfulModel_Tests.xctest */,
93 | );
94 | name = Products;
95 | sourceTree = "";
96 | };
97 | 6003F58C195388D20070C39A /* Frameworks */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 181817C21C843B1D00745529 /* libsqlite3.tbd */,
101 | 6003F58D195388D20070C39A /* Foundation.framework */,
102 | 6003F58F195388D20070C39A /* CoreGraphics.framework */,
103 | 6003F591195388D20070C39A /* UIKit.framework */,
104 | 6003F5AF195388D20070C39A /* XCTest.framework */,
105 | DF3994A9A34C6C481609B709 /* libPods-YTXRestfulModel_Tests.a */,
106 | );
107 | name = Frameworks;
108 | sourceTree = "";
109 | };
110 | 6003F5B5195388D20070C39A /* Tests */ = {
111 | isa = PBXGroup;
112 | children = (
113 | 62CD75A71C89814400AA6A16 /* test_YTXRestfulModelAFNetworkingRemote.m */,
114 | 0CB946381C716F0E009B83A7 /* test_YTXRestfulModelUserDefaultSpec.m */,
115 | 1867C4C71C7EEDBF00D900E9 /* test_YTXRestfulModelDB.m */,
116 | 6003F5B6195388D20070C39A /* Supporting Files */,
117 | 62CD75A91C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.h */,
118 | 62CD75AA1C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.m */,
119 | 62CD75AF1C8985AD00AA6A16 /* YTXTestAFNetworkingRemoteModel.h */,
120 | 62CD75B01C8985C000AA6A16 /* YTXTestAFNetworkingRemoteModel.m */,
121 | 1867C4CC1C7EF62A00D900E9 /* YTXTestHumanModel.h */,
122 | 1867C4CD1C7EF62A00D900E9 /* YTXTestHumanModel.m */,
123 | 1867C4C91C7EF01000D900E9 /* YTXTestStudentModel.h */,
124 | 1867C4CA1C7EF01000D900E9 /* YTXTestStudentModel.m */,
125 | 625D8E2F1C868DD8003A6F81 /* YTXTestTeacherModel.h */,
126 | 625D8E301C868DD8003A6F81 /* YTXTestTeacherModel.m */,
127 | 621EE9701C88013C0033A211 /* YTXTestStudentCollection.h */,
128 | 621EE9711C88013C0033A211 /* YTXTestStudentCollection.m */,
129 | 18E9FFF51C702CA500143B68 /* db.json */,
130 | 624C05901C55EDC200C40CE6 /* service.json */,
131 | );
132 | path = Tests;
133 | sourceTree = "";
134 | };
135 | 6003F5B6195388D20070C39A /* Supporting Files */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 6003F5B7195388D20070C39A /* Tests-Info.plist */,
139 | 6003F5B8195388D20070C39A /* InfoPlist.strings */,
140 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
141 | );
142 | name = "Supporting Files";
143 | sourceTree = "";
144 | };
145 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
146 | isa = PBXGroup;
147 | children = (
148 | C00D7C8B97513F9E766D02BD /* YTXRestfulModel.podspec */,
149 | B49B4CC15A25D49DB32DA99D /* README.md */,
150 | 44BA7F8968B8D7FBB1291584 /* LICENSE */,
151 | );
152 | name = "Podspec Metadata";
153 | sourceTree = "";
154 | };
155 | CB32C1DAB34DE4955450843B /* Pods */ = {
156 | isa = PBXGroup;
157 | children = (
158 | C6176AB77AD238DD4C8DD2B5 /* Pods-YTXRestfulModel_Tests.debug.xcconfig */,
159 | 0888F830D92D08408493FB13 /* Pods-YTXRestfulModel_Tests.release.xcconfig */,
160 | );
161 | name = Pods;
162 | sourceTree = "";
163 | };
164 | /* End PBXGroup section */
165 |
166 | /* Begin PBXNativeTarget section */
167 | 6003F5AD195388D20070C39A /* YTXRestfulModel_Tests */ = {
168 | isa = PBXNativeTarget;
169 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "YTXRestfulModel_Tests" */;
170 | buildPhases = (
171 | FDA13838148F72BC7F3BE3AE /* [CP] Check Pods Manifest.lock */,
172 | 6003F5AA195388D20070C39A /* Sources */,
173 | 6003F5AB195388D20070C39A /* Frameworks */,
174 | 6003F5AC195388D20070C39A /* Resources */,
175 | 4AAD9A50A9F903433AFF9967 /* [CP] Embed Pods Frameworks */,
176 | 72E53629E55A53CCDB71837F /* [CP] Copy Pods Resources */,
177 | );
178 | buildRules = (
179 | );
180 | dependencies = (
181 | );
182 | name = YTXRestfulModel_Tests;
183 | productName = YTXRestfulModelTests;
184 | productReference = 6003F5AE195388D20070C39A /* YTXRestfulModel_Tests.xctest */;
185 | productType = "com.apple.product-type.bundle.unit-test";
186 | };
187 | /* End PBXNativeTarget section */
188 |
189 | /* Begin PBXProject section */
190 | 6003F582195388D10070C39A /* Project object */ = {
191 | isa = PBXProject;
192 | attributes = {
193 | CLASSPREFIX = YTX;
194 | LastUpgradeCheck = 0720;
195 | ORGANIZATIONNAME = caojun;
196 | TargetAttributes = {
197 | 6003F5AD195388D20070C39A = {
198 | TestTargetID = 6003F589195388D20070C39A;
199 | };
200 | };
201 | };
202 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "YTXRestfulModel" */;
203 | compatibilityVersion = "Xcode 3.2";
204 | developmentRegion = English;
205 | hasScannedForEncodings = 0;
206 | knownRegions = (
207 | en,
208 | Base,
209 | );
210 | mainGroup = 6003F581195388D10070C39A;
211 | productRefGroup = 6003F58B195388D20070C39A /* Products */;
212 | projectDirPath = "";
213 | projectRoot = "";
214 | targets = (
215 | 6003F5AD195388D20070C39A /* YTXRestfulModel_Tests */,
216 | );
217 | };
218 | /* End PBXProject section */
219 |
220 | /* Begin PBXResourcesBuildPhase section */
221 | 6003F5AC195388D20070C39A /* Resources */ = {
222 | isa = PBXResourcesBuildPhase;
223 | buildActionMask = 2147483647;
224 | files = (
225 | 18E9FFF61C702CA500143B68 /* db.json in Resources */,
226 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
227 | 624C05911C55EDC200C40CE6 /* service.json in Resources */,
228 | );
229 | runOnlyForDeploymentPostprocessing = 0;
230 | };
231 | /* End PBXResourcesBuildPhase section */
232 |
233 | /* Begin PBXShellScriptBuildPhase section */
234 | 4AAD9A50A9F903433AFF9967 /* [CP] Embed Pods Frameworks */ = {
235 | isa = PBXShellScriptBuildPhase;
236 | buildActionMask = 2147483647;
237 | files = (
238 | );
239 | inputPaths = (
240 | );
241 | name = "[CP] Embed Pods Frameworks";
242 | outputPaths = (
243 | );
244 | runOnlyForDeploymentPostprocessing = 0;
245 | shellPath = /bin/sh;
246 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YTXRestfulModel_Tests/Pods-YTXRestfulModel_Tests-frameworks.sh\"\n";
247 | showEnvVarsInLog = 0;
248 | };
249 | 72E53629E55A53CCDB71837F /* [CP] Copy Pods Resources */ = {
250 | isa = PBXShellScriptBuildPhase;
251 | buildActionMask = 2147483647;
252 | files = (
253 | );
254 | inputPaths = (
255 | );
256 | name = "[CP] Copy Pods Resources";
257 | outputPaths = (
258 | );
259 | runOnlyForDeploymentPostprocessing = 0;
260 | shellPath = /bin/sh;
261 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YTXRestfulModel_Tests/Pods-YTXRestfulModel_Tests-resources.sh\"\n";
262 | showEnvVarsInLog = 0;
263 | };
264 | FDA13838148F72BC7F3BE3AE /* [CP] Check Pods Manifest.lock */ = {
265 | isa = PBXShellScriptBuildPhase;
266 | buildActionMask = 2147483647;
267 | files = (
268 | );
269 | inputPaths = (
270 | );
271 | name = "[CP] Check Pods Manifest.lock";
272 | outputPaths = (
273 | );
274 | runOnlyForDeploymentPostprocessing = 0;
275 | shellPath = /bin/sh;
276 | 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";
277 | showEnvVarsInLog = 0;
278 | };
279 | /* End PBXShellScriptBuildPhase section */
280 |
281 | /* Begin PBXSourcesBuildPhase section */
282 | 6003F5AA195388D20070C39A /* Sources */ = {
283 | isa = PBXSourcesBuildPhase;
284 | buildActionMask = 2147483647;
285 | files = (
286 | 62CD75B11C8985C000AA6A16 /* YTXTestAFNetworkingRemoteModel.m in Sources */,
287 | 1867C4CE1C7EF62A00D900E9 /* YTXTestHumanModel.m in Sources */,
288 | 625D8E311C868DD8003A6F81 /* YTXTestTeacherModel.m in Sources */,
289 | 0CB946391C716F0E009B83A7 /* test_YTXRestfulModelUserDefaultSpec.m in Sources */,
290 | 62CD75AD1C89828300AA6A16 /* YTXTestAFNetworkingRemoteCollection.m in Sources */,
291 | 1867C4C81C7EEDBF00D900E9 /* test_YTXRestfulModelDB.m in Sources */,
292 | 621EE9721C88013C0033A211 /* YTXTestStudentCollection.m in Sources */,
293 | 1867C4CB1C7EF01000D900E9 /* YTXTestStudentModel.m in Sources */,
294 | 62CD75A81C89814400AA6A16 /* test_YTXRestfulModelAFNetworkingRemote.m in Sources */,
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | /* End PBXSourcesBuildPhase section */
299 |
300 | /* Begin PBXVariantGroup section */
301 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
302 | isa = PBXVariantGroup;
303 | children = (
304 | 6003F5B9195388D20070C39A /* en */,
305 | );
306 | name = InfoPlist.strings;
307 | sourceTree = "";
308 | };
309 | /* End PBXVariantGroup section */
310 |
311 | /* Begin XCBuildConfiguration section */
312 | 6003F5BD195388D20070C39A /* Debug */ = {
313 | isa = XCBuildConfiguration;
314 | buildSettings = {
315 | ALWAYS_SEARCH_USER_PATHS = NO;
316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
317 | CLANG_CXX_LIBRARY = "libc++";
318 | CLANG_ENABLE_MODULES = YES;
319 | CLANG_ENABLE_OBJC_ARC = YES;
320 | CLANG_WARN_BOOL_CONVERSION = YES;
321 | CLANG_WARN_CONSTANT_CONVERSION = YES;
322 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
323 | CLANG_WARN_EMPTY_BODY = YES;
324 | CLANG_WARN_ENUM_CONVERSION = YES;
325 | CLANG_WARN_INT_CONVERSION = YES;
326 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
328 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
329 | COPY_PHASE_STRIP = NO;
330 | ENABLE_TESTABILITY = YES;
331 | GCC_C_LANGUAGE_STANDARD = gnu99;
332 | GCC_DYNAMIC_NO_PIC = NO;
333 | GCC_OPTIMIZATION_LEVEL = 0;
334 | GCC_PREPROCESSOR_DEFINITIONS = (
335 | "DEBUG=1",
336 | "$(inherited)",
337 | );
338 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
339 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
340 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
341 | GCC_WARN_UNDECLARED_SELECTOR = YES;
342 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
343 | GCC_WARN_UNUSED_FUNCTION = YES;
344 | GCC_WARN_UNUSED_VARIABLE = YES;
345 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
346 | ONLY_ACTIVE_ARCH = YES;
347 | SDKROOT = iphoneos;
348 | TARGETED_DEVICE_FAMILY = "1,2";
349 | };
350 | name = Debug;
351 | };
352 | 6003F5BE195388D20070C39A /* Release */ = {
353 | isa = XCBuildConfiguration;
354 | buildSettings = {
355 | ALWAYS_SEARCH_USER_PATHS = NO;
356 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
357 | CLANG_CXX_LIBRARY = "libc++";
358 | CLANG_ENABLE_MODULES = YES;
359 | CLANG_ENABLE_OBJC_ARC = YES;
360 | CLANG_WARN_BOOL_CONVERSION = YES;
361 | CLANG_WARN_CONSTANT_CONVERSION = YES;
362 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
363 | CLANG_WARN_EMPTY_BODY = YES;
364 | CLANG_WARN_ENUM_CONVERSION = YES;
365 | CLANG_WARN_INT_CONVERSION = YES;
366 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
368 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
369 | COPY_PHASE_STRIP = YES;
370 | ENABLE_NS_ASSERTIONS = NO;
371 | GCC_C_LANGUAGE_STANDARD = gnu99;
372 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
374 | GCC_WARN_UNDECLARED_SELECTOR = YES;
375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
376 | GCC_WARN_UNUSED_FUNCTION = YES;
377 | GCC_WARN_UNUSED_VARIABLE = YES;
378 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
379 | SDKROOT = iphoneos;
380 | TARGETED_DEVICE_FAMILY = "1,2";
381 | VALIDATE_PRODUCT = YES;
382 | };
383 | name = Release;
384 | };
385 | 6003F5C3195388D20070C39A /* Debug */ = {
386 | isa = XCBuildConfiguration;
387 | baseConfigurationReference = C6176AB77AD238DD4C8DD2B5 /* Pods-YTXRestfulModel_Tests.debug.xcconfig */;
388 | buildSettings = {
389 | FRAMEWORK_SEARCH_PATHS = (
390 | "$(SDKROOT)/Developer/Library/Frameworks",
391 | "$(inherited)",
392 | "$(DEVELOPER_FRAMEWORKS_DIR)",
393 | );
394 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
395 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
396 | GCC_PREPROCESSOR_DEFINITIONS = (
397 | "DEBUG=1",
398 | "$(inherited)",
399 | );
400 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
401 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
402 | PRODUCT_NAME = "$(TARGET_NAME)";
403 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YTXRestfulModel_Example.app/YTXRestfulModel_Example";
404 | WRAPPER_EXTENSION = xctest;
405 | };
406 | name = Debug;
407 | };
408 | 6003F5C4195388D20070C39A /* Release */ = {
409 | isa = XCBuildConfiguration;
410 | baseConfigurationReference = 0888F830D92D08408493FB13 /* Pods-YTXRestfulModel_Tests.release.xcconfig */;
411 | buildSettings = {
412 | FRAMEWORK_SEARCH_PATHS = (
413 | "$(SDKROOT)/Developer/Library/Frameworks",
414 | "$(inherited)",
415 | "$(DEVELOPER_FRAMEWORKS_DIR)",
416 | );
417 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
418 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
419 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
420 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
421 | PRODUCT_NAME = "$(TARGET_NAME)";
422 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YTXRestfulModel_Example.app/YTXRestfulModel_Example";
423 | WRAPPER_EXTENSION = xctest;
424 | };
425 | name = Release;
426 | };
427 | /* End XCBuildConfiguration section */
428 |
429 | /* Begin XCConfigurationList section */
430 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "YTXRestfulModel" */ = {
431 | isa = XCConfigurationList;
432 | buildConfigurations = (
433 | 6003F5BD195388D20070C39A /* Debug */,
434 | 6003F5BE195388D20070C39A /* Release */,
435 | );
436 | defaultConfigurationIsVisible = 0;
437 | defaultConfigurationName = Release;
438 | };
439 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "YTXRestfulModel_Tests" */ = {
440 | isa = XCConfigurationList;
441 | buildConfigurations = (
442 | 6003F5C3195388D20070C39A /* Debug */,
443 | 6003F5C4195388D20070C39A /* Release */,
444 | );
445 | defaultConfigurationIsVisible = 0;
446 | defaultConfigurationName = Release;
447 | };
448 | /* End XCConfigurationList section */
449 | };
450 | rootObject = 6003F582195388D10070C39A /* Project object */;
451 | }
452 |
--------------------------------------------------------------------------------
/Example/YTXRestfulModel.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/YTXRestfulModel.xcodeproj/xcshareddata/xcschemes/YTXRestfulModel-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Example/YTXRestfulModel.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 caojun <78612846@qq.com>
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baidao/YTXRestfulModel/1272d03b9d6675c1e2f14858bf0dc752b12f2a14/Pod/Assets/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baidao/YTXRestfulModel/1272d03b9d6675c1e2f14858bf0dc752b12f2a14/Pod/Classes/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/Model/YTXRestfulCollection.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulCollection.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 |
10 | #import "YTXRestfulModelStorageProtocol.h"
11 | #import "YTXRestfulModelRemoteProtocol.h"
12 | #import "YTXRestfulModelDBProtocol.h"
13 | #import "YTXRestfulModel.h"
14 |
15 | #import
16 |
17 | @interface YTXRestfulCollection : NSObject
18 |
19 | @property (nonnull, nonatomic, assign) Class modelClass;
20 | @property (nonnull, nonatomic, strong, readonly) NSArray * models;
21 |
22 | @property (nonnull, nonatomic, strong) id storageSync;
23 | @property (nonnull, nonatomic, strong) id remoteSync;
24 | @property (nonnull, nonatomic, strong) id dbSync;
25 |
26 |
27 | - (nonnull instancetype) initWithModelClass:(nonnull Class)modelClass;
28 |
29 | - (nonnull instancetype) initWithModelClass:(nonnull Class)modelClass userDefaultSuiteName:(nullable NSString *) suiteName;
30 |
31 | #pragma mark storage
32 | - (nonnull NSString *) storageKey;
33 |
34 | /** GET */
35 | - (nullable instancetype) fetchStorageSync:(nullable NSDictionary *) param;
36 |
37 | /** POST / PUT */
38 | - (nonnull instancetype) saveStorageSync:(nullable NSDictionary *) param;
39 |
40 | /** DELETE */
41 | - (void) destroyStorageSync:(nullable NSDictionary *) param;
42 |
43 | /** GET */
44 | - (nullable instancetype) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
45 |
46 | /** POST / PUT */
47 | - (nonnull instancetype) saveStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
48 |
49 | /** DELETE */
50 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
51 |
52 | #pragma mark remote
53 | /* RACSignal return self **/
54 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
55 |
56 | /* RACSignal return self **/
57 | - (void) fetchRemoteThenAdd:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
58 |
59 | #pragma mark db
60 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable) error;
61 | //
62 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderByColumnNames:(nonnull NSArray * )columnNames;
63 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...;
64 | //
65 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger)start count:(NSUInteger)count soryBy:(YTXRestfulModelDBSortBy)sortBy orderByColumnNames:(nonnull NSArray * )columnNames;
66 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger)start count:(NSUInteger)count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...;
67 | //
68 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetConditions:(nonnull NSArray * )conditions;
69 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMet:(nonnull NSString * )condition, ...;
70 | //
71 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditionsArray:(nonnull NSArray * )conditions;
72 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...;
73 | //
74 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditionsArray:(nonnull NSArray * )conditions;
75 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...;
76 | //
77 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetConditionsArray:(nonnull NSArray * )conditions;
78 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMet:(nonnull NSString * )condition, ...;
79 | //
80 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditionsArray:(nonnull NSArray * )conditions;
81 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...;
82 | //
83 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditionsArray:(nonnull NSArray * )conditions;
84 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...;
85 | //
86 | - (BOOL) destroyDBSyncAllWithError:(NSError * _Nullable * _Nullable)error;
87 |
88 | #pragma clang diagnostic push
89 | #pragma clang diagnostic ignored "-Wnullability-completeness"
90 | - (nonnull NSArray *) arrayWithArgs:(va_list) args firstArgument:(nullable id)firstArgument;
91 | #pragma clang diagnostic pop
92 |
93 | - (nonnull NSArray *) arrayOfMappedArgsWithOriginArray:(nonnull NSArray *)originArray;
94 |
95 | #pragma mark - function
96 |
97 | - (nullable NSArray< id > *) transformerProxyOfResponse:(nullable id) response error:(NSError * _Nullable * _Nullable) error;
98 |
99 | /** 在拉到数据转mantle的时候用 */
100 | - (nullable NSArray *) transformerProxyOfModels:(nonnull NSArray< id > *) array;
101 |
102 | /** 注入自己时使用 */
103 | - (nonnull instancetype) removeAllModels;
104 |
105 | - (nonnull instancetype) resetModels:(nonnull NSArray *) array;
106 |
107 | - (nonnull instancetype) addModels:(nonnull NSArray *) array;
108 |
109 | - (nonnull instancetype) insertFrontModels:(nonnull NSArray *) array;
110 |
111 | - (nonnull instancetype) sortedArrayUsingComparator:(nonnull NSComparator)cmptr;
112 |
113 | - (nullable NSArray *) arrayWithRange:(NSRange)range;
114 |
115 | - (nullable YTXRestfulCollection *) collectionWithRange:(NSRange)range;
116 |
117 | - (nullable YTXRestfulModel *) modelAtIndex:(NSInteger) index;
118 |
119 | /** 主键可能是NSNumber或NSString,统一转成NSString来判断*/
120 | - (nullable YTXRestfulModel *) modelWithPrimaryKey:(nonnull NSString *) primaryKey;
121 |
122 | - (BOOL) addModel:(nonnull YTXRestfulModel *) model;
123 |
124 | - (BOOL) insertFrontModel:(nonnull YTXRestfulModel *) model;
125 |
126 | /** 插入到index之后*/
127 | - (BOOL) insertModel:(nonnull YTXRestfulModel *) model afterIndex:(NSInteger) index;
128 |
129 | /** 插入到index之前*/
130 | - (BOOL) insertModel:(nonnull YTXRestfulModel *) model beforeIndex:(NSInteger) index;
131 |
132 | - (BOOL) removeModelAtIndex:(NSInteger) index;
133 |
134 | /** 主键可能是NSNumber或NSString,统一转成NSString来判断*/
135 | - (BOOL) removeModelWithPrimaryKey:(nonnull NSString *) primaryKey;
136 |
137 | - (BOOL) removeModelWithModel:(nonnull YTXRestfulModel *) model;
138 |
139 | /** 逆序输出Collection*/
140 | - (void) reverseModels;
141 |
142 | @end
143 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/YTXRestfulCollection.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulCollection.m
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/19.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulCollection.h"
10 | #import "YTXRestfulModel.h"
11 |
12 | #ifdef YTX_USERDEFAULTSTORAGESYNC_EXISTS
13 | #import "YTXRestfulModelUserDefaultStorageSync.h"
14 | #endif
15 |
16 | #ifdef YTX_AFNETWORKINGREMOTESYNC_EXISTS
17 | #import "AFNetworkingRemoteSync.h"
18 | #endif
19 |
20 | #ifdef YTX_FMDBSYNC_EXISTS
21 | #import "YTXRestfulModelFMDBSync.h"
22 | #endif
23 |
24 | #import
25 |
26 |
27 | typedef enum {
28 | RESET,
29 | ADD,
30 | INSERTFRONT,
31 | } FetchRemoteHandleScheme;
32 |
33 | @interface YTXRestfulCollection()
34 |
35 | @property (nonnull, nonatomic, strong) NSArray * models;
36 |
37 | @end
38 |
39 | @implementation YTXRestfulCollection
40 |
41 | - (instancetype)init
42 | {
43 | if(self = [super init])
44 | {
45 |
46 | #ifdef YTX_USERDEFAULTSTORAGESYNC_EXISTS
47 | self.storageSync = [YTXRestfulModelUserDefaultStorageSync new];
48 | #endif
49 |
50 | #ifdef YTX_AFNETWORKINGREMOTESYNC_EXISTS
51 | self.remoteSync = [AFNetworkingRemoteSync new];
52 | #endif
53 |
54 | #ifdef YTX_FMDBSYNC_EXISTS
55 | self.dbSync = [YTXRestfulModelFMDBSync new];
56 | #endif
57 | self.modelClass = [YTXRestfulModel class];
58 | self.models = @[];
59 | }
60 | return self;
61 |
62 | }
63 |
64 | - (instancetype)initWithModelClass:(Class)modelClass
65 | {
66 | return [self initWithModelClass:modelClass userDefaultSuiteName:nil];
67 | }
68 |
69 | - (instancetype)initWithModelClass:(Class)modelClass userDefaultSuiteName:(NSString *) suiteName
70 | {
71 | if(self = [super init])
72 | {
73 |
74 | #ifdef YTX_USERDEFAULTSTORAGESYNC_EXISTS
75 | self.storageSync = [YTXRestfulModelUserDefaultStorageSync new];
76 | #endif
77 |
78 | #ifdef YTX_AFNETWORKINGREMOTESYNC_EXISTS
79 | self.remoteSync = [AFNetworkingRemoteSync new];
80 | #endif
81 |
82 | #ifdef YTX_FMDBSYNC_EXISTS
83 | self.dbSync = [YTXRestfulModelFMDBSync syncWithModelOfClass:modelClass primaryKey:[modelClass syncPrimaryKey]];
84 | #endif
85 | self.modelClass = modelClass;
86 | self.models = @[];
87 | }
88 | return self;
89 | }
90 |
91 | #pragma mark storage
92 | /** GET */
93 | - (nullable instancetype) fetchStorageSync:(nullable NSDictionary *) param
94 | {
95 | return [self fetchStorageSyncWithKey:[self storageKey] param:param];
96 | }
97 |
98 | /** POST / PUT */
99 | - (nonnull instancetype) saveStorageSync:(nullable NSDictionary *) param
100 | {
101 | return [self saveStorageSyncWithKey:[self storageKey] param:param];
102 | }
103 |
104 | /** DELETE */
105 | - (void) destroyStorageSync:(nullable NSDictionary *) param
106 | {
107 | return [self destroyStorageSyncWithKey:[self storageKey] param:param];
108 | }
109 |
110 | /** GET */
111 | - (nullable instancetype) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
112 | {
113 |
114 | NSArray * x = [self.storageSync fetchStorageSyncWithKey:storage param:param];
115 | if (x) {
116 | NSError * error;
117 | NSArray * ret = [self transformerProxyOfResponse:x error:nil];
118 | if (!error) {
119 | [self resetModels:ret];
120 | return self;
121 | }
122 | }
123 | return nil;
124 | }
125 |
126 | /** POST / PUT */
127 | - (nonnull instancetype) saveStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
128 | {
129 | [self.storageSync saveStorageSyncWithKey:storage withObject:[self transformerProxyOfModels:[self.models copy]] param:param];
130 |
131 | return self;
132 | }
133 |
134 | /** DELETE */
135 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
136 | {
137 | [self.storageSync destroyStorageSyncWithKey:storage param:param];
138 | }
139 |
140 | - (nonnull NSString *) storageKey
141 | {
142 | return [NSString stringWithFormat:@"EFSCollection+%@", NSStringFromClass(self.modelClass)];
143 | }
144 |
145 | #pragma mark remote
146 |
147 | /** 在拉到数据转mantle的时候用 */
148 | - (nullable NSArray< id > *) transformerProxyOfResponse:(nullable id) response error:(NSError * _Nullable * _Nullable) error
149 | {
150 | return [MTLJSONAdapter modelsOfClass:[self modelClass] fromJSONArray:response error:error];
151 | }
152 |
153 | /** 在拉到数据转mantle的时候用 */
154 | - (nullable NSArray *) transformerProxyOfModels:(nonnull NSArray< id > *) array
155 | {
156 | return [MTLJSONAdapter JSONArrayFromModels:array];
157 | }
158 |
159 | - (nonnull instancetype) removeAllModels
160 | {
161 | self.models = @[];
162 | return self;
163 | }
164 |
165 | - (nonnull instancetype) resetModels:(nonnull NSArray *) array
166 | {
167 | # if DEBUG
168 | for (id item in array) {
169 | NSAssert([item isMemberOfClass:self.modelClass], @"加入的数组中的每一项都必须是当前的Model类型");
170 | }
171 | # endif
172 | self.models = array;
173 | return self;
174 | }
175 |
176 | - (nonnull instancetype) addModels:(nonnull NSArray *) array
177 | {
178 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
179 |
180 | [temp addObjectsFromArray:array];
181 |
182 | return [self resetModels:temp];
183 | }
184 |
185 | - (nonnull instancetype) insertFrontModels:(nonnull NSArray *) array
186 | {
187 | NSMutableArray * temp = [NSMutableArray arrayWithArray:array];
188 |
189 | [temp addObjectsFromArray:self.models];
190 |
191 | return [self resetModels:temp];
192 | }
193 |
194 | - (nonnull instancetype)sortedArrayUsingComparator:(NSComparator)cmptr
195 | {
196 | [self resetModels:[self.models sortedArrayUsingComparator:cmptr]];
197 | return self;
198 | }
199 |
200 |
201 | /* RACSignal return self **/
202 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
203 | {
204 | __weak __typeof(&*self)weakSelf = self;
205 | [self.remoteSync fetchRemote:param success:^(id _Nullable response) {
206 | NSError * error = nil;
207 | NSArray * arr = [weakSelf transformerProxyOfResponse:response error:&error];
208 |
209 | [weakSelf resetModels:arr];
210 | if (!error) {
211 | success(weakSelf);
212 | }
213 | else {
214 | failed(error);
215 | }
216 | } failed:failed];
217 |
218 | }
219 |
220 | /* RACSignal return self **/
221 | - (void) fetchRemoteThenAdd:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
222 | {
223 | __weak __typeof(&*self)weakSelf = self;
224 | [self.remoteSync fetchRemote:param success:^(id _Nullable response) {
225 | NSError * error = nil;
226 | NSArray * arr = [weakSelf transformerProxyOfResponse:response error:&error];
227 |
228 | [weakSelf addModels:arr];
229 | if (!error) {
230 | success(weakSelf);
231 | }
232 | else {
233 | failed(error);
234 | }
235 | } failed:failed];
236 | }
237 |
238 |
239 | #pragma mark db
240 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable)error
241 | {
242 | NSArray * x = [self.dbSync fetchAllSyncWithError:error];
243 |
244 | if (x && *error == nil) {
245 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
246 | }
247 |
248 | return self;
249 | }
250 |
251 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderByColumnNames:(nonnull NSArray * )columnNames
252 | {
253 | NSArray * x = [self.dbSync fetchAllSyncWithError:error soryBy:sortBy orderBy:columnNames];
254 |
255 | if (x && *error == nil) {
256 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
257 | }
258 |
259 | return self;
260 | }
261 |
262 | - (nonnull instancetype) fetchDBSyncAllWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) columnName, ...
263 | {
264 | va_list args;
265 | va_start(args, columnName);
266 |
267 | NSArray * columnNames = [self arrayWithArgs:args firstArgument:columnName];
268 |
269 | va_end(args);
270 |
271 | columnNames = [self arrayOfMappedArgsWithOriginArray:columnNames];
272 |
273 | return [self fetchDBSyncAllWithError:error soryBy:sortBy orderByColumnNames:columnNames];
274 | }
275 |
276 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger)start count:(NSUInteger)count soryBy:(YTXRestfulModelDBSortBy)sortBy orderByColumnNames:(nonnull NSArray * )columnNames
277 | {
278 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error start:start count:count soryBy:sortBy orderBy:columnNames];
279 |
280 | if (x && *error == nil) {
281 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
282 | }
283 |
284 | return self;
285 | }
286 |
287 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger)start count:(NSUInteger)count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...
288 | {
289 | va_list args;
290 | va_start(args, columnName);
291 |
292 | NSArray * columnNames = [self arrayWithArgs:args firstArgument:columnName];
293 |
294 | va_end(args);
295 |
296 | columnNames = [self arrayOfMappedArgsWithOriginArray:columnNames];
297 |
298 | return [self fetchDBSyncMultipleWithError:error start:start count:count soryBy:sortBy orderByColumnNames:columnNames];
299 | }
300 |
301 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetConditions:(nonnull NSArray * )conditions
302 | {
303 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error whereAllTheConditionsAreMet:conditions];
304 |
305 | if (x && *error == nil) {
306 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
307 | }
308 |
309 | return self;
310 | }
311 |
312 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMet:(nonnull NSString * )condition, ...
313 | {
314 | va_list args;
315 | va_start(args, condition);
316 |
317 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
318 |
319 | va_end(args);
320 |
321 | return [self fetchDBSyncMultipleWithError:error whereAllTheConditionsAreMetConditions:conditions];
322 | }
323 |
324 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditionsArray:(nonnull NSArray * )conditions
325 | {
326 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error whereAllTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditions:conditions];
327 |
328 | if (x && *error == nil) {
329 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
330 | }
331 |
332 | return self;
333 | }
334 |
335 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...
336 | {
337 | va_list args;
338 | va_start(args, condition);
339 |
340 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
341 |
342 | va_end(args);
343 |
344 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error whereAllTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditions:conditions];
345 |
346 | if (x && *error == nil) {
347 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
348 | }
349 |
350 | return [self fetchDBSyncMultipleWithError:error whereAllTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditionsArray:conditions];
351 | }
352 |
353 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditionsArray:(nonnull NSArray * )conditions
354 | {
355 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error whereAllTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditions:conditions];
356 |
357 | if (x && *error == nil) {
358 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
359 | }
360 |
361 | return self;
362 |
363 | }
364 |
365 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...
366 | {
367 | va_list args;
368 | va_start(args, condition);
369 |
370 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
371 |
372 | va_end(args);
373 |
374 | return [self fetchDBSyncMultipleWithError:error whereAllTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditionsArray:conditions];
375 | }
376 |
377 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetConditionsArray:(nonnull NSArray * )conditions
378 | {
379 |
380 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error wherePartOfTheConditionsAreMet:conditions];
381 |
382 | if (x && *error == nil) {
383 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
384 | }
385 |
386 | return self;
387 | }
388 |
389 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMet:(nonnull NSString * )condition, ...
390 | {
391 | va_list args;
392 | va_start(args, condition);
393 |
394 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
395 |
396 | va_end(args);
397 |
398 | return [self fetchDBSyncMultipleWithError:error wherePartOfTheConditionsAreMetConditionsArray:conditions];
399 | }
400 |
401 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditionsArray:(nonnull NSArray * )conditions
402 | {
403 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error wherePartOfTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditions:conditions];
404 |
405 | if (x && *error == nil) {
406 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
407 | }
408 |
409 | return self;
410 | }
411 |
412 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...
413 | {
414 | va_list args;
415 | va_start(args, condition);
416 |
417 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
418 |
419 | va_end(args);
420 |
421 | return [self fetchDBSyncMultipleWithError:error wherePartOfTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditionsArray:conditions];
422 | }
423 |
424 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditionsArray:(nonnull NSArray * )conditions
425 | {
426 | NSArray * x = [self.dbSync fetchMultipleSyncWithError:error wherePartOfTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditions:conditions];
427 |
428 | if (x && *error == nil) {
429 | [self resetModels:[self transformerProxyOfResponse:x error:error]];
430 | }
431 |
432 | return self;
433 | }
434 |
435 | - (nonnull instancetype) fetchDBSyncMultipleWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...
436 | {
437 | va_list args;
438 | va_start(args, condition);
439 |
440 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
441 |
442 | va_end(args);
443 |
444 | return [self fetchDBSyncMultipleWithError:error wherePartOfTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditionsArray:conditions];
445 | }
446 |
447 | - (BOOL) destroyDBSyncAllWithError:(NSError * _Nullable * _Nullable) error
448 | {
449 | return [self.dbSync destroyAllSyncWithError:error];
450 | }
451 |
452 | - (nullable NSArray *) arrayWithRange:(NSRange)range
453 | {
454 | if (range.location + range.length > self.models.count) {
455 | return nil;
456 | }
457 |
458 | return [self.models subarrayWithRange:range];
459 | }
460 |
461 | - (nullable YTXRestfulCollection *) collectionWithRange:(NSRange)range
462 | {
463 | NSArray * arr = [self arrayWithRange:range];
464 |
465 | return arr ? [[[YTXRestfulCollection alloc] initWithModelClass:self.modelClass] addModels:arr] : nil;
466 | }
467 |
468 | - (nullable YTXRestfulModel *) modelAtIndex:(NSInteger) index
469 | {
470 | if (index < 0 || index >= self.models.count) {
471 | return nil;
472 | }
473 |
474 | return self.models[index];
475 | }
476 |
477 | - (nullable YTXRestfulModel *) modelWithPrimaryKey:(nonnull NSString *) primaryKey
478 | {
479 | for (YTXRestfulModel *model in self.models) {
480 | if ( [[[model primaryValue] description] isEqualToString:primaryKey]) {
481 | return model;
482 | }
483 | }
484 | return nil;
485 | }
486 |
487 | - (BOOL) addModel:(nonnull YTXRestfulModel *) model
488 | {
489 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
490 | [temp addObject:model];
491 | [self resetModels:temp];
492 | return YES;
493 | }
494 |
495 | - (BOOL) insertFrontModel:(nonnull YTXRestfulModel *) model
496 | {
497 | return [self insertModel:model beforeIndex:0];
498 | }
499 |
500 | /** 插入到index之后*/
501 | - (BOOL) insertModel:(nonnull YTXRestfulModel *) model afterIndex:(NSInteger) index
502 | {
503 | if (self.models.count == 0 || self.models.count == index+1) {
504 | return [self addModel:model];
505 | }
506 |
507 | if (index < 0 || index >= self.models.count) {
508 | return NO;
509 | }
510 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
511 | [temp insertObject:model atIndex:index+1];
512 | [self resetModels:temp];
513 | return YES;
514 | }
515 |
516 | /** 插入到index之前*/
517 | - (BOOL) insertModel:(nonnull YTXRestfulModel *) model beforeIndex:(NSInteger) index
518 | {
519 | if (self.models.count == 0) {
520 | return [self addModel:model];
521 | }
522 |
523 | if (index < 0 || index >= self.models.count) {
524 | return NO;
525 | }
526 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
527 | [temp insertObject:model atIndex:index];
528 | [self resetModels:temp];
529 | return YES;
530 | }
531 |
532 | - (BOOL) removeModelAtIndex:(NSInteger) index
533 | {
534 | if (index < 0 || index >= self.models.count) {
535 | return NO;
536 | }
537 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
538 | [temp removeObjectAtIndex:index];
539 | [self resetModels:temp];
540 | return YES;
541 | }
542 |
543 | /** 主键可能是NSNumber或NSString,统一转成NSString来判断*/
544 | - (BOOL) removeModelWithPrimaryKey:(nonnull NSString *) primaryKey
545 | {
546 | for (YTXRestfulModel *model in self.models) {
547 | if ( [[[model primaryValue] description] isEqualToString:primaryKey]) {
548 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
549 | [temp removeObject:model];
550 | [self resetModels:temp];
551 | return YES;
552 | }
553 | }
554 | return NO;
555 | }
556 |
557 | - (BOOL) removeModelWithModel:(nonnull YTXRestfulModel *) model
558 | {
559 | NSMutableArray * temp = [NSMutableArray arrayWithArray:self.models];
560 |
561 | NSInteger index = [[self models] indexOfObject:model];
562 |
563 | if (NSNotFound == index) {
564 | return NO;
565 | }
566 |
567 | [temp removeObjectAtIndex:index];
568 | [self resetModels:temp];
569 | return YES;
570 | }
571 |
572 | - (void)reverseModels
573 | {
574 | [self resetModels:self.models.reverseObjectEnumerator.allObjects];
575 | }
576 |
577 | - (nonnull NSArray *) arrayWithArgs:(va_list) args firstArgument:(nullable id)firstArgument
578 | {
579 | if (firstArgument == nil) {
580 | return @[];
581 | }
582 |
583 | NSMutableArray * array = [NSMutableArray arrayWithObject:firstArgument];
584 | id arg = nil;
585 | while ((arg = va_arg(args,id))) {
586 | [array addObject:arg];
587 | }
588 | return array;
589 | }
590 |
591 | - (nonnull NSArray *) arrayOfMappedArgsWithOriginArray:(nonnull NSArray *)originArray
592 | {
593 | NSDictionary * propertiesMap = [self.modelClass JSONKeyPathsByPropertyKey];
594 | NSMutableArray *retArray = [NSMutableArray array];
595 | for (id arg in originArray) {
596 | [retArray addObject:propertiesMap[arg] ?: arg];
597 | }
598 | return retArray;
599 | }
600 |
601 | - (id)storageSync
602 | {
603 | YTXAssertSyncExists(_storageSync, @"StorageSync");
604 | return _storageSync;
605 | }
606 |
607 | -(id)dbSync
608 | {
609 | YTXAssertSyncExists(_dbSync, @"DBSync");
610 | return _dbSync;
611 | }
612 |
613 | -(id)remoteSync
614 | {
615 | YTXAssertSyncExists(_remoteSync, @"RemoteSync");
616 | return _remoteSync;
617 | }
618 |
619 | @end
620 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/YTXRestfulModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXModel.h
3 | // YTXRestfulModel
4 | //
5 | // Created by cao jun on 16/01/25.
6 | // Copyright © 2015 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulModelProtocol.h"
10 | #import "YTXRestfulModelStorageProtocol.h"
11 | #import "YTXRestfulModelRemoteProtocol.h"
12 | #import "YTXRestfulModelDBProtocol.h"
13 | #import
14 | #import
15 | #import
16 |
17 | #define YTXAssertSyncExists(__SYNC__, __DESC__) \
18 | NSAssert(__SYNC__ != nil, @"应该在pod中安装%@ 像这样:%@", __DESC__, @"pod 'YTXRestfulModel', :path => '../', :subspecs => [ 'FMDBSync', 'UserDefaultStorageSync']");\
19 |
20 | @interface YTXRestfulModel : MTLModel
21 |
22 | @property (nonnull, nonatomic, strong) id storageSync;
23 | @property (nonnull, nonatomic, strong) id remoteSync;
24 | @property (nonnull, nonatomic, strong) id dbSync;
25 |
26 |
27 | - (nonnull instancetype) mergeWithAnother:(_Nonnull id) model;
28 |
29 | /** 要用keyId判断 */
30 | - (BOOL) isNew;
31 |
32 | /** 需要告诉我主键是什么,子类也应当实现 */
33 | + (nonnull NSString *) primaryKey;
34 |
35 | + (nonnull NSString *)syncPrimaryKey;
36 |
37 | /** 方便的直接取主键的值*/
38 | - (nullable id) primaryValue;
39 |
40 | /** 在拉到数据转mantle的时候用 */
41 | - (nonnull instancetype) transformerProxyOfResponse:(nonnull id) response error:(NSError * _Nullable * _Nullable) error;
42 |
43 | /** 在拉到数据转外部mantle对象的时候用 */
44 | - (nonnull id) transformerProxyOfForeign:(nonnull Class)modelClass response:(nonnull id) response error:(NSError * _Nullable * _Nullable) error;
45 |
46 | /** 将自身转化为Dictionary,然后对传入参数进行和自身属性的融合。自身的属性优先级最高,不可被传入参数修改。 */
47 | - (nonnull NSDictionary *)mergeSelfAndParameters:(nullable NSDictionary *)param;
48 |
49 | - (nonnull NSString *) storageKeyWithParam:(nullable NSDictionary *) param;
50 |
51 | /** GET */
52 | - (nullable instancetype) fetchStorageSync:(nullable NSDictionary *) param;
53 |
54 | /** POST / PUT */
55 | - (nonnull instancetype) saveStorageSync:(nullable NSDictionary *) param;
56 |
57 | /** DELETE */
58 | - (void) destroyStorageSync:(nullable NSDictionary *) param;
59 |
60 | /** GET */
61 | - (nullable instancetype) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
62 |
63 | /** POST / PUT */
64 | - (nonnull instancetype) saveStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
65 |
66 | /** DELETE */
67 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
68 |
69 |
70 | /** :id/comment 这种形式的时候使用GET; modelClass is MTLModel*/
71 | - (void) fetchRemoteForeignWithName:(nonnull NSString *)name modelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
72 | /** GET */
73 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
74 | /** POST / PUT */
75 | - (void) saveRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
76 | /** DELETE */
77 | - (void) destroyRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
78 |
79 | /** 主键是否自增,默认为YES */
80 | + (BOOL) isPrimaryKeyAutoincrement;
81 |
82 | /** 若主键是NSNumber 将会默认设置为自增的 */
83 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey;
84 |
85 | + (nullable NSNumber *) currentMigrationVersion;
86 |
87 | + (void) migrationsMethodWithSync:(nonnull id)sync;
88 |
89 | /** GET */
90 | - (nonnull instancetype) fetchDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
91 |
92 | /**
93 | * POST / PUT
94 | * 数据库不存在时创建,否则更新
95 | * 更新必须带主键
96 | */
97 | - (nonnull instancetype) saveDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
98 |
99 | /** DELETE */
100 | - (BOOL) destroyDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
101 |
102 | /** GET Foreign Models with primary key */
103 | - (nonnull NSArray *) fetchDBForeignSyncWithModelClass:(nonnull Class)modelClass error:(NSError * _Nullable * _Nullable) error param:(nullable NSDictionary *)param;
104 |
105 | @end
106 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/YTXRestfulModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXModel.m
3 | // YTXRestfulModel
4 | //
5 | // Created by cao jun on 16/01/25.
6 | // Copyright © 2015 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulModel.h"
10 |
11 | #ifdef YTX_USERDEFAULTSTORAGESYNC_EXISTS
12 | #import "YTXRestfulModelUserDefaultStorageSync.h"
13 | #endif
14 |
15 | #ifdef YTX_AFNETWORKINGREMOTESYNC_EXISTS
16 | #import "AFNetworkingRemoteSync.h"
17 | #endif
18 |
19 | #ifdef YTX_FMDBSYNC_EXISTS
20 | #import "YTXRestfulModelFMDBSync.h"
21 | #import "NSValue+YTXRestfulModelFMDBSync.h"
22 | #endif
23 |
24 | #import
25 | #import
26 |
27 | #import
28 |
29 | @implementation YTXRestfulModelDBSerializingModel
30 |
31 | @end
32 |
33 | @implementation YTXRestfulModelDBMigrationEntity
34 |
35 | @end
36 |
37 | @implementation YTXRestfulModel
38 |
39 | - (instancetype)init
40 | {
41 | if(self = [super init])
42 | {
43 | #ifdef YTX_USERDEFAULTSTORAGESYNC_EXISTS
44 | self.storageSync = [YTXRestfulModelUserDefaultStorageSync new];
45 | #endif
46 |
47 | #ifdef YTX_AFNETWORKINGREMOTESYNC_EXISTS
48 | self.remoteSync = [AFNetworkingRemoteSync syncWithPrimaryKey: [[self class] syncPrimaryKey]];
49 | #endif
50 |
51 | #ifdef YTX_FMDBSYNC_EXISTS
52 | self.dbSync = [YTXRestfulModelFMDBSync syncWithModelOfClass:[self class] primaryKey: [[self class] syncPrimaryKey]];
53 | #endif
54 | }
55 | return self;
56 | }
57 |
58 | #pragma mark MTL
59 | - (NSDictionary *)dictionaryValue {
60 | NSDictionary *originalDictValue = [super dictionaryValue];
61 | NSMutableDictionary *dictValue = [originalDictValue mutableCopy];
62 | for (NSString *key in originalDictValue) {
63 | if ([self valueForKey:key] == nil) {
64 | [dictValue removeObjectForKey:key];
65 | }
66 | }
67 | //删除这个2个不必要的属性 可以用http://stackoverflow.com/questions/18961622/how-to-omit-null-values-in-json-dictionary-using-mantle这些方法,但是最合理的还是这个。
68 | [dictValue removeObjectForKey:@"remoteSync"];
69 | [dictValue removeObjectForKey:@"storageSync"];
70 | [dictValue removeObjectForKey:@"dbSync"];
71 | return [dictValue copy];
72 | }
73 |
74 |
75 | //Mantle的model属性和目标源属性的映射表。DBSync也会使用。
76 | + (NSDictionary *)JSONKeyPathsByPropertyKey
77 | {
78 | return @{};
79 | }
80 |
81 | #pragma mark EFSModelProtocol
82 |
83 | - (nonnull instancetype) mergeWithAnother:(_Nonnull id) model
84 | {
85 | if ([self class] != [model class]){
86 | return self;
87 | }
88 | NSSet * keys = [[self class] propertyKeys];
89 |
90 | for (NSString * key in keys) {
91 | id value = [model valueForKey:key];
92 | if (value) {
93 | [self setValue:value forKey:key];
94 | }
95 | }
96 | return self;
97 | }
98 |
99 | //主键名。在Model上的名字
100 | + (nonnull NSString *)primaryKey
101 | {
102 | return @"keyId";
103 | }
104 |
105 | - (nullable id) primaryValue
106 | {
107 | return [self valueForKey:[[self class] primaryKey]];
108 | }
109 |
110 | + (nonnull NSString *)syncPrimaryKey
111 | {
112 | return [self JSONKeyPathsByPropertyKey][[self primaryKey]] ?: [self primaryKey];
113 | }
114 |
115 | /** 要用keyId判断 */
116 | - (BOOL) isNew
117 | {
118 | return [self primaryValue] == nil;
119 | }
120 |
121 |
122 | #pragma mark storage
123 | /** GET */
124 | - (nullable instancetype) fetchStorageSync:(nullable NSDictionary *) param
125 | {
126 | return [self fetchStorageSyncWithKey:[self storageKeyWithParam:param] param:param];
127 | }
128 |
129 | /** POST / PUT */
130 | - (nonnull instancetype) saveStorageSync:(nullable NSDictionary *) param
131 | {
132 | return [self saveStorageSyncWithKey:[self storageKeyWithParam:param] param:param];
133 | }
134 |
135 | /** DELETE */
136 | - (void) destroyStorageSync:(nullable NSDictionary *) param
137 | {
138 | return [self destroyStorageSyncWithKey:[self storageKeyWithParam:param] param:param];
139 | }
140 |
141 | /** GET */
142 | - (nullable instancetype) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
143 | {
144 | NSDictionary * dict = [self.storageSync fetchStorageSyncWithKey:storage param:param];
145 | if (dict) {
146 | NSError * error;
147 | [self transformerProxyOfResponse:dict error:&error];
148 | if (!error) {
149 | return self;
150 | }
151 |
152 | }
153 | return nil;
154 | }
155 |
156 | /** POST / PUT */
157 | - (nonnull instancetype) saveStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
158 | {
159 | [self.storageSync saveStorageSyncWithKey:storage withObject:[self mergeSelfAndParameters:param] param:param];
160 | return self;
161 | }
162 |
163 | /** DELETE */
164 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
165 | {
166 | [self.storageSync destroyStorageSyncWithKey:storage param:param];
167 | }
168 |
169 |
170 | - (nonnull NSString *) storageKeyWithParam:(nullable NSDictionary *) param
171 | {
172 | NSDictionary * dict = [self mergeSelfAndParameters:param];
173 | id primaryKeyValue = dict[[[self class] syncPrimaryKey]];
174 |
175 | NSAssert(primaryKeyValue != nil, @"Stroage必须找到主键的值");
176 |
177 | return [NSString stringWithFormat:@"EFSModel+%@+%@", NSStringFromClass([self class]), [primaryKeyValue description]];
178 | }
179 |
180 | #pragma mark remote
181 | /** 在拉到数据转mantle的时候用 */
182 | - (nonnull instancetype) transformerProxyOfResponse:(nonnull id) response error:(NSError * _Nullable * _Nullable) error
183 | {
184 | return [self mergeWithAnother:[MTLJSONAdapter modelOfClass:[self class] fromJSONDictionary:response error:error]];
185 | }
186 |
187 | - (nonnull NSDictionary *)mapParameters:(nonnull NSDictionary *)param
188 | {
189 | NSMutableDictionary * retDict = [NSMutableDictionary dictionary];
190 |
191 | NSMutableDictionary *_JSONKeyPathsByPropertyKey = [[[self class] JSONKeyPathsByPropertyKey] copy];
192 |
193 | NSString * mappedPropertyKey = nil;
194 |
195 | for (NSString *key in param) {
196 |
197 | mappedPropertyKey = _JSONKeyPathsByPropertyKey[key] ? : key;
198 |
199 | retDict[mappedPropertyKey] = param[key];
200 | }
201 |
202 | return retDict;
203 | }
204 |
205 | - (nonnull NSDictionary *)mergeSelfAndParameters:(nullable NSDictionary *)param
206 | {
207 | NSDictionary * mapParam = [self mapParameters:param];
208 |
209 | NSMutableDictionary *retDic = [[MTLJSONAdapter JSONDictionaryFromModel:self] mutableCopy];
210 |
211 | for (NSString *key in mapParam) {
212 | retDic[key] = mapParam[key];
213 | }
214 | return retDic;
215 | }
216 |
217 | - (nonnull NSDictionary *)mergeSelfPrimaryKeyAndParameters:(nullable NSDictionary *)param
218 | {
219 | NSDictionary * mapParam = [self mapParameters:param];
220 |
221 | NSDictionary *dic = [MTLJSONAdapter JSONDictionaryFromModel:self];
222 |
223 | NSMutableDictionary *retDic = [NSMutableDictionary dictionary];
224 |
225 | if (dic[[[self class] syncPrimaryKey]] != nil) {
226 | retDic[[[self class] syncPrimaryKey]] = dic[[[self class] syncPrimaryKey]];
227 | }
228 |
229 | for (NSString *key in mapParam) {
230 | retDic[key] = mapParam[key];
231 | }
232 | return retDic;
233 | }
234 |
235 | - (nonnull id) transformerProxyOfForeign:(nonnull Class)modelClass response:(nonnull id) response error:(NSError * _Nullable * _Nullable) error;
236 | {
237 | return [MTLJSONAdapter modelsOfClass:modelClass fromJSONArray:response error:error];
238 | }
239 |
240 | - (void) fetchRemoteForeignWithName:(nonnull NSString *)name modelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
241 | {
242 | __weak __typeof(&*self)weakSelf = self;
243 | [self.remoteSync fetchRemoteForeignWithName:name param:[self mergeSelfAndParameters:param] success:^(id _Nullable response) {
244 | NSError * error = nil;
245 | id model = [weakSelf transformerProxyOfForeign:modelClass response:response error:&error];
246 | if (!error) {
247 | success(model);
248 | }
249 | else {
250 | failed(error);
251 | }
252 | } failed:failed];
253 | }
254 |
255 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
256 | {
257 | __weak __typeof(&*self)weakSelf = self;
258 | [self.remoteSync fetchRemote:[self mergeSelfPrimaryKeyAndParameters:param] success:^(id _Nullable response) {
259 | NSError * error = nil;
260 | id model = [weakSelf transformerProxyOfResponse:response error:&error];
261 | if (!error) {
262 | success(model);
263 | }
264 | else {
265 | failed(error);
266 | }
267 | } failed:failed];
268 | }
269 |
270 | - (void) saveRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
271 | {
272 | __weak __typeof(&*self)weakSelf = self;
273 | if ([self isNew]) {
274 | [self.remoteSync createRemote:[self mergeSelfAndParameters:param] success:^(id _Nullable response) {
275 | NSError * error = nil;
276 | id model = [weakSelf transformerProxyOfResponse:response error:&error];
277 | if (!error) {
278 | success(model);
279 | }
280 | else {
281 | failed(error);
282 | }
283 | } failed:failed];
284 | } else {
285 | [self.remoteSync updateRemote:[self mergeSelfAndParameters:param] success:^(id _Nullable response) {
286 | NSError * error = nil;
287 | id model = [weakSelf transformerProxyOfResponse:response error:&error];
288 | if (!error) {
289 | success(model);
290 | }
291 | else {
292 | failed(error);
293 | }
294 | } failed:failed];
295 | }
296 | }
297 |
298 | - (void) destroyRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
299 | {
300 | __weak __typeof(&*self)weakSelf = self;
301 | [self.remoteSync destroyRemote:[self mergeSelfAndParameters:param] success:^(id _Nullable response) {
302 | NSError * error = nil;
303 | id model = [weakSelf transformerProxyOfResponse:response error:&error];
304 | if (!error) {
305 | success(model);
306 | }
307 | else {
308 | failed(error);
309 | }
310 | } failed:failed];
311 | }
312 |
313 | + (nonnull NSMutableDictionary *> *) _tableKeyPathsByPropertyKeyMap
314 | {
315 | static NSMutableDictionary *> * map;
316 |
317 | if (map == nil) {
318 | map = [NSMutableDictionary dictionary];
319 | }
320 |
321 | return map;
322 | }
323 |
324 | + (nonnull NSString *) _tableKeyPathsCachedKey
325 | {
326 | return [NSString stringWithFormat:@"YTX.%@", NSStringFromClass([self class])];
327 | }
328 |
329 | #pragma mark DB
330 | + (BOOL) isPrimaryKeyAutoincrement
331 | {
332 | return YES;
333 | }
334 |
335 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey
336 | {
337 | NSMutableDictionary * cachedKeys = [self _tableKeyPathsByPropertyKeyMap][[self _tableKeyPathsCachedKey]];
338 |
339 | if (cachedKeys != nil) {
340 | return cachedKeys;
341 | }
342 |
343 | __block NSMutableDictionary * properties = [NSMutableDictionary dictionary];
344 |
345 | #pragma clang diagnostic push
346 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
347 |
348 | [[self class] performSelector:NSSelectorFromString(@"enumeratePropertiesUsingBlock:") withObject:^(objc_property_t property, BOOL *stop) {
349 | mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property);
350 | char *propertyType = property_copyAttributeValue(property, "T");
351 | @onExit {
352 | free(attributes);
353 | free(propertyType);
354 | };
355 |
356 | if (attributes->readonly && attributes->ivar == NULL) return;
357 |
358 | NSString *modelProperyName = [NSString stringWithUTF8String:property_getName(property)];
359 |
360 | if ([modelProperyName isEqualToString:@"dbSync"] || [modelProperyName isEqualToString:@"remoteSync"] || [modelProperyName isEqualToString:@"storageSync"]) {
361 | return;
362 | }
363 |
364 | NSString *columnName = [self JSONKeyPathsByPropertyKey][modelProperyName] ? : modelProperyName;
365 |
366 | NSString * propertyClassName = [[self class] formateObjectType:propertyType];
367 |
368 | BOOL isPrimaryKey = [modelProperyName isEqualToString:[self primaryKey]];
369 |
370 | BOOL isPrimaryKeyAutoincrement = NO;
371 | if (isPrimaryKey) {
372 | isPrimaryKeyAutoincrement = [self isPrimaryKeyAutoincrement];
373 | }
374 |
375 | YTXRestfulModelDBSerializingModel * dbsm = [YTXRestfulModelDBSerializingModel new];
376 | dbsm.objectClass = propertyClassName;
377 | dbsm.columnName = columnName;
378 | dbsm.modelName = modelProperyName;
379 | dbsm.isPrimaryKey = isPrimaryKey;
380 | dbsm.autoincrement = isPrimaryKeyAutoincrement;
381 | dbsm.unique = NO;
382 |
383 | [properties setObject:dbsm forKey:columnName];
384 | }];
385 | #pragma clang diagnostic pop
386 |
387 | [self _tableKeyPathsByPropertyKeyMap][[self _tableKeyPathsCachedKey]] = properties;
388 |
389 | return properties;
390 | }
391 |
392 | + (nullable NSNumber *) currentMigrationVersion
393 | {
394 | return @0;
395 | }
396 |
397 | + (BOOL) autoAlterTable
398 | {
399 | return YES;
400 | }
401 |
402 | + (BOOL) autoCreateTable
403 | {
404 | return NO;
405 | }
406 |
407 | + (void) migrationsMethodWithSync:(nonnull id)sync;
408 | {
409 |
410 | }
411 |
412 | + (void)dbWillMigrateWithSync:(nonnull id)sync
413 | {
414 |
415 | }
416 |
417 | + (void)dbDidMigrateWithSync:(nonnull id)sync
418 | {
419 |
420 | }
421 |
422 | /** GET */
423 | - (nonnull instancetype) fetchDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error
424 | {
425 | NSDictionary * x = [self.dbSync fetchOneSync:[self mergeSelfAndParameters:param] error:error];
426 |
427 | if (x && *error == nil ) {
428 | [self transformerProxyOfResponse:x error:error];
429 | }
430 | return self;
431 | }
432 |
433 | /**
434 | * POST / PUT
435 | * 数据库不存在时创建,否则更新
436 | * 更新必须带主键
437 | */
438 | - (nonnull instancetype) saveDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error
439 | {
440 | NSDictionary * x = [self.dbSync saveOneSync:[self mergeSelfAndParameters:param] error:error];
441 |
442 | if (x && *error == nil ) {
443 | [self transformerProxyOfResponse:x error:error];
444 | }
445 |
446 | return self;
447 | }
448 |
449 |
450 | /** DELETE */
451 | - (BOOL) destroyDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error
452 | {
453 | return [self.dbSync destroyOneSync:[self mergeSelfAndParameters:param] error:error];
454 | }
455 |
456 | /** GET Foreign Models with primary key */
457 | - (nonnull NSArray *) fetchDBForeignSyncWithModelClass:(nonnull Class)modelClass error:(NSError * _Nullable * _Nullable) error param:(nullable NSDictionary *)param
458 | {
459 | NSDictionary * dict = [self mergeSelfAndParameters:param];
460 |
461 | id primaryKeyValue = dict[[[self class] syncPrimaryKey]];
462 |
463 | NSAssert(primaryKeyValue != nil, @"主键的值不能为空");
464 |
465 | NSArray * x = [self.dbSync fetchForeignSyncWithModelClass:modelClass primaryKeyValue:primaryKeyValue error:error param:dict];
466 |
467 | return [self transformerProxyOfForeign:modelClass response:x error:error];
468 | }
469 |
470 | #pragma mark - tools
471 | + (nonnull NSString*) formateObjectType:(const char* _Nonnull )objcType
472 | {
473 | if (!objcType || !strlen(objcType)) return nil;
474 | NSString* type = [NSString stringWithCString:objcType encoding:NSUTF8StringEncoding];
475 |
476 | switch (objcType[0]) {
477 | case '@':
478 | type = [type substringWithRange:NSMakeRange(2, strlen(objcType)-3)];
479 | break;
480 | case '{':
481 | type = [type substringWithRange:NSMakeRange(1, strchr(objcType, '=')-objcType-1)];
482 | break;
483 | default:
484 | break;
485 | }
486 | return type;
487 | }
488 |
489 |
490 | - (id)storageSync
491 | {
492 | YTXAssertSyncExists(_storageSync, @"StorageSync");
493 | return _storageSync;
494 | }
495 |
496 | -(id)dbSync
497 | {
498 | YTXAssertSyncExists(_dbSync, @"DBSync");
499 | return _dbSync;
500 | }
501 |
502 | -(id)remoteSync
503 | {
504 | YTXAssertSyncExists(_remoteSync, @"RemoteSync");
505 | return _remoteSync;
506 | }
507 |
508 | @end
509 |
--------------------------------------------------------------------------------
/Pod/Classes/Protocol/YTXRestfulModelDBProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelDBProtocol.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/19.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef enum : NSUInteger {
12 | YTXRestfulModelDBErrorCodeNotFound = 0,
13 | YTXRestfulModelDBErrorCodeNotColumns = 1,
14 | YTXRestfulModelDBErrorCodeUnkonw = 9999
15 | } YTXRestfulModelDBErrorCode;
16 |
17 | typedef enum : NSUInteger {
18 | //升序
19 | YTXRestfulModelDBSortByDESC,
20 | //降序
21 | YTXRestfulModelDBSortByASC
22 | } YTXRestfulModelDBSortBy;
23 |
24 | @interface YTXRestfulModelDBSerializingModel : NSObject
25 |
26 | /** 可以是CType @"d"这种*/
27 | @property (nonatomic, nonnull, copy) NSString * objectClass;
28 |
29 | /** 表名 */
30 | @property (nonatomic, nonnull, copy) NSString * columnName;
31 |
32 | /** Model原始的属性名字 */
33 | @property (nonatomic, nonnull, copy) NSString * modelName;
34 |
35 | @property (nonatomic, assign) BOOL isPrimaryKey;
36 |
37 | @property (nonatomic, assign) BOOL autoincrement;
38 |
39 | @property (nonatomic, assign) BOOL unique;
40 |
41 | @property (nonatomic, nonnull, copy) NSString * defaultValue;
42 |
43 | /** 外键类名 可以使用fetchForeignWithName */
44 | @property (nonatomic, nonnull, copy) NSString * foreignClassName;
45 |
46 | @end
47 |
48 | @protocol YTXRestfulModelDBProtocol;
49 |
50 | @protocol YTXRestfulModelDBSerializing
51 |
52 | /** NSDictionary */
53 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey;
54 |
55 | + (nullable NSNumber *) currentMigrationVersion;
56 |
57 | + (BOOL) autoAlterTable;
58 |
59 | + (BOOL) autoCreateTable;
60 |
61 | + (BOOL) isPrimaryKeyAutoincrement;
62 |
63 | + (void) migrationsMethodWithSync:(nonnull id)sync;
64 |
65 | @optional
66 | /** 在这个方法内migrateWithVersion*/
67 | + (void) dbWillMigrateWithSync:(nonnull id)sync;
68 |
69 | + (void) dbDidMigrateWithSync:(nonnull id)sync;
70 |
71 | @end
72 |
73 |
74 | typedef void (^YTXRestfulModelMigrationBlock)(_Nonnull id, NSError * _Nullable * _Nullable);
75 |
76 | @interface YTXRestfulModelDBMigrationEntity : NSObject
77 |
78 | @property (nonnull, nonatomic, copy) YTXRestfulModelMigrationBlock block;
79 | @property (nonnull, nonatomic, copy) NSNumber *version;
80 |
81 | @end
82 |
83 | @protocol YTXRestfulModelDBProtocol
84 |
85 | @required
86 |
87 | @property (nonatomic, assign, readonly, nonnull) Class modelClass;
88 |
89 | @property (nonnull, nonatomic, copy, readonly) NSString * primaryKey;
90 |
91 | + (nonnull instancetype) syncWithModelOfClass:(nonnull Class) modelClass primaryKey:(nonnull NSString *) key;
92 |
93 | + (nonnull NSString *) path;
94 |
95 | - (nonnull NSString *) tableName;
96 |
97 | - (nonnull instancetype) initWithModelOfClass:(nonnull Class) modelClass primaryKey:(nonnull NSString *) key;
98 |
99 | - (nonnull NSError *) createTable;
100 |
101 | - (nonnull NSError *) dropTable;
102 |
103 | //操作将会保证在migration之后进行
104 |
105 | /** GET Model with primary key */
106 | - (nullable NSDictionary *) fetchOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
107 |
108 | /** POST / PUT Model with primary key */
109 | - (nullable NSDictionary *) saveOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
110 |
111 | /** DELETE Model with primary key */
112 | - (BOOL) destroyOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
113 |
114 | /** GET */
115 | - (nullable NSDictionary *) fetchTopOneSyncWithError:(NSError * _Nullable * _Nullable) error;
116 |
117 | /** GET */
118 | - (nullable NSDictionary *) fetchLatestOneSyncWithError:(NSError * _Nullable * _Nullable) error;
119 |
120 | /** DELETE All Model with primary key */
121 | - (BOOL) destroyAllSyncWithError:(NSError * _Nullable * _Nullable) error;
122 |
123 | /** GET Foreign Models with primary key */
124 | - (nonnull NSArray *) fetchForeignSyncWithModelClass:(nonnull Class)modelClass primaryKeyValue:(nonnull id) value error:(NSError * _Nullable * _Nullable) error param:(nullable NSDictionary *)param;
125 |
126 | /** ORDER BY primaryKey ASC*/
127 | - (nonnull NSArray *) fetchAllSyncWithError:(NSError * _Nullable * _Nullable) error;
128 |
129 |
130 | - (nonnull NSArray *) fetchAllSyncWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSArray * )columnNames;
131 |
132 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSArray * )columnNames;
133 |
134 | /**
135 | * ORDER BY primaryKey ASC
136 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
137 | */
138 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMet:(nonnull NSArray * )conditions;
139 |
140 | /**
141 | * ORDER BY primaryKey ASC
142 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
143 | */
144 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSArray * )conditions;
145 |
146 | /**
147 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
148 | */
149 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSArray * )conditions;
150 |
151 | /**
152 | * ORDER BY primaryKey ASC
153 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
154 | */
155 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMet:(nonnull NSArray * )conditions;
156 |
157 | /**
158 | * ORDER BY primaryKey ASC
159 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
160 | */
161 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSArray * )conditions;
162 |
163 | /**
164 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
165 | */
166 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSArray * )conditions;
167 |
168 |
169 | //Migration
170 |
171 | /** 数字越大越后面执行*/
172 |
173 | @property (nonatomic, strong, readonly, nonnull) NSMutableArray * migrationBlocks;
174 |
175 | /** 大于currentMigrationVersion将会依次执行,数字越大越后执行*/
176 | - (void) migrate:(nonnull YTXRestfulModelDBMigrationEntity *) entity;
177 |
178 | - (BOOL) createColumnWithDB:(nonnull id)db structSync:(nonnull YTXRestfulModelDBSerializingModel *)sstruct error:(NSError * _Nullable * _Nullable)error;
179 |
180 | @optional
181 |
182 | - (BOOL) renameColumnWithDB:(nonnull id)db originName:(nonnull NSString *)originName newName:(nonnull NSString *)newName error:(NSError * _Nullable * _Nullable)error;
183 |
184 | - (BOOL) dropColumnWithDB:(nonnull id)db structSync:(nonnull YTXRestfulModelDBSerializingModel *)sstruct error:(NSError * _Nullable * _Nullable)error;
185 |
186 | - (BOOL) changeCollumnDB:(nonnull id)db oldStructSync:(nonnull YTXRestfulModelDBSerializingModel *) oldStruct toNewStruct:(nonnull YTXRestfulModelDBSerializingModel *) newStruct error:(NSError * _Nullable * _Nullable)error;
187 |
188 | @end
189 |
--------------------------------------------------------------------------------
/Pod/Classes/Protocol/YTXRestfulModelProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelProtocol.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //尽量想写成Restful
12 | @protocol YTXRestfulModelProtocol
13 |
14 | @required
15 | - (nonnull instancetype) mergeWithAnother:(_Nonnull id) model;
16 |
17 | /** 需要告诉我主键PrimaryKey是什么 */
18 | + (nonnull NSString *) primaryKey;
19 |
20 | + (nonnull NSString *)syncPrimaryKey;
21 | /** 知道主键后我可以方便的直接取Value */
22 | - (nullable id) primaryValue;
23 | /** 要用keyId判断 */
24 | - (BOOL) isNew;
25 |
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Pod/Classes/Protocol/YTXRestfulModelRemoteProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelRemoteProtocol.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef NSDictionary * _Nonnull(^YTXRestfulModelRemoteHookExtraParamBlock)();
12 | typedef void(^YTXRestfulModelRemoteHookRequestBlock)(_Nonnull id request, NSString * _Nonnull method, NSURL * _Nonnull *_Nonnull url, NSMutableDictionary * _Nonnull * _Nonnull parameters);
13 |
14 | typedef void (^YTXRestfulModelRemoteSuccessBlock)(id _Nullable response);
15 | typedef void (^YTXRestfulModelRemoteFailedBlock)(NSError * _Nullable error);
16 |
17 | @protocol YTXRestfulModelRemoteProtocol
18 |
19 | @required
20 |
21 | /** 超时时间 */
22 | @property (nonatomic, assign) NSTimeInterval timeoutInterval;
23 |
24 | @property (nonnull, nonatomic, strong) NSURL * url;
25 |
26 | /** 设置网络请求的地址,通过Block形式,每次访问都会重新执行,以处理shared中URL会变的情况。同时使用URL和URLBlock会优先使用Block */
27 | @property (nullable, nonatomic, strong) NSURL * _Nonnull (^urlHookBlock)(void);
28 |
29 | @property (nonnull, nonatomic, copy, readonly) NSString * primaryKey;
30 |
31 | + (nonnull instancetype) syncWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey;
32 |
33 | + (nonnull instancetype) syncWithPrimaryKey:(nonnull NSString *) primaryKey;
34 |
35 | + (nullable YTXRestfulModelRemoteHookExtraParamBlock) hookExtraParamBlock;
36 |
37 | + (void) setHookExtraParamBlock:(nullable YTXRestfulModelRemoteHookExtraParamBlock) hookExtraParamBlock;
38 |
39 | + (nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock;
40 |
41 | + (void) setHookRequestBlock:(nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock;
42 |
43 | - (nonnull instancetype) initWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey;
44 |
45 | - (nonnull instancetype) initWithPrimaryKey:(nonnull NSString *) primaryKey;
46 |
47 | /** GET :id/commont */
48 | - (void) fetchRemoteForeignWithName:(nonnull NSString *)name param:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
49 |
50 | /** GET */
51 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
52 |
53 | /** POST */
54 | - (void) createRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
55 |
56 | /** put */
57 | - (void) updateRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
58 |
59 | /** DELETE */
60 | - (void) destroyRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Pod/Classes/Protocol/YTXRestfulModelStorageProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelStorageProtocol.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @protocol YTXRestfulModelStorageProtocol
13 |
14 | @required
15 |
16 | /** GET */
17 | - (nullable id) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
18 |
19 | /** POST / PUT */
20 | - (nullable id) saveStorageSyncWithKey:(nonnull NSString *)storage withObject:(nonnull id)object param:(nullable NSDictionary *) param;
21 |
22 | /** DELETE */
23 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
24 |
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Pod/Classes/RACSupport/YTXRestfulCollection+RACSupport.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulCollection+RACSupport.h
3 | // Pods
4 | //
5 | // Created by Chuan on 4/11/16.
6 | //
7 | //
8 |
9 | #import
10 |
11 | #import
12 | #import
13 |
14 | @interface YTXRestfulCollection (RACSupport)
15 |
16 | #pragma mark - remote
17 | /* RACSignal return self **/
18 | - (nonnull RACSignal *) rac_fetchRemote:(nullable NSDictionary *)param;
19 |
20 | /* RACSignal return self **/
21 | - (nonnull RACSignal *) rac_fetchRemoteThenAdd:(nullable NSDictionary *)param;
22 |
23 | #pragma mark - storage
24 | /** GET */
25 | - (nonnull RACSignal *) rac_fetchStorage:(nullable NSDictionary *)param;
26 |
27 | /** POST / PUT */
28 | - (nonnull RACSignal *) rac_saveStorage:(nullable NSDictionary *)param;
29 |
30 | /** DELETE */
31 | - (nonnull RACSignal *) rac_destroyStorage:(nullable NSDictionary *)param;
32 |
33 | /** GET */
34 | - (nonnull RACSignal *) rac_fetchStorageWithKey:(nonnull NSString *)storageKey param:(nullable NSDictionary *)param;
35 |
36 | /** POST / PUT */
37 | - (nonnull RACSignal *) rac_saveStorageWithKey:(nonnull NSString *)storageKey param:(nullable NSDictionary *)param;
38 |
39 | /** DELETE */
40 | - (nonnull RACSignal *) rac_destroyStorageWithKey:(nonnull NSString *)storageKey param:(nullable NSDictionary *)param;
41 |
42 | #pragma mark - db
43 | - (nonnull RACSignal *) rac_fetchDBAll;
44 |
45 | - (nonnull RACSignal *) rac_fetchDBAllSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...;
46 |
47 | - (nonnull RACSignal *) rac_fetchDBMultipleWith:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...;
48 |
49 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMet:(nonnull NSString * )condition, ...;
50 |
51 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...;
52 |
53 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...;
54 |
55 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMet:(nonnull NSString * )condition, ...;
56 |
57 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...;
58 |
59 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...;
60 |
61 | /* RACSignal return BOOL **/
62 | - (nonnull RACSignal *) rac_destroyDBAll;
63 | @end
64 |
--------------------------------------------------------------------------------
/Pod/Classes/RACSupport/YTXRestfulCollection+RACSupport.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulCollection+RACSupport.m
3 | // Pods
4 | //
5 | // Created by Chuan on 4/11/16.
6 | //
7 | //
8 |
9 | #import "YTXRestfulCollection+RACSupport.h"
10 |
11 | @implementation YTXRestfulCollection (RACSupport)
12 |
13 | #pragma mark - remote
14 |
15 | - (nonnull RACSignal *) rac_fetchRemote:(nullable NSDictionary *)param
16 | {
17 | RACSubject * subject = [RACSubject subject];
18 | [self fetchRemote:param success:^(id _Nullable response) {
19 | [subject sendNext:response];
20 | [subject sendCompleted];
21 | } failed:^(NSError * _Nullable error) {
22 | [subject sendError:error];
23 | }];
24 | return subject;
25 | }
26 |
27 | - (nonnull RACSignal *) rac_fetchRemoteThenAdd:(nullable NSDictionary *)param
28 | {
29 | RACSubject * subject = [RACSubject subject];
30 | [self fetchRemoteThenAdd:param success:^(id _Nullable response) {
31 | [subject sendNext:response];
32 | [subject sendCompleted];
33 | } failed:^(NSError * _Nullable error) {
34 | [subject sendError:error];
35 | }];
36 | return subject;
37 | }
38 |
39 | #pragma mark - storage
40 |
41 | /** GET */
42 | - (nonnull RACSignal *) rac_fetchStorage:(nullable NSDictionary *)param
43 | {
44 | return [self rac_fetchStorageWithKey:[self storageKey] param:param];
45 | }
46 |
47 | /** POST / PUT */
48 | - (nonnull RACSignal *) rac_saveStorage:(nullable NSDictionary *)param
49 | {
50 | return [self rac_saveStorageWithKey:[self storageKey] param:param];
51 | }
52 |
53 | /** DELETE */
54 | - (nonnull RACSignal *) rac_destroyStorage:(nullable NSDictionary *)param
55 | {
56 | return [self rac_destroyStorageWithKey:[self storageKey] param:param];
57 | }
58 |
59 | - (nonnull RACSignal *) rac_fetchStorageWithKey:(NSString *)storageKey param:(NSDictionary *)param
60 | {
61 | NSArray * x = [self.storageSync fetchStorageSyncWithKey:storageKey param:param];
62 | NSError * error = nil;
63 | if (x) {
64 | NSArray * ret = [self transformerProxyOfResponse:x error:&error];
65 | [self resetModels:ret];
66 | }
67 | else {
68 | error = [NSError errorWithDomain:NSStringFromClass([self class]) code:404 userInfo:nil];
69 | }
70 |
71 |
72 | @weakify(self);
73 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
74 | @strongify(self);
75 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
76 | if (!error) {
77 | [subscriber sendNext:self];
78 | [subscriber sendCompleted];
79 | }
80 | else {
81 | [subscriber sendError:error];
82 | }
83 | });
84 |
85 | return nil;
86 | }];
87 | }
88 |
89 | - (nonnull RACSignal *) rac_saveStorageWithKey:(NSString *)storageKey param:(NSDictionary *)param
90 | {
91 | [self.storageSync saveStorageSyncWithKey:storageKey withObject:[self transformerProxyOfModels:[self.models copy]] param:param];
92 | @weakify(self);
93 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
94 | @strongify(self);
95 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
96 | [subscriber sendNext:self];
97 | [subscriber sendCompleted];
98 | });
99 |
100 | return nil;
101 | }];
102 | }
103 |
104 | - (nonnull RACSignal *) rac_destroyStorageWithKey:(NSString *)storageKey param:(NSDictionary *)param
105 | {
106 | [self.storageSync destroyStorageSyncWithKey:storageKey param:param];
107 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
108 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
109 | [subscriber sendNext:nil];
110 | [subscriber sendCompleted];
111 | });
112 |
113 | return nil;
114 | }];
115 | }
116 |
117 | #pragma mark - db
118 | - (nonnull RACSignal *) rac_fetchDBAll
119 | {
120 | NSError * error = nil;
121 | return [self _createRACSingalWithNext:[self fetchDBSyncAllWithError:&error] error:error];
122 | }
123 |
124 | - (nonnull RACSignal *) rac_fetchDBAllSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...
125 | {
126 | NSError * error = nil;
127 | va_list args;
128 | va_start(args, columnName);
129 |
130 | NSArray * columnNames = [self arrayWithArgs:args firstArgument:columnName];
131 |
132 | va_end(args);
133 |
134 | columnNames = [self arrayOfMappedArgsWithOriginArray:columnNames];
135 |
136 | return [self _createRACSingalWithNext:[self fetchDBSyncAllWithError:&error soryBy:sortBy orderByColumnNames:columnNames] error:error];
137 | }
138 |
139 | - (nonnull RACSignal *) rac_fetchDBMultipleWith:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )columnName, ...
140 | {
141 | NSError * error = nil;
142 | va_list args;
143 | va_start(args, columnName);
144 |
145 | NSArray * columnNames = [self arrayWithArgs:args firstArgument:columnName];
146 |
147 | va_end(args);
148 |
149 | columnNames = [self arrayOfMappedArgsWithOriginArray:columnNames];
150 |
151 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error start:start count:count soryBy:sortBy orderByColumnNames:columnNames] error:error];
152 | }
153 |
154 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMet:(nonnull NSString * )condition, ...
155 | {
156 | va_list args;
157 | va_start(args, condition);
158 |
159 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
160 |
161 | va_end(args);
162 |
163 | NSError * error = nil;
164 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error whereAllTheConditionsAreMetConditions:conditions] error:error];
165 | }
166 |
167 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...
168 | {
169 | va_list args;
170 | va_start(args, condition);
171 |
172 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
173 |
174 | va_end(args);
175 |
176 | NSError * error = nil;
177 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error whereAllTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditionsArray:conditions] error:error];
178 | }
179 |
180 | - (nonnull RACSignal *) rac_fetchDBMultipleWhereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...
181 | {
182 | va_list args;
183 | va_start(args, condition);
184 |
185 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
186 |
187 | va_end(args);
188 |
189 | NSError * error = nil;
190 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error whereAllTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditionsArray:conditions] error:error];
191 | }
192 |
193 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMet:(nonnull NSString * )condition, ...
194 | {
195 | va_list args;
196 | va_start(args, condition);
197 |
198 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
199 |
200 | va_end(args);
201 |
202 | NSError * error = nil;
203 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error wherePartOfTheConditionsAreMetConditionsArray:conditions] error:error];
204 | }
205 |
206 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSString * )condition, ...
207 | {
208 | va_list args;
209 | va_start(args, condition);
210 |
211 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
212 |
213 | va_end(args);
214 |
215 | NSError * error = nil;
216 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error wherePartOfTheConditionsAreMetWithSoryBy:sortBy orderBy:orderBy conditionsArray:conditions] error:error];
217 | }
218 |
219 | - (nonnull RACSignal *) rac_fetchDBMultipleWherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSString * )condition, ...
220 | {
221 | va_list args;
222 | va_start(args, condition);
223 |
224 | NSArray * conditions = [self arrayWithArgs:args firstArgument:condition];
225 |
226 | va_end(args);
227 |
228 | NSError * error = nil;
229 | return [self _createRACSingalWithNext:[self fetchDBSyncMultipleWithError:&error wherePartOfTheConditionsAreMetWithStart:start count:count soryBy:sortBy orderBy:orderBy conditionsArray:conditions] error:error];
230 | }
231 |
232 | /* RACSignal return BOOL **/
233 | - (nonnull RACSignal *) rac_destroyDBAll
234 | {
235 | NSError * error = nil;
236 | return [self _createRACSingalWithNext:@([self destroyDBSyncAllWithError:&error]) error:error];
237 | }
238 |
239 | - (nonnull RACSignal *) _createRACSingalWithNext:(id) ret error:(nullable NSError *) error
240 | {
241 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
242 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
243 | if (error) {
244 | [subscriber sendError:error];
245 | return;
246 | }
247 | [subscriber sendNext:ret];
248 | [subscriber sendCompleted];
249 | });
250 | return nil;
251 | }];
252 | }
253 | @end
254 |
--------------------------------------------------------------------------------
/Pod/Classes/RACSupport/YTXRestfulModel+RACSupport.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModel+RACSupport.h
3 | // Pods
4 | //
5 | // Created by Chuan on 4/11/16.
6 | //
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 |
13 | @interface YTXRestfulModel (RACSupport)
14 |
15 | #pragma mark - remote
16 | /** :id/comment 这种形式的时候使用GET; modelClass is MTLModel*/
17 | - (nonnull RACSignal *) rac_fetchRemoteForeignWithName:(nonnull NSString *)name modelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param;
18 | /** GET */
19 | - (nonnull RACSignal *) rac_fetchRemote:(nullable NSDictionary *)param;
20 | /** POST / PUT */
21 | - (nonnull RACSignal *) rac_saveRemote:(nullable NSDictionary *)param;
22 | /** DELETE */
23 | - (nonnull RACSignal *) rac_destroyRemote:(nullable NSDictionary *)param;
24 |
25 | #pragma mark - storage
26 |
27 | - (nonnull RACSignal *) rac_fetchStorage:(nullable NSDictionary *)param;
28 |
29 | - (nonnull RACSignal *) rac_saveStorage:(nullable NSDictionary *)param;
30 | /** DELETE */
31 | - (nonnull RACSignal *) rac_destroyStorage:(nullable NSDictionary *)param;
32 |
33 | - (nonnull RACSignal *) rac_fetchStorageWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *)param;
34 |
35 | - (nonnull RACSignal *) rac_saveStorageWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *)param;
36 | /** DELETE */
37 | - (nonnull RACSignal *) rac_destroyStorageWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *)param;
38 |
39 | #pragma mark - db
40 |
41 | /** GET */
42 | - (nonnull RACSignal *) rac_fetchDB:(nullable NSDictionary *)param;
43 | /**
44 | * POST / PUT
45 | * 数据库不存在时创建,否则更新
46 | * 更新必须带主键
47 | */
48 | - (nonnull RACSignal *) rac_saveDB:(nullable NSDictionary *)param;
49 | /** DELETE */
50 | - (nonnull RACSignal *) rac_destroyDB:(nullable NSDictionary *)param;
51 | /** GET Foreign Models with primary key */
52 | - (nonnull RACSignal *) rac_fetchDBForeignWithModelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param;
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/Pod/Classes/RACSupport/YTXRestfulModel+RACSupport.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModel+RACSupport.m
3 | // Pods
4 | //
5 | // Created by Chuan on 4/11/16.
6 | //
7 | //
8 |
9 | #import "YTXRestfulModel+RACSupport.h"
10 |
11 | @implementation YTXRestfulModel (RACSupport)
12 |
13 | # pragma mark - remote
14 |
15 | - (nonnull RACSignal *) rac_fetchRemoteForeignWithName:(nonnull NSString *)name modelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param;
16 | {
17 | NSAssert([modelClass isSubclassOfClass: [MTLModel class] ], @"希望传入的class是MTLModel的子类,这样才能使用mantle转换");
18 | RACSubject * subject = [RACSubject subject];
19 | [self fetchRemoteForeignWithName:name modelClass:modelClass param:param success:^(id _Nullable response) {
20 | [subject sendNext:response];
21 | [subject sendCompleted];
22 | } failed:^(NSError * _Nullable error) {
23 | [subject sendError:error];
24 | }];
25 | return subject;
26 | }
27 |
28 | - (nonnull RACSignal *) rac_fetchRemote:(nullable NSDictionary *)param
29 | {
30 | RACSubject * subject = [RACSubject subject];
31 | [self fetchRemote:param success:^(id _Nullable response) {
32 | [subject sendNext:response];
33 | [subject sendCompleted];
34 | } failed:^(NSError * _Nullable error) {
35 | [subject sendError:error];
36 | }];
37 | return subject;
38 | }
39 |
40 | - (nonnull RACSignal *) rac_saveRemote:(nullable NSDictionary *)param
41 | {
42 | RACSubject * subject = [RACSubject subject];
43 | [self saveRemote:param success:^(id _Nullable response) {
44 | [subject sendNext:response];
45 | [subject sendCompleted];
46 | } failed:^(NSError * _Nullable error) {
47 | [subject sendError:error];
48 | }];
49 | return subject;
50 | }
51 |
52 | - (nonnull RACSignal *) rac_destroyRemote:(nullable NSDictionary *)param
53 | {
54 | RACSubject * subject = [RACSubject subject];
55 | [self destroyRemote:param success:^(id _Nullable response) {
56 | [subject sendNext:response];
57 | [subject sendCompleted];
58 | } failed:^(NSError * _Nullable error) {
59 | [subject sendError:error];
60 | }];
61 | return subject;
62 | }
63 |
64 | # pragma mark - storage
65 |
66 | - (nonnull RACSignal *) rac_fetchStorage:(nullable NSDictionary *)param
67 | {
68 | return [self rac_fetchStorageWithKey:[self storageKeyWithParam:param] param:param];
69 | }
70 |
71 | - (nonnull RACSignal *) rac_saveStorage:(nullable NSDictionary *)param
72 | {
73 | return [self rac_saveStorageWithKey:[self storageKeyWithParam:param] param:param];
74 | }
75 |
76 | /** DELETE */
77 | - (nonnull RACSignal *) rac_destroyStorage:(nullable NSDictionary *)param
78 | {
79 | return [self rac_destroyStorageWithKey:[self storageKeyWithParam:param] param:param];
80 | }
81 |
82 | - (nonnull RACSignal *) rac_fetchStorageWithKey:(NSString *)storage param:(NSDictionary *)param
83 | {
84 | NSDictionary * dict = [self.storageSync fetchStorageSyncWithKey:storage param:param];
85 | NSError * error = nil;
86 | if (dict) {
87 | [self transformerProxyOfResponse:dict error:&error];
88 | }
89 | else {
90 | error = [NSError errorWithDomain:NSStringFromClass([self class]) code:404 userInfo:nil];
91 | }
92 | @weakify(self);
93 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
94 | @strongify(self);
95 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
96 | if (!error) {
97 | [subscriber sendNext:self];
98 | [subscriber sendCompleted];
99 | }
100 | else {
101 | [subscriber sendError:error];
102 | }
103 | });
104 |
105 | return nil;
106 | }];
107 | }
108 |
109 | - (nonnull RACSignal *) rac_saveStorageWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *)param
110 | {
111 | id object = [self mergeSelfAndParameters:param];
112 | [self.storageSync saveStorageSyncWithKey:storage withObject:object param:param];
113 | @weakify(self);
114 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
115 | @strongify(self);
116 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
117 | [subscriber sendNext:self];
118 | [subscriber sendCompleted];
119 | });
120 |
121 | return nil;
122 | }];
123 | }
124 |
125 | - (nonnull RACSignal *) rac_destroyStorageWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *)param
126 | {
127 | [self.storageSync destroyStorageSyncWithKey:storage param:param];
128 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
129 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
130 | [subscriber sendNext:nil];
131 | [subscriber sendCompleted];
132 | });
133 |
134 | return nil;
135 | }];
136 | }
137 |
138 | #pragma mark - db
139 |
140 | /** GET */
141 | - (nonnull RACSignal *) rac_fetchDB:(nullable NSDictionary *)param
142 | {
143 | NSError * error = nil;
144 | return [self _createRACSingalWithNext:[self fetchDBSync:param error:&error] error:error];
145 | }
146 |
147 | /**
148 | * POST / PUT
149 | * 数据库不存在时创建,否则更新
150 | * 更新必须带主键
151 | */
152 | - (nonnull RACSignal *) rac_saveDB:(nullable NSDictionary *)param
153 | {
154 | NSError * error = nil;
155 | return [self _createRACSingalWithNext:[self saveDBSync:param error:&error] error:error];
156 | }
157 |
158 | /** DELETE */
159 | - (nonnull RACSignal *) rac_destroyDB:(nullable NSDictionary *)param
160 | {
161 | NSError * error = nil;
162 | return [self _createRACSingalWithNext:@([self destroyDBSync:param error:&error]) error:error];
163 | }
164 |
165 | /** GET Foreign Models with primary key */
166 | - (nonnull RACSignal *) rac_fetchDBForeignWithModelClass:(nonnull Class)modelClass param:(nullable NSDictionary *)param
167 | {
168 | NSError * error;
169 | NSArray * ret = [self fetchDBForeignSyncWithModelClass:modelClass error:&error param:param];
170 | return [self _createRACSingalWithNext:ret error:error];
171 | }
172 |
173 |
174 | - (nonnull RACSignal *) _createRACSingalWithNext:(id) ret error:(nullable NSError *) error
175 | {
176 | return [RACSignal createSignal:^RACDisposable *(id subscriber) {
177 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
178 | if (error) {
179 | [subscriber sendError:error];
180 | return;
181 | }
182 | [subscriber sendNext:ret];
183 | [subscriber sendCompleted];
184 | });
185 | return nil;
186 | }];
187 | }
188 |
189 | @end
190 |
--------------------------------------------------------------------------------
/Pod/Classes/RACSupport/YTXRestfulModelRACSupport.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelRACSupport.h
3 | // Pods
4 | //
5 | // Created by Chuan on 4/11/16.
6 | //
7 | //
8 |
9 | #ifndef YTXRestfulModelRACSupport_h
10 | #define YTXRestfulModelRACSupport_h
11 |
12 | #import
13 | #import
14 |
15 | #endif /* YTXRestfulModelRACSupport_h */
16 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/AFNetworkingRemoteSync/AFNetworkingRemoteSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // AFNetworkingRemoteSync.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/3/4.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulModelRemoteProtocol.h"
10 |
11 | #import
12 |
13 | @class AFHTTPSessionManager;
14 |
15 | @interface AFNetworkingRemoteSync : NSObject
16 |
17 | @property (nonnull, nonatomic, strong, readonly) AFHTTPSessionManager * requestSessionManager;
18 |
19 | /** 超时时间 默认60 */
20 | @property (nonatomic, assign) NSTimeInterval timeoutInterval;
21 |
22 | @property (nonnull, nonatomic, strong) NSURL * url;
23 |
24 | /** 设置网络请求的地址,通过Block形式,每次访问都会重新执行,以处理shared中URL会变的情况。同时使用URL和URLBlock会优先使用Block */
25 | @property (nullable, nonatomic, strong) NSURL * _Nonnull (^urlHookBlock)(void);
26 |
27 | @property (nonnull, nonatomic, copy, readonly) NSString * primaryKey;
28 |
29 | + (nonnull instancetype) syncWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey;
30 |
31 | + (nonnull instancetype) syncWithPrimaryKey:(nonnull NSString *) primaryKey;
32 |
33 | + (nullable YTXRestfulModelRemoteHookExtraParamBlock) hookExtraParamBlock;
34 |
35 | + (void) setHookExtraParamBlock:(nullable YTXRestfulModelRemoteHookExtraParamBlock) hookExtraParamBlock;
36 |
37 | + (nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock;
38 |
39 | + (void) setHookRequestBlock:(nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock;
40 |
41 | - (nonnull instancetype) initWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey;
42 |
43 | - (nonnull instancetype) initWithPrimaryKey:(nonnull NSString *) primaryKey;
44 |
45 | /** GET :id/commont */
46 | - (void) fetchRemoteForeignWithName:(nonnull NSString *)name param:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
47 |
48 | /** GET */
49 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
50 |
51 | /** POST */
52 | - (void) createRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
53 |
54 | /** put */
55 | - (void) updateRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
56 |
57 | /** DELETE */
58 | - (void) destroyRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/AFNetworkingRemoteSync/AFNetworkingRemoteSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // AFNetworkingRemoteSync.m
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/3/4.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "AFNetworkingRemoteSync.h"
10 |
11 | #import
12 |
13 | static YTXRestfulModelRemoteHookExtraParamBlock __hookExtraParamBlock;
14 |
15 | static YTXRestfulModelRemoteHookRequestBlock __hookRequestBlock;
16 |
17 | static NSString *const RestFulDomain = @"AFNetworkingRemoteSync"; //error domain
18 |
19 | @interface AFNetworkingRemoteSync()
20 |
21 | @property (nonnull, nonatomic, strong) AFHTTPSessionManager * requestSessionManager;
22 |
23 | @end
24 |
25 | @implementation AFNetworkingRemoteSync
26 |
27 | - (NSURL *)url {
28 | if (self.urlHookBlock) {
29 | return self.urlHookBlock();
30 | }
31 | return _url;
32 | }
33 |
34 | + (nonnull instancetype) syncWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey
35 | {
36 | return [[self alloc] initWithURL:URL primaryKey:primaryKey];
37 | }
38 |
39 | + (nonnull instancetype) syncWithPrimaryKey:(nonnull NSString *) primaryKey
40 | {
41 | return [[self alloc] initWithPrimaryKey:primaryKey];
42 | }
43 |
44 | + (nullable YTXRestfulModelRemoteHookExtraParamBlock) hookExtraParamBlock
45 | {
46 | return __hookExtraParamBlock;
47 | }
48 |
49 | + (void) setHookExtraParamBlock:(nullable YTXRestfulModelRemoteHookExtraParamBlock)hookExtraParamBlock
50 | {
51 | __hookExtraParamBlock = hookExtraParamBlock;
52 | }
53 |
54 | + (nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock
55 | {
56 | return __hookRequestBlock;
57 | }
58 |
59 | + (void) setHookRequestBlock:(nullable YTXRestfulModelRemoteHookRequestBlock) hookRequestBlock
60 | {
61 | __hookRequestBlock = hookRequestBlock;
62 | }
63 |
64 | - (nonnull instancetype) initWithURL:(nonnull NSURL *)URL primaryKey:(nonnull NSString *) primaryKey
65 | {
66 | if (self = [super init]) {
67 | _url = URL;
68 | _primaryKey = primaryKey;
69 | _timeoutInterval = 60;
70 | self.requestSessionManager.requestSerializer.timeoutInterval = _timeoutInterval;
71 | }
72 | return self;
73 | }
74 |
75 | - (nonnull instancetype) initWithPrimaryKey:(nonnull NSString *) primaryKey
76 | {
77 | if (self = [super init]) {
78 | _primaryKey = primaryKey;
79 | _timeoutInterval = 60;
80 | self.requestSessionManager.requestSerializer.timeoutInterval = _timeoutInterval;
81 | }
82 | return self;
83 | }
84 |
85 | /** GET :id/comment */
86 | - (void) fetchRemoteForeignWithName:(nonnull NSString *)name param:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
87 | {
88 | NSURL * url = [[self restfulURLWithParam:param] URLByAppendingPathComponent:name];
89 | NSMutableDictionary * newParam = [[self restfulParamWithParam:param] mutableCopy];
90 |
91 | if (AFNetworkingRemoteSync.hookRequestBlock) {
92 | AFNetworkingRemoteSync.hookRequestBlock(self, @"GET", &url, &newParam);
93 | }
94 |
95 | [self.requestSessionManager GET:[url absoluteString] parameters:newParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
96 | success(responseObject);
97 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
98 | failed(error);
99 | }];
100 | }
101 |
102 | /** GET */
103 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
104 | {
105 | NSURL * url = [self restfulURLWithParam:param];
106 | NSMutableDictionary * newParam = [[self restfulParamWithParam:param] mutableCopy];
107 |
108 | if (AFNetworkingRemoteSync.hookRequestBlock) {
109 | AFNetworkingRemoteSync.hookRequestBlock(self, @"GET", &url, &newParam);
110 | }
111 |
112 | [self.requestSessionManager GET:[url absoluteString] parameters:newParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
113 | success(responseObject);
114 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
115 | failed(error);
116 | }];
117 | }
118 |
119 | /** POST */
120 | - (void) createRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
121 | {
122 | NSURL * url = [self restfulURLWithParam:param];
123 | NSMutableDictionary * newParam = [[self restfulParamWithParam:param] mutableCopy];
124 |
125 | if (AFNetworkingRemoteSync.hookRequestBlock) {
126 | AFNetworkingRemoteSync.hookRequestBlock(self, @"POST", &url, &newParam);
127 | }
128 |
129 | [self.requestSessionManager POST:[url absoluteString] parameters:newParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
130 | success(responseObject);
131 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
132 | failed(error);
133 | }];
134 | }
135 |
136 | /** PUT */
137 | - (void) updateRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
138 | {
139 | NSURL * url = [self restfulURLWithParam:param];
140 | NSMutableDictionary * newParam = [[self restfulParamWithParam:param] mutableCopy];
141 |
142 | if (AFNetworkingRemoteSync.hookRequestBlock) {
143 | AFNetworkingRemoteSync.hookRequestBlock(self, @"PUT", &url, &newParam);
144 | }
145 |
146 | [self.requestSessionManager PUT:[url absoluteString] parameters:newParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
147 | success(responseObject);
148 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
149 | failed(error);
150 | }];
151 | }
152 |
153 | /** DELETE */
154 | - (void) destroyRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed
155 | {
156 | NSURL * url = [self restfulURLWithParam:param];
157 | NSMutableDictionary * newParam = [[self restfulParamWithParam:param] mutableCopy];
158 |
159 | if (AFNetworkingRemoteSync.hookRequestBlock) {
160 | AFNetworkingRemoteSync.hookRequestBlock(self, @"DELETE", &url, &newParam);
161 | }
162 |
163 | [self.requestSessionManager DELETE:[url absoluteString] parameters:newParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
164 | success(responseObject);
165 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
166 | failed(error);
167 | }];
168 | }
169 |
170 | #pragma mark - function
171 |
172 | - (NSURL *) restfulURLWithParam:(NSDictionary *)param
173 | {
174 | NSURL *url = [self.url copy];
175 | id primaryKey = param[self.primaryKey];
176 | if (primaryKey) {
177 | url = [url URLByAppendingPathComponent:[primaryKey description]];
178 | }
179 | return url;
180 | }
181 |
182 | - (NSDictionary *) restfulParamWithParam:(NSDictionary *)param
183 | {
184 | NSMutableDictionary *retParam = [NSMutableDictionary dictionaryWithDictionary:AFNetworkingRemoteSync.hookExtraParamBlock != nil ? AFNetworkingRemoteSync.hookExtraParamBlock() : @{}];
185 |
186 | for (NSString * key in param) {
187 | [retParam setObject:param[key] forKey:key];
188 | }
189 |
190 | if (self.primaryKey) {
191 | [retParam removeObjectForKey:self.primaryKey];
192 | }
193 | return retParam;
194 | }
195 |
196 | - (nonnull AFHTTPSessionManager *) requestSessionManager
197 | {
198 | if (!_requestSessionManager) {
199 | _requestSessionManager = [AFHTTPSessionManager manager];
200 | }
201 | return _requestSessionManager;
202 | }
203 |
204 | - (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval
205 | {
206 | _timeoutInterval = timeoutInterval;
207 | self.requestSessionManager.requestSerializer.timeoutInterval = _timeoutInterval;
208 | }
209 |
210 | @end
211 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSArray+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSArray+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSArray (YTXRestfulModelFMDBSync)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSArray+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSArray+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSArray+YTXRestfulModelFMDBSync.h"
10 | #import "NSObject+YTXRestfulModelFMDBSync.h"
11 |
12 | @implementation NSArray (YTXRestfulModelFMDBSync)
13 |
14 | - (nullable NSString *) sqliteValue
15 | {
16 | NSError *error;
17 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
18 | options:kNilOptions
19 | error:&error];
20 | NSString *jsonStr = [[NSString alloc] initWithData:jsonData
21 | encoding:NSUTF8StringEncoding];
22 | if (error) {
23 | return nil;
24 | }
25 |
26 | return [jsonStr sqliteValue];
27 | }
28 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
29 | {
30 | NSError *error;
31 | NSData *objectData = [sqlstring dataUsingEncoding:NSUTF8StringEncoding];
32 | NSArray *arr = [NSJSONSerialization JSONObjectWithData:objectData
33 | options:NSJSONReadingMutableContainers
34 | error:&error];
35 | if (error) {
36 | return nil;
37 | }
38 |
39 | return arr;
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSDate+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSDate (YTXRestfulModelFMDBSync)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSDate+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSDate+YTXRestfulModelFMDBSync.h"
10 |
11 | @implementation NSDate (YTXRestfulModelFMDBSync)
12 |
13 | - (nullable NSString *) sqliteValue
14 | {
15 | return [NSString stringWithFormat:@"%f", [self timeIntervalSince1970]];
16 | }
17 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
18 | {
19 | return @([sqlstring doubleValue]);
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSDictionary+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSDictionary (YTXRestfulModelFMDBSync)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSDictionary+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSDictionary+YTXRestfulModelFMDBSync.h"
10 | #import "NSObject+YTXRestfulModelFMDBSync.h"
11 |
12 | @implementation NSDictionary (YTXRestfulModelFMDBSync)
13 |
14 | - (nullable NSString *) sqliteValue
15 | {
16 | NSError *error;
17 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
18 | options:kNilOptions
19 | error:&error];
20 | NSString *jsonStr = [[NSString alloc] initWithData:jsonData
21 | encoding:NSUTF8StringEncoding];
22 |
23 | if (error) {
24 | return nil;
25 | }
26 |
27 | return [jsonStr sqliteValue];;
28 | }
29 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
30 | {
31 | NSError *error;
32 | NSData *objectData = [sqlstring dataUsingEncoding:NSUTF8StringEncoding];
33 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:objectData
34 | options:NSJSONReadingMutableContainers
35 | error:&error];
36 | if (error) {
37 | return nil;
38 | }
39 |
40 | return dict;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSNumber+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSNumber+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSNumber (YTXRestfulModelFMDBSync)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSNumber+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSNumber+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSNumber+YTXRestfulModelFMDBSync.h"
10 |
11 | @implementation NSNumber (YTXRestfulModelFMDBSync)
12 |
13 | - (nullable NSString *) sqliteValue
14 | {
15 | return [self stringValue];
16 | }
17 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
18 | {
19 | NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
20 | return [fmt numberFromString:sqlstring];
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSObject+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSObject (YTXRestfulModelFMDBSync)
12 |
13 | - (nullable NSString *) sqliteValue;
14 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSObject+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSObject+YTXRestfulModelFMDBSync.h"
10 |
11 | @implementation NSObject (YTXRestfulModelFMDBSync)
12 |
13 | - (nullable NSString *) sqliteValue
14 | {
15 | return nil;
16 | }
17 |
18 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
19 | {
20 | return nil;
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSString+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (YTXRestfulModelFMDBSync)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSString+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSString+YTXRestfulModelFMDBSync.h"
10 |
11 | @implementation NSString (YTXRestfulModelFMDBSync)
12 |
13 | - (nullable NSString *) sqliteValue
14 | {
15 | return [NSString stringWithFormat:@"'%@'", [self stringByReplacingOccurrencesOfString:@"'" withString:@"''"]];
16 | }
17 | + (nullable NSString *) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
18 | {
19 | return sqlstring;
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSValue+YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSValue+YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSValue (YTXRestfulModelFMDBSync)
12 |
13 | + (nonnull NSString*) formateObjectType:(const char* _Nonnull )objcType;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/Category/NSValue+YTXRestfulModelFMDBSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSValue+YTXRestfulModelFMDBSync.m
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/24.
6 | //
7 | //
8 |
9 | #import "NSValue+YTXRestfulModelFMDBSync.h"
10 | #import "NSObject+YTXRestfulModelFMDBSync.h"
11 | #import
12 |
13 | @implementation NSValue (YTXRestfulModelFMDBSync)
14 |
15 | + (nonnull NSString*) formateObjectType:(const char* _Nonnull )objcType
16 | {
17 | if (!objcType || !strlen(objcType)) return nil;
18 | NSString* type = [NSString stringWithCString:objcType encoding:NSUTF8StringEncoding];
19 |
20 | switch (objcType[0]) {
21 | case '@':
22 | type = [type substringWithRange:NSMakeRange(2, strlen(objcType)-3)];
23 | break;
24 | case '{':
25 | type = [type substringWithRange:NSMakeRange(1, strchr(objcType, '=')-objcType-1)];
26 | break;
27 | default:
28 | break;
29 | }
30 | return type;
31 | }
32 |
33 | - (nullable NSString *) sqliteValue
34 | {
35 | NSString* type = [NSValue formateObjectType:[self objCType]];
36 |
37 | if ([type isEqualToString:@"CGPoint"]) {
38 | return [NSStringFromCGPoint([self CGPointValue]) sqliteValue];
39 | } else if ([type isEqualToString:@"CGSize"]) {
40 | return [NSStringFromCGSize([self CGSizeValue]) sqliteValue];
41 | } else if ([type isEqualToString:@"CGRect"]) {
42 | return [NSStringFromCGRect([self CGRectValue]) sqliteValue];
43 | } else if ([type isEqualToString:@"CGVector"]) {
44 | return [NSStringFromCGVector([self CGVectorValue]) sqliteValue];
45 | } else if ([type isEqualToString:@"CGAffineTransform"]) {
46 | return [NSStringFromCGAffineTransform([self CGAffineTransformValue]) sqliteValue];
47 | } else if ([type isEqualToString:@"UIEdgeInsets"]) {
48 | return [NSStringFromUIEdgeInsets([self UIEdgeInsetsValue]) sqliteValue];
49 | } else if ([type isEqualToString:@"UIOffset"]) {
50 | return [NSStringFromUIOffset([self UIOffsetValue]) sqliteValue];
51 | } else if ([type isEqualToString:@"NSRange"]) {
52 | return [NSStringFromRange([self rangeValue]) sqliteValue];
53 | }
54 |
55 | return nil;
56 | }
57 | + (nullable id) objectForSqliteString:(nonnull NSString *) sqlstring objectType:(nonnull NSString *) type
58 | {
59 | if ([type isEqualToString:@"CGPoint"]) {
60 | return [NSValue valueWithCGPoint:CGPointFromString(sqlstring)];
61 | } else if ([type isEqualToString:@"CGSize"]) {
62 | return [NSValue valueWithCGSize:CGSizeFromString(sqlstring)];
63 | } else if ([type isEqualToString:@"CGRect"]) {
64 | return [NSValue valueWithCGRect:CGRectFromString(sqlstring)];
65 | } else if ([type isEqualToString:@"CGVector"]) {
66 | return [NSValue valueWithCGVector:CGVectorFromString(sqlstring)];
67 | } else if ([type isEqualToString:@"CGAffineTransform"]) {
68 | return [NSValue valueWithCGAffineTransform:CGAffineTransformFromString(sqlstring)];
69 | } else if ([type isEqualToString:@"UIEdgeInsets"]) {
70 | return [NSValue valueWithUIEdgeInsets:UIEdgeInsetsFromString(sqlstring)];
71 | } else if ([type isEqualToString:@"UIOffset"]) {
72 | return [NSValue valueWithUIOffset:UIOffsetFromString(sqlstring)];
73 | } else if ([type isEqualToString:@"NSRange"]) {
74 | return [NSValue valueWithRange:NSRangeFromString(sqlstring)];
75 | }
76 | return nil;
77 | }
78 |
79 | @end
80 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/FMDBSync/YTXRestfulModelFMDBSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelFMDBSync.h
3 | // Pods
4 | //
5 | // Created by CaoJun on 16/2/22.
6 | //
7 | //
8 |
9 | #import "YTXRestfulModelDBProtocol.h"
10 |
11 | #import
12 |
13 | @class FMDatabaseQueue;
14 | @class FMDatabase;
15 |
16 | @interface YTXRestfulModelFMDBSync : NSObject
17 |
18 | @property (nonatomic, strong, readonly, nonnull) FMDatabaseQueue * fmdbQueue;
19 |
20 | @property (nonatomic, assign, readonly, nonnull) Class modelClass;
21 |
22 | @property (nonnull, nonatomic, copy, readonly) NSString * primaryKey;
23 |
24 |
25 | #pragma mark db operation
26 |
27 | + (nonnull instancetype) syncWithModelOfClass:(nonnull Class) modelClass primaryKey:(nonnull NSString *) key;
28 |
29 | + (nonnull NSString *) path;
30 |
31 | - (nonnull NSString *) tableName;
32 |
33 | - (nonnull instancetype) initWithModelOfClass:(nonnull Class) modelClass primaryKey:(nonnull NSString *) key;
34 | - (nonnull NSError *) createTable;
35 |
36 | - (nonnull NSError *) dropTable;
37 |
38 | //操作将会保证在migration之后进行
39 |
40 | /** GET Model with primary key */
41 | - (nullable NSDictionary *) fetchOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
42 |
43 | /** POST / PUT Model with primary key */
44 | - (nullable NSDictionary *) saveOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
45 |
46 | /** DELETE Model with primary key */
47 | - (BOOL) destroyOneSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
48 |
49 | /** GET */
50 | - (nullable NSDictionary *) fetchTopOneSyncWithError:(NSError * _Nullable * _Nullable) error;
51 |
52 | /** GET */
53 | - (nullable NSDictionary *) fetchLatestOneSyncWithError:(NSError * _Nullable * _Nullable) error;
54 |
55 | /** DELETE All Model with primary key */
56 | - (BOOL) destroyAllSyncWithError:(NSError * _Nullable * _Nullable) error;
57 |
58 | /** ORDER BY primaryKey ASC*/
59 | - (nonnull NSArray *) fetchAllSyncWithError:(NSError * _Nullable * _Nullable) error;
60 |
61 | /** GET Foreign Models with primary key */
62 | - (nonnull NSArray *) fetchForeignSyncWithModelClass:(nonnull Class)modelClass primaryKeyValue:(nonnull id) value error:(NSError * _Nullable * _Nullable) error param:(nullable NSDictionary *)param;
63 |
64 | - (nonnull NSArray *) fetchAllSyncWithError:(NSError * _Nullable * _Nullable)error soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSArray * )columnNames;
65 |
66 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error start:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSArray * )columnNames;
67 |
68 | /**
69 | * ORDER BY primaryKey ASC
70 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
71 | */
72 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMet:(nonnull NSArray * )conditions;
73 |
74 | /**
75 | * ORDER BY primaryKey ASC
76 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
77 | */
78 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSArray * )conditions;
79 |
80 | /**
81 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' AND old >= 10
82 | */
83 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error whereAllTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSArray * )conditions;
84 |
85 | /**
86 | * ORDER BY primaryKey ASC
87 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
88 | */
89 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMet:(nonnull NSArray * )conditions;
90 |
91 | /**
92 | * ORDER BY primaryKey ASC
93 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
94 | */
95 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithSoryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * )orderBy conditions:(nonnull NSArray * )conditions;
96 |
97 | /**
98 | * condition: @"name = 'CJ'", @"old >= 10" => name = 'CJ' OR old >= 10
99 | */
100 | - (nonnull NSArray *) fetchMultipleSyncWithError:(NSError * _Nullable * _Nullable)error wherePartOfTheConditionsAreMetWithStart:(NSUInteger) start count:(NSUInteger) count soryBy:(YTXRestfulModelDBSortBy)sortBy orderBy:(nonnull NSString * ) orderBy conditions:(nonnull NSArray * )conditions;
101 |
102 | //Migration
103 |
104 | /** 数字越大越后面执行*/
105 |
106 | @property (nonatomic, strong, readonly, nonnull) NSMutableArray * migrationBlocks;
107 |
108 | /** 大于currentMigrationVersion将会依次执行*/
109 | - (void) migrate:(nonnull YTXRestfulModelDBMigrationEntity *) entity;
110 |
111 | - (BOOL) createColumnWithDB:(nonnull id)db structSync:(nonnull YTXRestfulModelDBSerializingModel *)sstruct error:(NSError * _Nullable * _Nullable)error;
112 |
113 | // Tools
114 | + (nonnull NSDictionary * > *) mapOfCTypeToSqliteType;
115 | + (nonnull NSArray *) arrayOfMappedArgsWithOriginArray:(nonnull NSArray *)originArray propertiesMap:(nonnull NSDictionary *)propertiesMap;
116 |
117 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key equal:(nonnull id) value;
118 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key greatThan:(nonnull id) value;
119 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key greatThanOrEqaul:(nonnull id) value;
120 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key lessThan:(nonnull id) value;
121 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key lessThanOrEqual:(nonnull id) value;
122 | + (nonnull NSString * ) sqliteStringWhere:(nonnull NSString *) key like:(nonnull id) value;
123 |
124 | @end
125 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/UserDefaultStorageSync/YTXRestfulModelUserDefaultStorageSync.h:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelUserDefaultStorageSync.h
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulModelStorageProtocol.h"
10 |
11 | #import
12 |
13 |
14 | @interface YTXRestfulModelUserDefaultStorageSync : NSObject
15 |
16 | @property (nullable, nonatomic, copy, readonly) NSString * userDefaultSuiteName;
17 |
18 | - (nonnull instancetype) initWithUserDefaultSuiteName:(nullable NSString *) suiteName;
19 |
20 | /** GET */
21 | - (nullable id) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
22 |
23 | /** POST / PUT */
24 | - (nullable id) saveStorageSyncWithKey:(nonnull NSString *)storage withObject:(nonnull id)object param:(nullable NSDictionary *) param;
25 |
26 | /** DELETE */
27 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Pod/Classes/Sync/UserDefaultStorageSync/YTXRestfulModelUserDefaultStorageSync.m:
--------------------------------------------------------------------------------
1 | //
2 | // YTXRestfulModelUserDefaultStorageSync.m
3 | // YTXRestfulModel
4 | //
5 | // Created by CaoJun on 16/1/25.
6 | // Copyright © 2016年 Elephants Financial Service. All rights reserved.
7 | //
8 |
9 | #import "YTXRestfulModelUserDefaultStorageSync.h"
10 |
11 | #import
12 |
13 | @implementation YTXRestfulModelUserDefaultStorageSync
14 |
15 | - (nonnull instancetype) initWithUserDefaultSuiteName:(nullable NSString *) suiteName;
16 | {
17 | if (self = [super init]) {
18 | _userDefaultSuiteName = suiteName;
19 | }
20 | return self;
21 | }
22 |
23 | /** GET */
24 | - (nullable id) fetchStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
25 | {
26 | return [[[NSUserDefaults alloc] initWithSuiteName:self.userDefaultSuiteName] objectForKey:storage];
27 | }
28 |
29 | /** POST / PUT */
30 | - (nullable id) saveStorageSyncWithKey:(nonnull NSString *)storage withObject:(nonnull id)object param:(nullable NSDictionary *) param
31 | {
32 | [[[NSUserDefaults alloc] initWithSuiteName:self.userDefaultSuiteName] setObject:object forKey:storage];
33 | return object;
34 | }
35 |
36 | /** DELETE */
37 | - (void) destroyStorageSyncWithKey:(nonnull NSString *)storage param:(nullable NSDictionary *) param
38 | {
39 | [[[NSUserDefaults alloc] initWithSuiteName:self.userDefaultSuiteName] removeObjectForKey:storage];
40 | }
41 |
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # YTXRestfulModel [](https://travis-ci.org/baidao/YTXRestfulModel) [](http://cocoapods.org/pods/YTXRestfulModel) [](http://cocoapods.org/pods/YTXRestfulModel) [](http://cocoapods.org/pods/YTXRestfulModel)
2 | YTXRestfulModel makes it easy to fetch(GET), save(PUT/POST) or destroy(DELEGATE) data by database, remote or local storage.(YTXRestfulModel提供一种简单的方式从数据库,远程或本地存储去拉取,储存,销毁数据)
3 |
4 | 
5 |
6 | ## Dependency(依赖)
7 | - [FMDB ~>2.6](https://github.com/ccgus/fmdb)(FMDBSync)
8 | - [AFNetworking ~>2.6.3](https://github.com/AFNetworking/AFNetworking/tree/2.6.3) (AFNetworkingRemoteSync)
9 | - [Mantle ~>1.57.](https://github.com/Mantle/Mantle/tree/1.5.7)
10 | - Optional [ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa)FRP。
11 |
12 | Support IPv6
13 |
14 | ## Integration
15 |
16 | You shouldn't just use: pod "YTXRestfulModel". Since CocoaPods 0.36+ you should do something like:
17 |
18 | ```ruby
19 | pod 'YTXRestfulModel', :subspecs => ["RACSupport", "YTXRequestRemoteSync", "FMDBSync", "UserDefaultStorageSync"]
20 | ```
21 |
22 | ## Testing
23 | ```shell
24 | git clone https://github.com/baidao/YTXRestfulModel.git
25 | npm install -g json-server
26 | cd Example
27 | pod install
28 | cd Tests
29 | json-server db.json
30 | open YTXRestfulModel.xcworkspace
31 | ```
32 | Chose Target: YTXRestfulModel-Example
33 | Command+U to run Test
34 |
35 | ## More useage, please check(更多用法,请查看)[Tests](https://github.com/baidao/YTXRestfulModel/tree/github/Example/Tests)
36 |
37 | ## A Model Example(定义Model示例)
38 | ```objective-c
39 | @interface YTXTestModel : YTXRestfulModel
40 |
41 | @property (nonnull, nonatomic, strong) NSNumber *keyId;
42 | @property (nonnull, nonatomic, strong) NSNumber *userId;
43 | @property (nonnull, nonatomic, strong) NSString *title;
44 | @property (nonnull, nonatomic, strong) NSString *body;
45 |
46 | @end
47 | ```
48 | ```objective-c
49 | @implementation YTXTestModel
50 |
51 | //The dictionary returned by this method specifies how your model object's properties map to the keys in the JSON representation
52 | // Check Mantle
53 | + (NSDictionary *)JSONKeyPathsByPropertyKey
54 | {
55 | /** key 的值是 模型中的字段,value 的值是目标源上对应数据的名字。*/
56 | return @{@"keyId": @"id"};
57 | }
58 |
59 | + (NSString *)primaryKey
60 | {
61 | return @"keyId";
62 | }
63 |
64 | - (instancetype)init {
65 | if (self = [super init]) {
66 | //这种方式可以在每次使用url的时候都重新获取
67 | self.remoteSync.urlHookBlock = ^NSURL * _Nonnull{
68 | return [URLManager urlWithName:@"restful.posts"];
69 | };
70 | }
71 | return self;
72 | }
73 |
74 | // DB Migration(数据迁移)
75 | + (nullable NSNumber *) currentMigrationVersion
76 | {
77 | return @0;
78 | }
79 |
80 | // Default NO. If you wanna use dbsync, you should return YES;
81 | + (BOOL) autoCreateTable
82 | {
83 | return YES;
84 | }
85 |
86 | //Default YES. If auto alter table, it does not do migration.
87 | + (BOOL) autoAlterTable
88 | {
89 | return YES;
90 | }
91 |
92 | // Mantle Transformer
93 | // Implement this optional method to convert a property from a different type when deserializing from JSON
94 | + (MTLValueTransformer *)startSchoolDateJSONTransformer {
95 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSNumber *timestamp) {
96 | return [NSDate dateWithTimeIntervalSince1970: timestamp.longLongValue / 1000];
97 | } reverseBlock:^(NSDate *date) {
98 | return @((SInt64)(date.timeIntervalSince1970 * 1000));
99 | }];
100 | }
101 | + (MTLValueTransformer *) bodyJSONTransformer
102 | {
103 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString * body) {
104 | return body;
105 | } reverseBlock:^(NSString * body) {
106 | return body;
107 | }];
108 | }
109 |
110 | @end
111 | ```
112 |
113 | ## Fetch
114 | ```objective-c
115 | - (nullable instancetype) fetchStorageSync:(nullable NSDictionary *) param;
116 |
117 | - (void) fetchRemote:(nullable NSDictionary *)param success:(nonnull YTXRestfulModelRemoteSuccessBlock)success failed:(nonnull YTXRestfulModelRemoteFailedBlock)failed;
118 |
119 | - (nonnull instancetype) saveDBSync:(nullable NSDictionary *)param error:(NSError * _Nullable * _Nullable) error;
120 |
121 | ```
122 |
123 | ## Model transition Refrence(Model的转换参考)[Mantle](https://github.com/Mantle/Mantle/tree/1.5.7)
124 | 无论数据源来自Remote,Storage,DB都会经过MTLValueTransformer,如果你定义了该属性的Transformer。
125 | ```objective-c
126 | + (MTLValueTransformer *)birthdayJSONTransformer {
127 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSNumber *timestamp) {
128 | return [NSDate dateWithTimeIntervalSince1970: timestamp.longLongValue / 1000];
129 | } reverseBlock:^(NSDate *date) {
130 | return @((SInt64)(date.timeIntervalSince1970 * 1000));
131 | }];
132 | }
133 |
134 | + (MTLValueTransformer *)passwordJSONTransformer {
135 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *value) {
136 | return [self encryption:value];
137 | } reverseBlock:^(NSString *value) {
138 | return [self decryption:value];
139 | }];
140 | }
141 | ```
142 |
143 | ### Response pretreatment
144 | ```objective-c
145 | - (nonnull instancetype) transformerProxyOfResponse:(nonnull id) response error:(NSError * _Nullable * _Nullable) error
146 | {
147 | return [super transformerProxyOfResponse:response[@"properties"] error:error];
148 | }
149 |
150 | - (nonnull id) transformerProxyOfForeign:(nonnull Class)modelClass response:(nonnull id) response error:(NSError * _Nullable * _Nullable) error;
151 | {
152 | return [[super transformerProxyOfForeign:modelClass response:response[@"properties"] error:error];
153 | }
154 | ```
155 |
156 | ## RACSupport
157 | ```ruby
158 | pod "YTXRestfulModel", :path => "../", :subspecs => ["RACSupport", "AFNetworkingRemoteSync", "FMDBSync", "UserDefaultStorageSync"]
159 | ```
160 |
161 | ```objective-c
162 |
163 | /** GET */
164 | - (nonnull RACSignal *) rac_fetchStorage:(nullable NSDictionary *)param;
165 |
166 | /** GET */
167 | - (nonnull RACSignal *) rac_fetchRemote:(nullable NSDictionary *)param;
168 |
169 | /** POST / PUT */
170 | - (nonnull RACSignal *) rac_saveRemote:(nullable NSDictionary *)param;
171 |
172 | /** GET */
173 | - (nonnull RACSignal *) rac_fetchDB:(nullable NSDictionary *)param;
174 |
175 | ```
176 |
177 | ```objective-c
178 | #import
179 |
180 | YTXTestAFNetworkingRemoteCollection * collection = [YTXTestAFNetworkingRemoteCollection new];
181 | [[collection rac_fetchRemote:@{@"_start": @"1", @"_limit": @"2"}] subscribeNext:^(YTXTestAFNetworkingRemoteCollection *x) {
182 |
183 | } error:^(NSError *error) {
184 |
185 | }];
186 | ```
187 |
188 | ## Example:
189 | ```objective-c
190 | /**
191 | 远程请求:http://jsonplaceholder.typicode.com/posts/1
192 | 返回数据:
193 | {
194 | "userId": 1,
195 | "id": 1,
196 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
197 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
198 | }
199 | */
200 | /**
201 | keyId = @1,按照JSONKeyPathsByPropertyKey方法中的映射转成retDictionary @{@"id":@1};
202 | 由于param为空,所以保留参数{@"id":@"1"}不做修改,直接执行同步操作,同步目标源中 id = 1 的数据;
203 | */
204 | YTXTestModel * currentTestModel = [[YTXTestModel alloc] init];
205 | currentTestModel.keyId = @1;
206 | [[currentTestModel rac_fetchRemote:nil] subscribeNext:^(YTXTestModel *responseModel) {
207 |
208 | } error:^(NSError *error) {
209 |
210 | }];
211 |
212 | /**
213 | Model的属性会按照映射转成retDictionary @{@"title":@"ytx test", @"body":@"test content", @"userId":@1}
214 | param按照映射转成mapParam,@{@"id":@2};(param = @{@"id":@2} 时也会转成 @{@"id":@2})。
215 | mapParam的value会替换retDictionary 的value,所以执行同步的参数是@{@"title":@"ytx_test", @"body":@"test_content", @"userId":@1, @"id":@1}
216 | 由于retDictionary 中没有主键,所以不符合rest原则,最后发送的请求是: *******?title=ytx_test&body=test_content&userId=1&id=1
217 | */
218 |
219 | YTXTestModel * testModel = [[YTXTestModel alloc] init];
220 | testModel.title = @"ytx test";
221 | testModel.body = @"test content";
222 | testModel.userId = @1;
223 | [[testModel rac_saveRemote:@{@"keyId":@1}] subscribeNext:^(YTXTestModel *responseModel) {
224 |
225 | } error:^(NSError *error) {
226 |
227 | }];
228 |
229 | YTXTestModel * currentTestModel = [[YTXTestModel alloc] init];
230 | __block id ret;
231 | currentTestModel.keyId = @1;
232 |
233 | [[currentTestModel rac_fetchRemoteForeignWithName:@"comments" modelClass:[YTXTestCommentModel class] param:nil] subscribeNext:^(id x) {
234 | ret = x;
235 | } error:^(NSError *error) {
236 |
237 | }];
238 |
239 | YTXTestModel * dbTestModel = [[YTXTestModel alloc] init];
240 | dbTestModel.keyId = @1;
241 |
242 | [[dbTestModel rac_fetchDB:nil] subscribeNext:^(YTXTestModel *responseModel) {
243 |
244 | } error:^(NSError *error) {
245 |
246 | }];
247 |
248 | YTXTestModel * storageTestModel = [[YTXTestModel alloc] init];
249 | storageTestModel.keyId = @1;
250 |
251 | [[storageTestModel rac_fetchStorage:nil] subscribeNext:^(YTXTestModel *responseModel) {
252 |
253 | } error:^(NSError *error) {
254 |
255 | }];
256 | ```
257 |
258 | ## RACSupport
259 | ```objective-c
260 | #import
261 |
262 | @interface YTXXXXModel : YTXRestfulModel
263 |
264 | - (nonnull RACSignal *) rac_fetchFromRemoteAndStorage;
265 |
266 | @end
267 |
268 | @implementation YTXXXXXModel
269 |
270 | - (nonnull RACSignal *) rac_fetchFromRemoteAndStorage
271 | {
272 | RACSubject * subject = [RACSubject subject];
273 | [self fetchRemote:param success:^(id _Nullable response) {
274 | [subject sendNext:response];
275 | [subject sendCompleted];
276 | } failed:^(NSError * _Nullable error) {
277 | [subject sendError:error];
278 |
279 | }];
280 | return subject;
281 | }
282 |
283 | @end
284 |
285 | ```
286 |
287 | ## Use new sync
288 |
289 | ```objective-c
290 | id storageSync;
291 | id remoteSync;
292 | id dbSync;
293 | ```
294 |
295 | ```objective-c
296 | - (instancetype)init
297 | {
298 | if(self = [super init])
299 | {
300 | self.storageSync = [YTXRestfulModelXXXFileStorageSync new];
301 | }
302 | return self;
303 | }
304 |
305 | YTXTestModel * model = [YTXTestModel new];
306 | model.storageSync = [YTXRestfulModelXXXFileStorageSync new];
307 |
308 | ```
309 |
310 | If necessary, You can also using sync like this(如果有必要你可以直接使用sync想这样)
311 | ```objective-c
312 | #import
313 |
314 | YTXRestfulModelUserDefaultStorageSync * sync = [[YTXRestfulModelUserDefaultStorageSync alloc] initWithUserDefaultSuiteName:suitName1]
315 | ```
316 |
317 | ## DB mapping
318 |
319 | Column Struct
320 | ```objective-c
321 | YTXRestfulModelDBSerializingModel * dbsm = [YTXRestfulModelDBSerializingModel new];
322 | dbsm.objectClass = propertyClassName;
323 | dbsm.columnName = columnName;
324 | dbsm.modelName = modelProperyName;
325 | dbsm.isPrimaryKey = isPrimaryKey;
326 | dbsm.autoincrement = isPrimaryKeyAutoincrement;
327 | dbsm.unique = NO;
328 | ```
329 | ```objective-c
330 | @interface YTXRestfulModelDBSerializingModel : NSObject
331 |
332 | /** 可以是CType @"d"这种*/
333 | @property (nonatomic, nonnull, copy) NSString * objectClass;
334 |
335 | /** 表名 */
336 | @property (nonatomic, nonnull, copy) NSString * columnName;
337 |
338 | /** Model原始的属性名字 */
339 | @property (nonatomic, nonnull, copy) NSString * modelName;
340 |
341 | /** 是否 主键*/
342 | @property (nonatomic, assign) BOOL isPrimaryKey;
343 |
344 | /** 是否自增*/
345 | @property (nonatomic, assign) BOOL autoincrement;
346 |
347 | /** 是否唯一*/
348 | @property (nonatomic, assign) BOOL unique;
349 |
350 | /** 默认值*/
351 | @property (nonatomic, nonnull, copy) NSString * defaultValue;
352 |
353 | /** 外键类名 可以使用fetchForeignWithName */
354 | @property (nonatomic, nonnull, copy) NSString * foreignClassName;
355 |
356 | @end
357 | ```
358 |
359 | Modify DB mapping in child Model
360 | ```objective-c
361 | + (nullable NSMutableDictionary *) tableKeyPathsByPropertyKey
362 | {
363 | NSMutableDictionary * tmpDictionary = [super tableKeyPathsByPropertyKey];
364 |
365 | YTXRestfulModelDBSerializingModel * genderStruct = tmpDictionary[@"gender"];
366 | genderStruct.defaultValue = [@(GenderFemale) sqliteValue];
367 | tmpDictionary[@"gender"] = genderStruct;
368 |
369 | YTXRestfulModelDBSerializingModel * scoreStruct = tmpDictionary[@"score"];
370 | scoreStruct.unique = YES;
371 | tmpDictionary[@"score"] = scoreStruct;
372 | return tmpDictionary;
373 | }
374 | ```
375 |
376 | Open auto creating table, if you use DB function.(开启自动创建数据库表。需要使用DB时才这样做)
377 | ```objective-c
378 | + (BOOL) autoCreateTable
379 | {
380 | return YES;
381 | }
382 | ```
383 |
384 | Close auto incremen (关闭主键默认自增)
385 | ```objective-c
386 | + (BOOL) isPrimaryKeyAutoincrement
387 | {
388 | return NO;
389 | }
390 | ```
391 |
392 | Model支持的属性类型(CType) Model Type SQLite Type
393 | ```objective-c
394 | @{
395 | @"c":@[ @"NSNumber", @"INTEGER"],
396 | @"i":@[ @"NSNumber", @"INTEGER"],
397 | @"s":@[ @"NSNumber", @"INTEGER"],
398 | @"l":@[ @"NSNumber", @"INTEGER"],
399 | @"q":@[ @"NSNumber", @"INTEGER"],
400 | @"C":@[ @"NSNumber", @"INTEGER"],
401 | @"I":@[ @"NSNumber", @"INTEGER"],
402 | @"S":@[ @"NSNumber", @"INTEGER"],
403 | @"L":@[ @"NSNumber", @"INTEGER"],
404 | @"Q":@[ @"NSNumber", @"INTEGER"],
405 | @"f":@[ @"NSNumber", @"REAL"],
406 | @"d":@[ @"NSNumber", @"REAL"],
407 | @"B":@[ @"NSNumber", @"INTEGER"],
408 | @"NSString":@[ @"NSString", @"TEXT"],
409 | @"NSMutableString":@[ @"NSMutableString", @"TEXT"],
410 | @"NSDate":@[ @"NSDate", @"REAL"],
411 | @"NSNumber":@[ @"NSNumber", @"REAL"],
412 | @"NSDictionary":@[ @"NSDictionary", @"TEXT"],
413 | @"NSMutableDictionary":@[ @"NSDictionary", @"TEXT"],
414 | @"NSArray":@[ @"NSArray", @"TEXT"],
415 | @"NSMutableArray":@[ @"NSArray", @"TEXT"],
416 | //这里以下和Remote一般不兼容
417 | @"CGPoint":@[ @"NSValue", @"TEXT"],
418 | @"CGSize":@[ @"NSValue", @"TEXT"],
419 | @"CGRect":@[ @"NSValue", @"TEXT"],
420 | @"CGVector":@[ @"NSValue", @"TEXT"],
421 | @"CGAffineTransform":@[ @"NSValue", @"TEXT"],
422 | @"UIEdgeInsets":@[ @"NSValue", @"TEXT"],
423 | @"UIOffset":@[ @"NSValue", @"TEXT"],
424 | @"NSRange":@[ @"NSValue", @"TEXT"]
425 | }
426 | ```
427 | ## DB Alter(自动扩展字段到表中)
428 |
429 | ```objective-c
430 |
431 | + (BOOL) autoAlterTable
432 | {
433 | return YES;//Default
434 | }
435 |
436 | + (nullable NSNumber *) currentMigrationVersion
437 | {
438 | return @0;
439 | }
440 |
441 | ```
442 |
443 | | currentMigrationVersion | Property | DB Column |
444 | | ------------------------------ |:--------------------:| --------------------:|
445 | | 0 | Name,KeyId | name,keyid |
446 | | 1 | Name,KeyId,title | name,keyid,title |
447 | | 2 | Name,KeyId,title,age | name,keyId,title,age |
448 | | 3 | Name,KeyId,title | name,keyId,title,age |
449 |
450 |
451 | ## DB Migration(数据库迁移)
452 | ```objective-c
453 | // DB Migration(数据迁移)
454 | + (nullable NSNumber *) currentMigrationVersion
455 | {
456 | return @0;
457 | }
458 |
459 | + (BOOL) autoAlterTable
460 | {
461 | return NO;//Not Default
462 | }
463 | ```
464 |
465 | | currentMigrationVersion | Property | DB Column |
466 | | ------------------------------ |:--------------------:| ---------------------------:|
467 | | 0 | KeyId,age | keyid,age |
468 | | 1 | KeyId,age,title | keyId,age,title |
469 | | 2 | KeyId,age,name | keyId,age,title,title=>name |
470 |
471 | sqlite does not support function rename an drop(sqlite并没有提供rename和drop column的方法)
472 |
473 | ## Migration Example
474 |
475 | ```objective-c
476 |
477 | //数据库迁移操作是从当前版本到最新版本依次进行的,所以本方法中要存储所有版本的迁移操作。
478 | + (void) migrationsMethodWithSync:(nonnull id)sync;
479 | {
480 | // 创建 数据库迁移的操作
481 | YTXRestfulModelDBMigrationEntity *migration = [YTXRestfulModelDBMigrationEntity new];
482 | // 设置 进行本次操作时的版本号
483 | migration.version = @1;
484 | // 设置 迁移操作(增、删、改)
485 | migration.block = ^(_Nonnull id db, NSError * _Nullable * _Nullable error) {
486 | YTXRestfulModelDBSerializingModel *runtimePStruct = [YTXRestfulModelDBSerializingModel new];
487 | runtimePStruct.objectClass = @"NSString";
488 | runtimePStruct.columnName = @"runtimeP";
489 | runtimePStruct.modelName = @"runtimeP";
490 | runtimePStruct.isPrimaryKey = NO;
491 | runtimePStruct.autoincrement = NO;
492 | runtimePStruct.unique = NO;
493 | // 创建新的列
494 | [sync createColumnWithDB:db structSync:runtimePStruct error:error];
495 | };
496 | // 存储 迁移操作
497 | [sync migrate:migration];
498 | }
499 |
500 | ```
501 |
502 |
503 | ```objective-c
504 | - (BOOL) createColumnWithDB:(nonnull id)db structSync:(nonnull YTXRestfulModelDBSerializingModel *)sstruct error:(NSError * _Nullable * _Nullable)error;
505 |
506 | @optional
507 |
508 | - (BOOL) renameColumnWithDB:(nonnull id)db originName:(nonnull NSString *)originName newName:(nonnull NSString *)newName error:(NSError * _Nullable * _Nullable)error;
509 |
510 | - (BOOL) dropColumnWithDB:(nonnull id)db structSync:(nonnull YTXRestfulModelDBSerializingModel *)sstruct error:(NSError * _Nullable * _Nullable)error;
511 |
512 | - (BOOL) changeCollumnDB:(nonnull id)db oldStructSync:(nonnull YTXRestfulModelDBSerializingModel *) oldStruct toNewStruct:(nonnull YTXRestfulModelDBSerializingModel *) newStruct error:(NSError * _Nullable * _Nullable)error;
513 | ```
514 |
515 | Migration Delegate
516 | ```objective-c
517 | + (void)dbWillMigrateWithSync:(nonnull id)sync
518 | {
519 | }
520 |
521 | + (void)dbDidMigrateWithSync:(nonnull id)sync
522 | {
523 | }
524 | ```
525 | ## Remote Hook
526 | 所有请求都会附带这些参数,hook的优先级最低,总是会被其他同名参数覆盖
527 | ```objective-c
528 | NSDictionary *(^hook)() = ^NSDictionary *() {
529 | return @{
530 | @"deviceToken": objectOrEmptyStr([NotificationManager sharedManager].deviceToken),
531 | @"deviceId": objectOrEmptyStr([AppInfo deviceUUID]),
532 | @"marketId": objectOrEmptyStr([AppInfo marketId]),
533 | @"appVersion": objectOrEmptyStr([AppInfo appVersion])
534 | };
535 | };
536 |
537 | AFNetworkingRemoteSync.HookExtraParamBlock = hook;
538 | ```
539 |
540 | ## Remote Hook Request
541 | 在发送请求的时候统一修改Header或者其他行为
542 | ```objective-c
543 | AFNetworkingRemoteSync.hookRequestBlock = ^(AFNetworkingRemoteSync * sync, NSString * method, NSURL ** url, NSMutableDictionary ** paramters) {
544 | retParamters = *paramters;
545 | retParamters[@"title"] = @"XXXX";
546 | *paramters = retParamters;
547 |
548 | AFHTTPSessionManager * sessionManager = sync.requestSessionManager;
549 | [sessionManager.requestSerializer setValue:@"test" forHTTPHeaderField:@"x-auth-token"];
550 | };
551 | ```
552 |
553 |
554 | ## subspec
555 | - AFNetworkingRemoteSync: 'AFNetworking', '~> 2.6.3'
556 | - FMDBSync: 'FMDB', '~> 2.6'
557 | - UserDefaultStorageSync:
558 | - RACSupport:'ReactiveCocoa', '~> 2.3.1'
559 |
560 |
561 |
562 | ## License
563 |
564 | YTXRestfulModel was built by caojun. It is licensed under the MIT License.
565 |
566 | If you use YTXRestfulModel in one of your apps, I'd love to hear about it.
567 |
--------------------------------------------------------------------------------
/YTXRestfulModel.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint YTXRestfulModel.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = "YTXRestfulModel"
11 | s.version = "1.2.2"
12 | s.summary = "YTXRestfulModel 提供了restful的功能"
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.homepage = "https://github.com/baidao/YTXRestfulModel"
21 | # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
22 | s.license = 'MIT'
23 | s.author = { "caojun" => "78612846@qq.com" }
24 | s.source = { :git => "https://github.com/baidao/YTXRestfulModel.git", :tag => s.version.to_s }
25 |
26 | s.platform = :ios, '7.0'
27 | s.requires_arc = true
28 |
29 | s.subspec "Default" do |ss|
30 | ss.source_files = ["Pod/Classes/Model/**/*", "Pod/Classes/Protocol/**/*"]
31 | ss.dependency 'Mantle', '~> 1.5.7'
32 | end
33 |
34 | s.subspec "RACSupport" do |ss|
35 | ss.source_files = ["Pod/Classes/RACSupport/**/*"]
36 | ss.dependency 'ReactiveCocoa', '~> 2.3.1'
37 | ss.dependency 'YTXRestfulModel/Default'
38 | end
39 |
40 | _AFNetworkingRemoteSync = { :spec_name => "AFNetworkingRemoteSync", :dependency => [{:name => "AFNetworking", :version => "~> 2.6.3" }] }
41 | _FMDBSync = { :spec_name => "FMDBSync", :dependency => [{:name => "FMDB", :version => "~> 2.6" }] }
42 | _UserDefaultStorageSync = { :spec_name => "UserDefaultStorageSync" }
43 |
44 | _all_names = []
45 |
46 | _all_sync = [_AFNetworkingRemoteSync, _FMDBSync, _UserDefaultStorageSync]
47 |
48 | _all_sync.each do |sync_spec|
49 | s.subspec sync_spec[:spec_name] do |ss|
50 |
51 | specname = sync_spec[:spec_name]
52 |
53 | _all_names << specname
54 |
55 | sources = ["Pod/Classes/Sync/#{specname}/**/*"]
56 |
57 | ss.prefix_header_contents = "#define YTX_#{specname.upcase}_EXISTS 1"
58 |
59 | ss.source_files = sources
60 |
61 | ss.dependency 'YTXRestfulModel/Default'
62 |
63 | if sync_spec[:dependency]
64 | sync_spec[:dependency].each do |dep|
65 | ss.dependency dep[:name], dep[:version]
66 | end
67 | end
68 |
69 | end
70 | end
71 |
72 |
73 | s.default_subspec = 'Default'
74 |
75 | spec_names = _all_names[0...-1].join(", ") + " 和 " + _all_names[-1]
76 |
77 | s.description = "提供了restful的model和collection。提供这些sync:#{spec_names}"
78 | end
79 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------
/buildpod.sh:
--------------------------------------------------------------------------------
1 | pushd "$(dirname "$0")" > /dev/null
2 | SCRIPT_DIR=$(pwd -L)
3 | popd > /dev/null
4 |
5 | echo "publish repo YTXRestfulModel"
6 | pod trunk push YTXRestfulModel.podspec --verbose
7 |
8 | ret=$?
9 |
10 | #exit $ret
11 |
--------------------------------------------------------------------------------
/lint.sh:
--------------------------------------------------------------------------------
1 | pod lib lint --sources='http://gitlab.baidao.com/ios/ytx-pod-specs.git,master' --verbose
2 |
--------------------------------------------------------------------------------