This repository has been archived by the owner on May 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
NICollectionViewCellFactory.h
196 lines (175 loc) · 7.67 KB
/
NICollectionViewCellFactory.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
//
// Copyright 2011 Jeff Verkoeyen
//
// 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "NICollectionViewModel.h"
/**
* A simple factory for creating collection view cells from objects.
*
* This factory provides a single method that accepts an object and returns a UICollectionViewCell
* for use in a UICollectionView. A cell will only be returned if the object passed to the factory
* conforms to the NICollectionViewCellObject protocol. The created cell should ideally conform to
* the NICollectionViewCell protocol. If it does, the object will be passed to it via
* @link NICollectionViewCell::shouldUpdateCellWithObject: shouldUpdateCellWithObject:@endlink
* before the factory method returns.
*
* This factory is designed to be used with NICollectionViewModel, though one could easily use
* it with other collection view data source implementations simply by providing nil for the
* collection view model.
*
* If you instantiate an NICollectionViewCellFactory then you can provide explicit mappings from
* objects to cells. This is helpful if the effort required to implement the NICollectionViewCell
* protocol on an object outweighs the benefit of using the factory, i.e. when you want to map
* simple types such as NSString to cells.
*
* @ingroup CollectionViewCellFactory
*/
@interface NICollectionViewCellFactory : NSObject <NICollectionViewModelDelegate>
/**
* Creates a cell from a given object if and only if the object conforms to the NICollectionViewCellObject
* protocol.
*
* This method signature matches the NICollectionViewModelDelegate method so that you can
* set this factory as the model's delegate:
*
* @code
// Must cast to id to avoid compiler warnings.
_model.delegate = (id)[NICollectionViewCellFactory class];
* @endcode
*
* If you would like to customize the factory's output, implement the model's delegate method
* and call the factory method. Remember that if the factory doesn't know how to map
* the object to a cell it will return nil.
*
* @code
- (UICollectionViewCell *)collectionViewModel:(NICollectionViewModel *)collectionViewModel
cellForCollectionView:(UICollectionView *)collectionView
atIndexPath:(NSIndexPath *)indexPath
withObject:(id)object {
UICollectionViewCell* cell = [NICollectionViewCellFactory collectionViewModel:collectionViewModel
cellForCollectionView:collectionView
atIndexPath:indexPath
withObject:object];
if (nil == cell) {
// Custom cell creation here.
}
return cell;
}
* @endcode
*/
+ (UICollectionViewCell *)collectionViewModel:(NICollectionViewModel *)collectionViewModel cellForCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath withObject:(id)object;
/**
* Map an object's class to a cell's class.
*
* If an object implements the NICollectionViewCell protocol AND is found in this factory
* mapping, the factory mapping will take precedence. This allows you to
* explicitly override the mapping on a case-by-case basis.
*/
- (void)mapObjectClass:(Class)objectClass toCellClass:(Class)collectionViewCellClass;
@end
@interface NICollectionViewCellFactory (KeyClassMapping)
/**
* Returns a mapped object from the given key class.
*
* If the key class is a subclass of any mapped key classes, the nearest ancestor class's mapped
* object will be returned and keyClass will be added to the map for future accesses.
*
* @param keyClass The key class that will be used to find the mapping in map.
* @param map A map of key classes to classes. May be modified if keyClass is a subclass of
* any existing key classes.
* @returns The mapped object if a match for keyClass was found in map. nil is returned
* otherwise.
*/
+ (id)objectFromKeyClass:(Class)keyClass map:(NSMutableDictionary *)map;
@end
/**
* The protocol for an object that can be used in the NICollectionViewCellFactory.
*
* @ingroup TableCellFactory
*/
@protocol NICollectionViewCellObject <NSObject>
@required
/** The class of cell to be created when this object is passed to the cell factory. */
- (Class)collectionViewCellClass;
@end
/**
* The protocol for a cell created in the NICollectionViewCellFactory.
*
* Cells that implement this protocol are given the object that implemented the NICollectionViewCellObject
* protocol and returned this cell's class name in @link NICollectionViewCellObject::collectionViewCellClass collectionViewCellClass@endlink.
*
* @ingroup TableCellFactory
*/
@protocol NICollectionViewCell <NSObject>
@required
/**
* Called when a cell is created and reused.
*
* Implement this method to customize the cell's properties for display using the given object.
*/
- (BOOL)shouldUpdateCellWithObject:(id)object;
@optional
/**
* Asks the receiver to calculate its height.
*
* The following is an appropiate implementation in your collectionView's delegate:
*
@code
-(CGFloat)collectionView:(UICollectionView *)collectionView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat height = collectionView.rowHeight;
id object = [(NICollectionViewModel *)collectionView.dataSource objectAtIndexPath:indexPath];
id class = [object collectionViewCellClass];
if ([class respondsToSelector:@selector(heightForObject:atIndexPath:collectionView:)]) {
height = [class heightForObject:object atIndexPath:indexPath collectionView:collectionView];
}
return height;
}
@endcode
*
* You may also use the
* @link NICollectionViewCellFactory::collectionView:heightForRowAtIndexPath:model: collectionView:heightForRowAtIndexPath:model:@endlink
* methods on NICollectionViewCellFactory to achieve the same result. Using the above example allows you to
* customize the logic according to your specific needs.
*/
+ (CGFloat)heightForObject:(id)object atIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView;
@end
/**
* A light-weight implementation of the NICollectionViewCellObject protocol.
*
* Use this object in cases where you can't set up a hard binding between an object and a cell,
* or when you simply don't want to.
*
* For example, let's say that you want to show a cell that shows a loading indicator.
* Rather than create a new interface, LoadMoreObject, simply for the cell and binding it
* to the cell view, you can create an NICollectionViewCellObject and pass the class name of the cell.
*
@code
[tableContents addObject:[NICollectionViewCellObject objectWithCellClass:[LoadMoreCell class]]];
@endcode
*/
@interface NICollectionViewCellObject : NSObject <NICollectionViewCellObject>
// Designated initializer.
- (id)initWithCellClass:(Class)collectionViewCellClass userInfo:(id)userInfo;
- (id)initWithCellClass:(Class)collectionViewCellClass;
+ (id)objectWithCellClass:(Class)collectionViewCellClass userInfo:(id)userInfo;
+ (id)objectWithCellClass:(Class)collectionViewCellClass;
@property (nonatomic, readonly, NI_STRONG) id userInfo;
@end
/**
* An object that can be used to populate information in the cell.
*
* @fn NICollectionViewCellObject::userInfo
*/