mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-24 04:46:01 +08:00
Added support for grouping objects into sections within RKTableController. closes #658
This commit is contained in:
27
Code/Support/NSArray+RKAdditions.h
Normal file
27
Code/Support/NSArray+RKAdditions.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// NSArray+RKAdditions.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 4/10/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
Provides useful additions to the NSArray interface.
|
||||
*/
|
||||
@interface NSArray (RKAdditions)
|
||||
|
||||
/**
|
||||
Evaluates a given key path against the receiving array, divides the array entries into
|
||||
sections grouped by the value for the key path, and returns an aggregate array of arrays
|
||||
containing the sections. The receiving array is assumed to be sorted.
|
||||
|
||||
@param keyPath The key path of the value to group the entries by.
|
||||
@returns An array of section arrays, with each section containing a group of objects sharing
|
||||
the same value for the given key path.
|
||||
*/
|
||||
- (NSArray *)sectionsGroupedByKeyPath:(NSString *)keyPath;
|
||||
|
||||
@end
|
||||
29
Code/Support/NSArray+RKAdditions.m
Normal file
29
Code/Support/NSArray+RKAdditions.m
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// NSArray+RKAdditions.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 4/10/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSArray+RKAdditions.h"
|
||||
|
||||
@implementation NSArray (RKAdditions)
|
||||
|
||||
- (NSArray *)sectionsGroupedByKeyPath:(NSString *)keyPath
|
||||
{
|
||||
NSString *keyPathWithOperator = [NSString stringWithFormat:@"@distinctUnionOfObjects.%@", keyPath];
|
||||
NSArray *sectionValues = [self valueForKeyPath:keyPathWithOperator];
|
||||
NSMutableArray *sections = [NSMutableArray arrayWithCapacity:[sectionValues count]];
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = $sectionValue", keyPath];
|
||||
for (id value in sectionValues) {
|
||||
NSDictionary *sub = [NSDictionary dictionaryWithObject:value forKey:@"sectionValue"];
|
||||
NSPredicate *sectionPredicate = [predicate predicateWithSubstitutionVariables:sub];
|
||||
NSArray *objectsForSection = [self filteredArrayUsingPredicate:sectionPredicate];
|
||||
[sections addObject:objectsForSection];
|
||||
}
|
||||
|
||||
return [NSArray arrayWithArray:sections];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -30,3 +30,6 @@
|
||||
#import "NSDictionary+RKAdditions.h"
|
||||
#import "NSString+RKAdditions.h"
|
||||
#import "NSBundle+RKAdditions.h"
|
||||
#import "NSArray+RKAdditions.h"
|
||||
#import "NSData+RKAdditions.h"
|
||||
#import "NSURL+RKAdditions.h"
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
After the block is invoked, the objects will be loaded into the specified section.
|
||||
*/
|
||||
// TODO: Update comments...
|
||||
- (void)loadTableItems:(NSArray *)tableItems withMappingBlock:(void (^)(RKTableViewCellMapping *))block; // TODO: Eliminate...
|
||||
- (void)loadTableItems:(NSArray *)tableItems withMapping:(RKTableViewCellMapping *)cellMapping;
|
||||
- (void)loadTableItems:(NSArray *)tableItems
|
||||
inSection:(NSUInteger)sectionIndex
|
||||
@@ -103,6 +102,11 @@
|
||||
/// @name Managing Sections
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
The key path on the loaded objects used to determine the section they belong to.
|
||||
*/
|
||||
@property(nonatomic, copy) NSString *sectionNameKeyPath;
|
||||
|
||||
// Coalesces a series of table view updates performed within the block into
|
||||
// a single animation using beginUpdates: and endUpdates: on the table view
|
||||
// TODO: Move to super-class?
|
||||
@@ -113,12 +117,6 @@
|
||||
// NOTE: connects cellMappings if section.cellMappings is nil...
|
||||
- (void)addSection:(RKTableSection *)section;
|
||||
|
||||
/**
|
||||
Creates an section and yields it to the block for configuration. After the block
|
||||
is evaluated, the section is added to the table.
|
||||
*/
|
||||
- (void)addSectionUsingBlock:(void (^)(RKTableSection *section))block;
|
||||
|
||||
/** Inserts a new section at the specified index.
|
||||
* @param section Must be a valid non nil RKTableViewSection.
|
||||
* @param index Must be less than the total number of sections. */
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#import "RKAbstractTableController_Internals.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKFormSection.h"
|
||||
#import "NSArray+RKAdditions.h"
|
||||
|
||||
// Define logging component
|
||||
#undef RKLogComponent
|
||||
@@ -30,6 +31,7 @@
|
||||
@implementation RKTableController
|
||||
|
||||
@synthesize form = _form;
|
||||
@synthesize sectionNameKeyPath = _sectionNameKeyPath;
|
||||
|
||||
#pragma mark - Instantiation
|
||||
|
||||
@@ -51,7 +53,8 @@
|
||||
- (void)dealloc {
|
||||
[self removeObserver:self forKeyPath:@"sections"];
|
||||
[_form release];
|
||||
|
||||
[_sectionNameKeyPath release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -93,10 +96,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addSectionUsingBlock:(void (^)(RKTableSection *section))block {
|
||||
[self addSection:[RKTableSection sectionUsingBlock:block]];
|
||||
}
|
||||
|
||||
- (void)removeSection:(RKTableSection *)section {
|
||||
NSAssert(section, @"Cannot remove a nil section");
|
||||
if ([self.sections containsObject:section] && self.sectionCount == 1) {
|
||||
@@ -179,7 +178,7 @@
|
||||
return [mutableObjects autorelease];
|
||||
}
|
||||
|
||||
// TODO: NOTE - Everything currently needs to pass through this method to pick up header/footer rows...
|
||||
// NOTE - Everything currently needs to pass through this method to pick up header/footer rows...
|
||||
- (void)loadObjects:(NSArray *)objects inSection:(NSUInteger)sectionIndex {
|
||||
// Clear any existing error state from the table
|
||||
self.error = nil;
|
||||
@@ -241,10 +240,6 @@
|
||||
[self loadTableItems:tableItems inSection:0];
|
||||
}
|
||||
|
||||
- (void)loadTableItems:(NSArray *)tableItems withMappingBlock:(void (^)(RKTableViewCellMapping*))block {
|
||||
[self loadTableItems:tableItems inSection:0 withMapping:[RKTableViewCellMapping cellMappingUsingBlock:block]];
|
||||
}
|
||||
|
||||
#pragma mark - Network Table Loading
|
||||
|
||||
- (void)loadTableFromResourcePath:(NSString*)resourcePath {
|
||||
@@ -275,12 +270,6 @@
|
||||
[self addSection:(RKTableSection *)section];
|
||||
}
|
||||
|
||||
// TODO: How to handle animating loading a replacement form?
|
||||
// if (self.loaded) {
|
||||
// NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [form.sections count] - 1)];
|
||||
// [self.tableView reloadSections:indexSet withRowAnimation:self.defaultRowAnimation];
|
||||
// }
|
||||
|
||||
[self didFinishLoad];
|
||||
[form didLoadInTableController:self];
|
||||
}
|
||||
@@ -331,15 +320,25 @@
|
||||
|
||||
- (void)objectLoader:(RKObjectLoader *)loader didLoadObjects:(NSArray *)objects {
|
||||
// TODO: Could not get the KVO to work without a boolean property...
|
||||
// TODO: Need to figure out how to group the objects into sections
|
||||
// TODO: Apply any sorting...
|
||||
|
||||
// Load them into the first section for now
|
||||
[self loadObjects:objects inSection:0];
|
||||
|
||||
if (self.sectionNameKeyPath) {
|
||||
[self removeAllSections];
|
||||
|
||||
NSArray *sectionedObjects = [objects sectionsGroupedByKeyPath:self.sectionNameKeyPath];
|
||||
for (NSArray *sectionOfObjects in sectionedObjects) {
|
||||
NSUInteger sectionIndex = [sectionedObjects indexOfObject:sectionOfObjects];
|
||||
if (sectionIndex >= [self sectionCount]) {
|
||||
[self addSection:[RKTableSection section]];
|
||||
}
|
||||
[self loadObjects:sectionOfObjects inSection:sectionIndex];
|
||||
}
|
||||
} else {
|
||||
[self loadObjects:objects inSection:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reloadRowForObject:(id)object withRowAnimation:(UITableViewRowAnimation)rowAnimation {
|
||||
// TODO: Find the indexPath of the object...
|
||||
NSIndexPath *indexPath = [self indexPathForObject:object];
|
||||
if (indexPath) {
|
||||
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:rowAnimation];
|
||||
|
||||
@@ -472,6 +472,12 @@
|
||||
2516112E1456F5520060A5C5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2516112D1456F5520060A5C5 /* CoreData.framework */; };
|
||||
251611301456F5590060A5C5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2516112F1456F5590060A5C5 /* Security.framework */; };
|
||||
251611321456F56C0060A5C5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 251611311456F56C0060A5C5 /* MobileCoreServices.framework */; };
|
||||
252A202D153471380078F8AD /* NSArray+RKAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 252A202B153471380078F8AD /* NSArray+RKAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
252A202E153471380078F8AD /* NSArray+RKAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 252A202C153471380078F8AD /* NSArray+RKAdditions.m */; };
|
||||
252A2030153471470078F8AD /* NSArray+RKAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 252A202C153471380078F8AD /* NSArray+RKAdditions.m */; };
|
||||
252A20311534714D0078F8AD /* NSArray+RKAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 252A202B153471380078F8AD /* NSArray+RKAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
252A2034153477870078F8AD /* NSArray+RKAdditionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 252A2033153477870078F8AD /* NSArray+RKAdditionsTest.m */; };
|
||||
252A2035153477870078F8AD /* NSArray+RKAdditionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 252A2033153477870078F8AD /* NSArray+RKAdditionsTest.m */; };
|
||||
252EFAFA14D8EAEC004863C8 /* RKEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 252EFAF914D8EAEC004863C8 /* RKEvent.m */; };
|
||||
252EFAFB14D8EAEC004863C8 /* RKEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 252EFAF914D8EAEC004863C8 /* RKEvent.m */; };
|
||||
252EFB0814D98F4D004863C8 /* RKSearchableManagedObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 252EFB0614D98F4D004863C8 /* RKSearchableManagedObjectTest.m */; };
|
||||
@@ -1007,6 +1013,9 @@
|
||||
2516112D1456F5520060A5C5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
2516112F1456F5590060A5C5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
251611311456F56C0060A5C5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
|
||||
252A202B153471380078F8AD /* NSArray+RKAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+RKAdditions.h"; sourceTree = "<group>"; };
|
||||
252A202C153471380078F8AD /* NSArray+RKAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RKAdditions.m"; sourceTree = "<group>"; };
|
||||
252A2033153477870078F8AD /* NSArray+RKAdditionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RKAdditionsTest.m"; sourceTree = "<group>"; };
|
||||
252EFAF814D8EAEC004863C8 /* RKEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKEvent.h; sourceTree = "<group>"; };
|
||||
252EFAF914D8EAEC004863C8 /* RKEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKEvent.m; sourceTree = "<group>"; };
|
||||
252EFAFC14D8EB30004863C8 /* RKTestNotificationObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RKTestNotificationObserver.h; path = Testing/RKTestNotificationObserver.h; sourceTree = "<group>"; };
|
||||
@@ -1495,6 +1504,8 @@
|
||||
25B6E95714CF7A1C00B1E881 /* RKErrors.m */,
|
||||
252EFB1914D9A7CB004863C8 /* NSBundle+RKAdditions.h */,
|
||||
252EFB1A14D9A7CB004863C8 /* NSBundle+RKAdditions.m */,
|
||||
252A202B153471380078F8AD /* NSArray+RKAdditions.h */,
|
||||
252A202C153471380078F8AD /* NSArray+RKAdditions.m */,
|
||||
);
|
||||
path = Support;
|
||||
sourceTree = "<group>";
|
||||
@@ -1891,6 +1902,7 @@
|
||||
251610551456F2330060A5C5 /* RKJSONParserJSONKitTest.m */,
|
||||
251610561456F2330060A5C5 /* RKPathMatcherTest.m */,
|
||||
251610571456F2330060A5C5 /* RKXMLParserTest.m */,
|
||||
252A2033153477870078F8AD /* NSArray+RKAdditionsTest.m */,
|
||||
);
|
||||
name = Support;
|
||||
path = Logic/Support;
|
||||
@@ -2198,6 +2210,7 @@
|
||||
257ABAB015112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.h in Headers */,
|
||||
257ABAB61511371E00CCAA76 /* NSManagedObject+RKAdditions.h in Headers */,
|
||||
25079C6F151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */,
|
||||
252A202D153471380078F8AD /* NSArray+RKAdditions.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2318,6 +2331,7 @@
|
||||
257ABAB115112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.h in Headers */,
|
||||
257ABAB71511371E00CCAA76 /* NSManagedObject+RKAdditions.h in Headers */,
|
||||
25079C70151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */,
|
||||
252A20311534714D0078F8AD /* NSArray+RKAdditions.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2717,6 +2731,7 @@
|
||||
257ABAB215112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.m in Sources */,
|
||||
257ABAB81511371E00CCAA76 /* NSManagedObject+RKAdditions.m in Sources */,
|
||||
25079C71151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */,
|
||||
252A202E153471380078F8AD /* NSArray+RKAdditions.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2800,6 +2815,7 @@
|
||||
25E36E0215195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */,
|
||||
25079C76151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */,
|
||||
25DB7508151BD551009F01AF /* NSManagedObject+ActiveRecordTest.m in Sources */,
|
||||
252A2034153477870078F8AD /* NSArray+RKAdditionsTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2897,6 +2913,7 @@
|
||||
257ABAB91511371E00CCAA76 /* NSManagedObject+RKAdditions.m in Sources */,
|
||||
25079C72151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */,
|
||||
250B849E152B6F63002581F9 /* RKObjectMappingProvider+CoreData.m in Sources */,
|
||||
252A2030153471470078F8AD /* NSArray+RKAdditions.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2980,6 +2997,7 @@
|
||||
25E36E0315195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */,
|
||||
25079C77151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */,
|
||||
25DB7509151BD551009F01AF /* NSManagedObject+ActiveRecordTest.m in Sources */,
|
||||
252A2035153477870078F8AD /* NSArray+RKAdditionsTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -111,6 +111,13 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
252A204215347F0B0078F8AD /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 253B489814E341C500B0483F /* RestKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 259C301615128079003066A2;
|
||||
remoteInfo = RestKitResources;
|
||||
};
|
||||
253B488514E3415800B0483F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 253B485614E3415800B0483F /* Project object */;
|
||||
@@ -153,13 +160,6 @@
|
||||
remoteGlobalIDString = 25160D1514564E810060A5C5;
|
||||
remoteInfo = RestKit;
|
||||
};
|
||||
25A41055152F23990098D0D0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 253B489814E341C500B0483F /* RestKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 259C301615128079003066A2;
|
||||
remoteInfo = RestKitResources;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -434,7 +434,7 @@
|
||||
253B48A514E341C500B0483F /* RestKitTests.octest */,
|
||||
253B48A714E341C500B0483F /* RestKit.framework */,
|
||||
253B48A914E341C500B0483F /* RestKitFrameworkTests.octest */,
|
||||
25A41056152F23990098D0D0 /* RestKitResources.bundle */,
|
||||
252A204315347F0B0078F8AD /* RestKitResources.bundle */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -734,6 +734,13 @@
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
252A204315347F0B0078F8AD /* RestKitResources.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = RestKitResources.bundle;
|
||||
remoteRef = 252A204215347F0B0078F8AD /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
253B48A314E341C500B0483F /* libRestKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@@ -762,13 +769,6 @@
|
||||
remoteRef = 253B48A814E341C500B0483F /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
25A41056152F23990098D0D0 /* RestKitResources.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = RestKitResources.bundle;
|
||||
remoteRef = 25A41055152F23990098D0D0 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
|
||||
@@ -798,6 +798,32 @@
|
||||
RKLogCritical(@"PENDING - Undefined Behavior!!!");
|
||||
}
|
||||
|
||||
- (void)testLoadCollectionOfObjectsAndMapThemIntoSections {
|
||||
RKObjectManager* objectManager = [RKTestFactory objectManager];
|
||||
objectManager.client.cachePolicy = RKRequestCachePolicyNone;
|
||||
RKTableControllerTestTableViewController* viewController = [RKTableControllerTestTableViewController new];
|
||||
RKTableController* tableController = [RKTableController tableControllerForTableViewController:viewController];
|
||||
tableController.objectManager = objectManager;
|
||||
[tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping* mapping) {
|
||||
mapping.cellClass = [RKTestUserTableViewCell class];
|
||||
[mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"];
|
||||
[mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"];
|
||||
}]];
|
||||
tableController.sectionNameKeyPath = @"name";
|
||||
RKTestTableControllerDelegate* delegate = [RKTestTableControllerDelegate tableControllerDelegate];
|
||||
delegate.timeout = 10;
|
||||
tableController.delegate = delegate;
|
||||
[tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader* objectLoader) {
|
||||
objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping* mapping) {
|
||||
[mapping mapAttributes:@"name", nil];
|
||||
}];
|
||||
}];
|
||||
[delegate waitForLoad];
|
||||
assertThatBool([tableController isLoaded], is(equalToBool(YES)));
|
||||
assertThatInt(tableController.sectionCount, is(equalToInt(3)));
|
||||
assertThatInt(tableController.rowCount, is(equalToInt(3)));
|
||||
}
|
||||
|
||||
#pragma mark - RKTableViewDelegate specs
|
||||
|
||||
- (void)testNotifyTheDelegateWhenLoadingStarts {
|
||||
@@ -1594,11 +1620,12 @@
|
||||
RKTableController* tableController = [RKTableController tableControllerForTableViewController:viewController];
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
__block BOOL dispatched = NO;
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) {
|
||||
cellMapping.onTapAccessoryButtonForObjectAtIndexPath = ^(UITableViewCell* cell, id object, NSIndexPath* indexPath) {
|
||||
dispatched = YES;
|
||||
};
|
||||
}];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping];
|
||||
[tableController tableView:tableController.tableView accessoryButtonTappedForRowWithIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThatBool(dispatched, is(equalToBool(YES)));
|
||||
}
|
||||
@@ -1608,11 +1635,12 @@
|
||||
RKTableController* tableController = [RKTableController tableControllerForTableViewController:viewController];
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
NSString* deleteTitle = @"Delete Me";
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) {
|
||||
cellMapping.titleForDeleteButtonForObjectAtIndexPath = ^ NSString*(UITableViewCell* cell, id object, NSIndexPath* indexPath) {
|
||||
return deleteTitle;
|
||||
};
|
||||
}];
|
||||
}];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping];
|
||||
NSString* delegateTitle = [tableController tableView:tableController.tableView
|
||||
titleForDeleteConfirmationButtonForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThat(delegateTitle, is(equalTo(deleteTitle)));
|
||||
@@ -1623,11 +1651,12 @@
|
||||
RKTableController* tableController = [RKTableController tableControllerForTableViewController:viewController];
|
||||
tableController.canEditRows = YES;
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) {
|
||||
cellMapping.editingStyleForObjectAtIndexPath = ^ UITableViewCellEditingStyle(UITableViewCell* cell, id object, NSIndexPath* indexPath) {
|
||||
return UITableViewCellEditingStyleInsert;
|
||||
};
|
||||
}];
|
||||
}];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping];
|
||||
UITableViewCellEditingStyle delegateStyle = [tableController tableView:tableController.tableView
|
||||
editingStyleForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThatInt(delegateStyle, is(equalToInt(UITableViewCellEditingStyleInsert)));
|
||||
@@ -1639,11 +1668,11 @@
|
||||
tableController.canMoveRows = YES;
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
NSIndexPath* moveToIndexPath = [NSIndexPath indexPathForRow:2 inSection:0];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
cellMapping.targetIndexPathForMove = ^ NSIndexPath*(UITableViewCell* cell, id object, NSIndexPath* sourceIndexPath, NSIndexPath* destinationIndexPath) {
|
||||
return moveToIndexPath;
|
||||
};
|
||||
}];
|
||||
}]];
|
||||
NSIndexPath* delegateIndexPath = [tableController tableView:tableController.tableView
|
||||
targetIndexPathForMoveFromRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]toProposedIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
|
||||
assertThat(delegateIndexPath, is(equalTo(moveToIndexPath)));
|
||||
@@ -1657,9 +1686,9 @@
|
||||
tableController.variableHeightRows = NO;
|
||||
tableController.tableView.rowHeight = 55;
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
cellMapping.rowHeight = 200;
|
||||
}];
|
||||
}]];
|
||||
CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThatFloat(height, is(equalToFloat(55)));
|
||||
}
|
||||
@@ -1670,9 +1699,9 @@
|
||||
tableController.variableHeightRows = YES;
|
||||
tableController.tableView.rowHeight = 55;
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
cellMapping.rowHeight = 200;
|
||||
}];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
cellMapping.rowHeight = 200;
|
||||
}]];
|
||||
CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThatFloat(height, is(equalToFloat(200)));
|
||||
}
|
||||
@@ -1683,10 +1712,10 @@
|
||||
tableController.variableHeightRows = YES;
|
||||
tableController.tableView.rowHeight = 55;
|
||||
RKTableItem* tableItem = [RKTableItem tableItem];
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMappingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
[tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping* cellMapping) {
|
||||
cellMapping.rowHeight = 200;
|
||||
cellMapping.heightOfCellForObjectAtIndexPath = ^ CGFloat(id object, NSIndexPath* indexPath) { return 150; };
|
||||
}];
|
||||
}]];
|
||||
CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
assertThatFloat(height, is(equalToFloat(150)));
|
||||
}
|
||||
|
||||
59
Tests/Logic/Support/NSArray+RKAdditionsTest.m
Normal file
59
Tests/Logic/Support/NSArray+RKAdditionsTest.m
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// NSArray+RKAdditionsTest.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 4/10/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "NSArray+RKAdditions.h"
|
||||
#import "RKTestUser.h"
|
||||
|
||||
@interface NSArray_RKAdditionsTest : RKTestCase
|
||||
@end
|
||||
|
||||
@implementation NSArray_RKAdditionsTest
|
||||
|
||||
#pragma mark - sectionsGroupedByKeyPath Tests
|
||||
|
||||
- (void)testReturnsEmptyArrayWhenGroupingEmptyArray
|
||||
{
|
||||
NSArray *objects = [NSArray array];
|
||||
assertThat([objects sectionsGroupedByKeyPath:@"whatever"], is(empty()));
|
||||
}
|
||||
|
||||
- (void)testReturnsSingleSectionWhenGroupingSingleObject
|
||||
{
|
||||
RKTestUser *user = [RKTestUser new];
|
||||
user.name = @"Blake";
|
||||
user.country = @"USA";
|
||||
NSArray *users = [NSArray arrayWithObject:user];
|
||||
|
||||
NSArray *sections = [users sectionsGroupedByKeyPath:@"country"];
|
||||
assertThat(sections, hasCountOf(1));
|
||||
}
|
||||
|
||||
- (void)testReturnsTwoSectionsWhenGroupingThreeObjectsWithTwoUniqueValues
|
||||
{
|
||||
RKTestUser *user1 = [RKTestUser new];
|
||||
user1.name = @"Blake";
|
||||
user1.country = @"USA";
|
||||
|
||||
RKTestUser *user2 = [RKTestUser new];
|
||||
user2.name = @"Colin";
|
||||
user2.country = @"USA";
|
||||
|
||||
RKTestUser *user3 = [RKTestUser new];
|
||||
user3.name = @"Pepe";
|
||||
user3.country = @"Spain";
|
||||
|
||||
NSArray *users = [NSArray arrayWithObjects:user1, user2, user3, nil];
|
||||
|
||||
NSArray *sections = [users sectionsGroupedByKeyPath:@"country"];
|
||||
assertThat(sections, hasCountOf(2));
|
||||
assertThat([sections objectAtIndex:0], contains(user1, user2, nil));
|
||||
assertThat([sections objectAtIndex:1], contains(user3, nil));
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -36,10 +36,15 @@
|
||||
// to determine if assocation values should be set
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if ([object isKindOfClass:[RKTestUser class]]) {
|
||||
return [[(RKTestUser*)object userID] isEqualToNumber:self.userID];
|
||||
} else {
|
||||
return NO;
|
||||
if ([(RKTestUser*)object userID] == nil && self.userID == nil) {
|
||||
// No primary key -- consult superclass
|
||||
return [super isEqual:object];
|
||||
} else {
|
||||
return [[(RKTestUser*)object userID] isEqualToNumber:self.userID];
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)valueForUndefinedKey:(NSString *)key {
|
||||
|
||||
Reference in New Issue
Block a user