/
RKPaginator.h
280 lines (213 loc) · 11.2 KB
/
RKPaginator.h
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
//
// RKPaginator.h
// RestKit
//
// Created by Blake Watters on 12/29/11.
// Copyright (c) 2009-2012 RestKit. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "RKHTTPRequestOperation.h"
#import "RKObjectRequestOperation.h"
#import "RKObjectMapping.h"
#import "RKMappingResult.h"
@protocol RKManagedObjectCaching;
/**
Instances of `RKPaginator` retrieve paginated collections of mappable data from remote systems via HTTP. Paginators perform GET requests and use a patterned URL to construct a full URL reflecting the state of the paginator. Paginators rely on an instance of RKObjectMappingProvider to determine how to perform object mapping on the retrieved data. Paginators can load Core Data backed models provided that an instance of RKManagedObjectStore is assigned to the paginator.
## Configuring Pagination Mapping
The paginator must be configured with a `paginationMapping` specifying how configuration metadata is to be mapped out of the response payload. The configured mapping must have an `objectClass` of `RKPaginator` and should include attribute mappings for the `currentPage`, `pageCount`, `perPage`, and `objectCount`. For example, given a paginated resource loaded from '/articles?page=1' with the followibg JSON:
{ "pagination": { "per_page": 10, "total_pages": 25, "total_objects": 250 }, "articles": [ // Array of articles ] }
The pagination mapping would be configured as:
RKObjectMapping *paginationMapping = [RKObjectMapping mappingForClass:[RKPaginator class]];
[paginationMapping addAttributeMappingsFromDictionary:@{
@"pagination.per_page": @"perPage",
@"pagination.total_pages": @"pageCount",
@"pagination.total_objects": @"objectCount",
}];
## iOS 5 Compatibility Caveats
The paginator is compatible with iOS 5.x through the use of proxy attributes. In iOS 6.0 and greater, key-value coding supports the automatic boxing and unboxing of primitive values. This enables direct mapping configuration for the `currentPage`, `pageCount`, `perPage`, and `objectCount` attributes. Under iOS 5, where autoboxing is not available, mapping configuration must target special proxy attributes instead. For each of the above properties, a private `NSNumber` property is implemented by the class. Each proxy property has 'Number' appended as a suffix to the property name: `currentPageNumber`, `pageCountNumber`, `perPageNumber`, and `objectCountNumber`.
*/
@interface RKPaginator : NSObject
///-------------------------------------
/// @name Initializing Paginator Objects
///-------------------------------------
/**
Initializes a RKPaginator object with the a provided patternURL and mappingProvider.
@param request A request with a URL containing a dynamic pattern specifying how paginated resources are to be accessed.
@param paginationMapping The pagination mapping specifying how pagination metadata is to be mapped from responses.
@param responseDescriptors An array of response descriptors describing how to map object representations loaded by object request operations dispatched by the paginator.
@return The receiver, initialized with the request, pagination mapping, and response descriptors.
*/
- (instancetype)initWithRequest:(NSURLRequest *)request
paginationMapping:(RKObjectMapping *)paginationMapping
responseDescriptors:(NSArray *)responseDescriptors;
///-----------------------------
/// @name Configuring Networking
///-----------------------------
/**
A URL with a path pattern for building a complete URL from
which to load the paginated resource collection. The patterned resource
path will be evaluated against the state of the paginator object itself.
For example, given a paginated collection of data at the /articles path,
the path portion of the pattern URL may look like:
/articles?per_page=:perPage&page_number=:currentPage
When the pattern is evaluated against the state of the paginator, this will
yield a complete path that can be used to load the specified page. Given
a paginator configured with 100 objects per page and a current page number of 3,
the path portion of the pagination URL would become:
/articles?per_page=100&page_number=3
*/
@property (nonatomic, readonly) NSURL *patternURL;
/**
Returns a complete URL to the paginated resource collection by interpolating the state of the paginator object against the patternURL.
*/
@property (nonatomic, readonly) NSURL *URL;
/**
An optional operation queue on which object request operations constructed by the paginator are to be enqueued for processing.
*/
@property (nonatomic, strong) NSOperationQueue *operationQueue;
/**
Returns the last object request operation used by the paginator to load a page of objects.
*/
@property (nonatomic, strong, readonly) RKObjectRequestOperation *objectRequestOperation;
/**
Sets the `RKHTTPRequestOperation` subclass to be used when constructing HTTP request operations for requests dispatched by the paginator.
**Default**: `[RKHTTPRequestOperation class]`
*/
- (void)setHTTPOperationClass:(Class)operationClass;
///-----------------------------------
/// @name Setting the Completion Block
///-----------------------------------
/**
Sets the completion block to be invoked when the paginator finishes loading a page of results.
@param success A block to be executed upon a successful load of a page of objects. The block has no return value and takes three arguments: the paginator object, an array containing the paginated objects, and an integer indicating the page that was loaded.
@param failure A block to be exected upon a failed load. The block has no return value and takes two arguments: the paginator object and an error indicating the nature of the failure.
*/
- (void)setCompletionBlockWithSuccess:(void (^)(RKPaginator *paginator, NSArray *objects, NSUInteger page))success
failure:(void (^)(RKPaginator *paginator, NSError *error))failure;
///-----------------------------------
/// @name Accessing Pagination Results
///-----------------------------------
/**
The mapping result containing the last set of paginated objects or `nil` if an error was encountered.
*/
@property (nonatomic, strong, readonly) RKMappingResult *mappingResult;
/**
The error, if any, that occured during the last load of the paginator.
*/
@property (nonatomic, strong, readonly) NSError *error;
///-----------------------------------
/// @name Object Mapping Configuration
///-----------------------------------
/**
The object mapping defining how pagination metadata is to be mapped from a paginated response onto the paginator object.
See the documentation in the "Configuring Pagination Mapping" section for details about the pagination mapping.
@warning The `objectClass` of the given mapping must be `RKPaginator`.
*/
@property (nonatomic, strong) RKObjectMapping *paginationMapping;
///------------------------------
/// @name Core Data Configuration
///------------------------------
#if __has_include("CoreData.h")
/**
The managed object context in which paginated managed objects are to be persisted.
*/
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
/**
The managed object cache used to find existing managed object instances in the persistent store.
*/
@property (nonatomic, strong) id<RKManagedObjectCaching> managedObjectCache;
/**
An array of fetch request blocks.
*/
@property (nonatomic, copy) NSArray *fetchRequestBlocks;
#endif
///------------------------------------
/// @name Accessing Pagination Metadata
///------------------------------------
/**
The number of objects to load per page
*/
@property (nonatomic, assign) NSUInteger perPage;
/**
A Boolean value indicating if the paginator has loaded a page of objects
@returns YES when the paginator has loaded a page of objects
*/
@property (nonatomic, readonly, getter = isLoaded) BOOL loaded;
/**
Returns the page number for the most recently loaded page of objects.
@return The page number for the current page of objects.
@exception NSInternalInconsistencyException Raised if `isLoaded` is equal to `NO`.
*/
@property (nonatomic, readonly) NSUInteger currentPage;
/**
Returns the offset based off the page for the most recently loaded objects.
@return The offset for the current page of objects.
@exception NSInternalInconsistencyException Raised if `isLoaded` is equal to `NO`.
*/
@property (nonatomic, readonly) NSUInteger offset;
/**
Returns the number of pages in the total resource collection.
@return A count of the number of pages in the resource collection.
@exception NSInternalInconsistencyException Raised if `hasPageCount` is `NO`.
*/
@property (nonatomic, readonly) NSUInteger pageCount;
/**
Returns the total number of objects in the collection
@return A count of the number of objects in the resource collection.
@exception NSInternalInconsistencyException Raised if `hasObjectCount` is `NO`.
*/
@property (nonatomic, readonly) NSUInteger objectCount;
/**
Returns a Boolean value indicating if the total number of pages in the collection is known by the paginator.
@return `YES` if the paginator knows the page count, otherwise `NO`.
*/
@property (nonatomic, readonly) BOOL hasPageCount;
/**
Returns a Boolean value indicating if the total number of objects in the collection is known by the paginator.
@return `YES` if the paginator knows the number of objects in the paginated collection, otherwise `NO`.
*/
@property (nonatomic, readonly) BOOL hasObjectCount;
/**
Returns a Boolean value indicating if there is a next page in the collection.
@return `YES` if there is a next page, otherwise `NO`.
@exception NSInternalInconsistencyException Raised if isLoaded or hasPageCount is `NO`.
*/
@property (nonatomic, readonly) BOOL hasNextPage;
/**
Returns a Boolean value indicating if there is a previous page in the collection.
@return `YES` if there is a previous page, otherwise `NO`.
@exception NSInternalInconsistencyException Raised if isLoaded is `NO`.
*/
@property (nonatomic, readonly) BOOL hasPreviousPage;
///------------------------
/// @name Paginator Actions
///------------------------
/**
Loads the next page of data by incrementing the current page, constructing an object loader to fetch the data, and object mapping the results.
*/
- (void)loadNextPage;
/**
Loads the previous page of data by decrementing the current page, constructing an object loader to fetch the data, and object mapping the results.
*/
- (void)loadPreviousPage;
/**
Loads a specific page of data by mutating the current page, constructing an object loader to fetch the data, and object mapping the results.
@param pageNumber The page of objects to load from the remote backend
*/
- (void)loadPage:(NSUInteger)pageNumber;
/**
Cancels an in-progress pagination request.
*/
- (void)cancel;
@end