杨锴
2024-10-09 e987bc09f955e01c2835f01e3a6af20723a579f9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//
//  OBSMTLModel.h
//  Mantle
//
//  Created by Justin Spahr-Summers on 2012-09-11.
//  Copyright (c) 2012 GitHub. All rights reserved.
//
 
#import <Foundation/Foundation.h>
 
/// Defines a property's storage behavior, which affects how it will be copied,
/// compared, and persisted.
///
/// OBSMTLPropertyStorageNone       - This property is not included in -description,
///                                -hash, or anything else.
/// OBSMTLPropertyStorageTransitory - This property is included in one-off
///                                operations like -copy and -dictionaryValue but
///                                does not affect -isEqual: or -hash.
///                                It may disappear at any time.
/// OBSMTLPropertyStoragePermanent  - The property is included in serialization
///                                (like `NSCoding`) and equality, since it can
///                                be expected to stick around.
typedef enum : NSUInteger {
    OBSMTLPropertyStorageNone,
    OBSMTLPropertyStorageTransitory,
    OBSMTLPropertyStoragePermanent,
} OBSMTLPropertyStorage;
 
/// This protocol defines the minimal interface that classes need to implement to
/// interact with Mantle adapters.
///
/// It is intended for scenarios where inheriting from OBSMTLModel is not feasible.
/// However, clients are encouraged to subclass the OBSMTLModel class if they can.
///
/// Clients that wish to implement their own adapters should target classes
/// conforming to this protocol rather than subclasses of OBSMTLModel to ensure
/// maximum compatibility.
@protocol OBSMTLModel <NSObject, NSCopying>
 
/// Initializes a new instance of the receiver using key-value coding, setting
/// the keys and values in the given dictionary.
///
/// dictionaryValue - Property keys and values to set on the instance. Any NSNull
///                   values will be converted to nil before being used. KVC
///                   validation methods will automatically be invoked for all of
///                   the properties given.
/// error           - If not NULL, this may be set to any error that occurs
///                   (like a KVC validation error).
///
/// Returns an initialized model object, or nil if validation failed.
+ (instancetype)modelWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error;
 
/// A dictionary representing the properties of the receiver.
///
/// Combines the values corresponding to all +propertyKeys into a dictionary,
/// with any nil values represented by NSNull.
///
/// This property must never be nil.
@property (nonatomic, copy, readonly) NSDictionary *dictionaryValue;
 
/// Initializes the receiver using key-value coding, setting the keys and values
/// in the given dictionary.
///
/// Subclass implementations may override this method, calling the super
/// implementation, in order to perform further processing and initialization
/// after deserialization.
///
/// dictionaryValue - Property keys and values to set on the receiver. Any NSNull
///                   values will be converted to nil before being used. KVC
///                   validation methods will automatically be invoked for all of
///                   the properties given. If nil, this method is equivalent to
///                   -init.
/// error           - If not NULL, this may be set to any error that occurs
///                   (like a KVC validation error).
///
/// Returns an initialized model object, or nil if validation failed.
- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error;
 
/// Merges the value of the given key on the receiver with the value of the same
/// key from the given model object, giving precedence to the other model object.
- (void)mergeValueForKey:(NSString *)key fromModel:(id<OBSMTLModel>)model;
 
/// Returns the keys for all @property declarations, except for `readonly`
/// properties without ivars, or properties on OBSMTLModel itself.
+ (NSSet *)propertyKeys;
 
/// Validates the model.
///
/// error - If not NULL, this may be set to any error that occurs during
///         validation
///
/// Returns YES if the model is valid, or NO if the validation failed.
- (BOOL)validate:(NSError **)error;
 
@end
 
/// An abstract base class for model objects, using reflection to provide
/// sensible default behaviors.
///
/// The default implementations of <NSCopying>, -hash, and -isEqual: make use of
/// the +propertyKeys method.
@interface OBSMTLModel : NSObject <OBSMTLModel>
 
/// Initializes the receiver using key-value coding, setting the keys and values
/// in the given dictionary.
///
/// dictionaryValue - Property keys and values to set on the receiver. Any NSNull
///                   values will be converted to nil before being used. KVC
///                   validation methods will automatically be invoked for all of
///                   the properties given. If nil, this method is equivalent to
///                   -init.
/// error           - If not NULL, this may be set to any error that occurs
///                   (like a KVC validation error).
///
/// Returns an initialized model object, or nil if validation failed.
- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error;
 
/// Initializes the receiver with default values.
///
/// This is the designated initializer for this class.
- (instancetype)init;
 
/// By default, this method looks for a `-merge<Key>FromModel:` method on the
/// receiver, and invokes it if found. If not found, and `model` is not nil, the
/// value for the given key is taken from `model`.
- (void)mergeValueForKey:(NSString *)key fromModel:(id<OBSMTLModel>)model;
 
/// Merges the values of the given model object into the receiver, using
/// -mergeValueForKey:fromModel: for each key in +propertyKeys.
///
/// `model` must be an instance of the receiver's class or a subclass thereof.
- (void)mergeValuesForKeysFromModel:(id<OBSMTLModel>)model;
 
/// The storage behavior of a given key.
///
/// The default implementation returns OBSMTLPropertyStorageNone for properties that
/// are readonly and not backed by an instance variable and
/// OBSMTLPropertyStoragePermanent otherwise.
///
/// Subclasses can use this method to prevent OBSMTLModel from resolving circular
/// references by returning OBSMTLPropertyStorageTransitory.
///
/// Returns the storage behavior for a given key on the receiver.
+ (OBSMTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey;
 
/// Compares the receiver with another object for equality.
///
/// The default implementation is equivalent to comparing all properties of both
/// models for which +storageBehaviorForPropertyWithKey: returns
/// OBSMTLPropertyStoragePermanent.
///
/// Returns YES if the two models are considered equal, NO otherwise.
- (BOOL)isEqual:(id)object;
 
/// A string that describes the contents of the receiver.
///
/// The default implementation is based on the receiver's class and all its
/// properties for which +storageBehaviorForPropertyWithKey: returns
/// OBSMTLPropertyStoragePermanent.
- (NSString *)description;
 
@end
 
/// Implements validation logic for OBSMTLModel.
@interface OBSMTLModel (Validation)
 
/// Validates the model.
///
/// The default implementation simply invokes -validateValue:forKey:error: with
/// all +propertyKeys and their current value. If -validateValue:forKey:error:
/// returns a new value, the property is set to that new value.
///
/// error - If not NULL, this may be set to any error that occurs during
///         validation
///
/// Returns YES if the model is valid, or NO if the validation failed.
- (BOOL)validate:(NSError **)error;
 
@end