Eliminate RKForm

This commit is contained in:
Blake Watters
2012-08-28 13:45:48 -04:00
parent 6b1e9fa071
commit d825a8f182
12 changed files with 0 additions and 1009 deletions

View File

@@ -1,45 +0,0 @@
//
// RKControlTableItem.h
// RestKit
//
// Created by Blake Watters on 8/22/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 "RKTableItem.h"
// TODO: Add note that any cell class used with an RKControlTableItem
// must have a control property to be auto-linked to the control in the table item
@interface RKControlTableItem : RKTableItem
@property (nonatomic, retain) UIControl *control;
/** @name Convenience Accessors */
@property (nonatomic, readonly) UIButton *button;
@property (nonatomic, readonly) UITextField *textField;
@property (nonatomic, readonly) UISwitch *switchControl;
@property (nonatomic, readonly) UISlider *slider;
@property (nonatomic, readonly) UILabel *label;
+ (id)tableItemWithControl:(UIControl *)control;
/**
Return the value from the control as an object. This will wrap
any primitive values into an appropriate object for use in mapping.
*/
- (id)controlValue;
@end

View File

@@ -1,113 +0,0 @@
//
// RKControlTableItem.m
// RestKit
//
// Created by Blake Watters on 8/22/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 "RKControlTableItem.h"
#import "RKTableViewCellMapping.h"
#import "RKControlTableViewCell.h"
@implementation RKControlTableItem
@synthesize control = _control;
+ (id)tableItemWithControl:(UIControl *)control
{
RKControlTableItem *tableItem = [self tableItem];
tableItem.control = control;
return tableItem;
}
- (id)init
{
self = [super init];
if (self) {
self.cellMapping.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellMapping.accessoryType = UITableViewCellAccessoryNone;
self.cellMapping.cellClass = [RKControlTableViewCell class];
// Link the UITableViewCell for this table item with the control
[self.cellMapping addPrepareCellBlock:^(UITableViewCell *cell) {
if ([cell respondsToSelector:@selector(setControl:)]) {
[cell setValue:self.control forKey:@"control"];
}
}];
}
return self;
}
- (void)dealloc
{
[_control release];
[super dealloc];
}
- (void)setControl:(UIControl *)control
{
NSAssert(control, @"Cannot add a nil control to a RKControlTableItem");
[control retain];
[_control release];
_control = control;
}
#pragma mark - Convenience Accessors
- (UIButton *)button
{
return ([self.control isKindOfClass:[UIButton class]]) ? (UIButton *)self.control : nil;
}
- (UITextField *)textField
{
return ([self.control isKindOfClass:[UITextField class]]) ? (UITextField *)self.control : nil;
}
- (UISwitch *)switchControl
{
return ([self.control isKindOfClass:[UISwitch class]]) ? (UISwitch *)self.control : nil;
}
- (UISlider *)slider
{
return ([self.control isKindOfClass:[UISlider class]]) ? (UISlider *)self.control : nil;
}
- (UILabel *)label
{
return ([self.control isKindOfClass:[UILabel class]]) ? (UILabel *)self.control : nil;
}
// TODO: What if we replace this with a protocol that enables KVC
// via the 'controlValue' property for the common types to allow pluggability?
- (id)controlValue
{
if ([self.control isKindOfClass:[UIButton class]]) {
return nil;
} else if ([self.control isKindOfClass:[UITextField class]]) {
return self.textField.text;
} else if ([self.control isKindOfClass:[UISlider class]]) {
return [NSNumber numberWithFloat:self.slider.value];
} else if ([self.control isKindOfClass:[UISwitch class]]) {
return [NSNumber numberWithBool:self.switchControl.isOn];
}
return nil;
}
@end

View File

@@ -1,27 +0,0 @@
//
// RKControlTableViewCell.h
// RestKit
//
// Created by Blake Watters on 8/24/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 <UIKit/UIKit.h>
@interface RKControlTableViewCell : UITableViewCell
@property (nonatomic, retain) UIControl *control;
@end

View File

@@ -1,48 +0,0 @@
//
// RKControlTableViewCell.m
// RestKit
//
// Created by Blake Watters on 8/24/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 "RKControlTableViewCell.h"
@implementation RKControlTableViewCell
@synthesize control;
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.control.superview != self.contentView) {
[self.control removeFromSuperview];
[self.contentView addSubview:self.control];
}
// If the control has not been sized, we assume you want it to
// take up the entire row of space
if (!self.control.frame.size.height) {
[self.control sizeToFit];
CGFloat contentWidth = self.contentView.frame.size.width;
CGFloat contentHeight = self.contentView.frame.size.height;
CGFloat controlHeight = self.control.frame.size.height;
self.control.frame = CGRectMake(8, floor(contentHeight/2 - controlHeight/2),
contentWidth - 8, controlHeight);
}
}
@end

View File

@@ -1,117 +0,0 @@
//
// RKForm.h
// RestKit
//
// Created by Blake Watters on 8/22/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 <UIKit/UIKit.h>
#import "RKControlTableItem.h"
typedef enum {
// RKFormControlTypeAutodetect, // TODO: Might be nice to support auto-selection of control type
RKFormControlTypeTextField,
RKFormControlTypeTextFieldSecure,
RKFormControlTypeSwitch,
RKFormControlTypeSlider,
RKFormControlTypeLabel,
RKFormControlTypeUnknown = 1000
} RKFormControlType;
typedef void(^RKFormBlock)();
@class RKTableController;
@class RKFormSection;
@interface RKForm : NSObject {
@private
NSMutableArray *_sections;
NSMutableArray *_observedAttributes;
}
/**
The object we are constructing a form for
*/
@property (nonatomic, readonly) id object;
// The table view we are bound to. not retained.
@property (nonatomic, readonly) RKTableController *tableController;
//@property (nonatomic, assign) id delegate;
@property (nonatomic, copy) RKFormBlock onSubmit;
// delegates...
// formDidSumbit, formWillSubmit, formWillValidate, formDidValidateSuccessfully, formDidFailValidation:withErrors:
+ (id)formForObject:(id)object;
+ (id)formForObject:(id)object usingBlock:(void (^)(RKForm *form))block;
- (id)initWithObject:(id)object;
/** @name Table Item Management */
@property (nonatomic, readonly) NSArray *sections;
@property (nonatomic, readonly) NSArray *tableItems;
- (void)addSection:(RKFormSection *)section;
- (void)addSectionUsingBlock:(void (^)(RKFormSection *section))block; // TODO: Eliminate this signature...
/** @name Single Section Forms */
/**
Adds a specific table item to the form
*/
- (void)addTableItem:(RKTableItem *)tableItem; // TODO: maybe addRowWithTableItem???
/** @name Key Path to Control Mapping */
// TODO: All of these method signatures should be carefully evaluated...
// TODO: Consider renaming to addControlForAttribute: | addControlTableItemForAttribute:
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType;
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType usingBlock:(void (^)(RKControlTableItem *tableItem))block;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control usingBlock:(void (^)(RKControlTableItem *tableItem))block;
// TODO: Should there be a flavor that accepts UIView *and yields an RKTableItem? This would avoid needing to cast to (UIControl *)
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass usingBlock:(void (^)(RKTableItem *tableItem))block;
- (RKTableItem *)tableItemForAttribute:(NSString *)attributeKeyPath;
- (RKControlTableItem *)controlTableItemForAttribute:(NSString *)attributeKeyPath;
- (UIControl *)controlForAttribute:(NSString *)attributeKeyPath;
/** @name Actions */
// serializes the values back out of the form and into the object...
- (BOOL)commitValuesToObject; // TODO: Better method signature??? mapFormToObject..
/**
Submits the form b
*/
- (void)submit;
/**
Validates the object state as represented in the form. Returns
YES if the object is state if valid.
*/
// TODO: Implement me...
//- (BOOL)validate:(NSArray**)errors;
- (void)willLoadInTableController:(RKTableController *)tableController;
- (void)didLoadInTableController:(RKTableController *)tableController;
// Sent from the form section
- (void)formSection:(RKFormSection *)formSection didAddTableItem:(RKTableItem *)tableItem forAttributeAtKeyPath:(NSString *)attributeKeyPath;
@end

View File

@@ -1,345 +0,0 @@
//
// RKForm.m
// RestKit
//
// Created by Blake Watters on 8/22/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 "RKForm.h"
#import "RKFormSection.h"
#import "RKTableViewCellMapping.h"
#import "RKTableController.h"
#import "RKMappingOperation.h"
#import "RKLog.h"
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent lcl_cRestKitUI
@interface RKForm (Private)
- (void)removeObserverForAttributes;
@end
@implementation RKForm
@synthesize tableController = _tableController;
@synthesize object = _object;
@synthesize onSubmit = _onSubmit;
+ (id)formForObject:(id)object
{
return [[[self alloc] initWithObject:object] autorelease];
}
+ (id)formForObject:(id)object usingBlock:(void (^)(RKForm *))block
{
id form = [self formForObject:object];
if (block) block(form);
return form;
}
- (id)initWithObject:(id)object
{
if (! object) {
[NSException raise:NSInvalidArgumentException format:@"%@ - cannot initialize a form with a nil object",
NSStringFromSelector(_cmd)];
}
self = [self init];
if (self) {
_object = [object retain];
if ([_object isKindOfClass:[NSManagedObject class]]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reloadObjectOnContextDidSaveNotification:)
name:NSManagedObjectContextDidSaveNotification
object:[(NSManagedObject *)_object managedObjectContext]];
}
}
return self;
}
- (id)init
{
self = [super init];
if (self) {
_sections = [NSMutableArray new];
_observedAttributes = [NSMutableArray new];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self removeObserverForAttributes];
_tableController = nil;
[_object release];
[_sections release];
[_observedAttributes release];
Block_release(_onSubmit);
[super dealloc];
}
- (void)addSection:(RKFormSection *)section
{
[_sections addObject:section];
}
- (void)addSectionUsingBlock:(void (^)(RKFormSection *section))block
{
RKFormSection *section = [RKFormSection sectionInForm:self];
block(section);
[self addSection:section];
}
#pragma mark - Table Item Management
- (NSArray *)sections
{
return [NSArray arrayWithArray:_sections];
}
- (RKFormSection *)returnOrInstantiateFirstSection
{
if ([_sections count] > 0) {
return [_sections objectAtIndex:0];
}
RKFormSection *section = [RKFormSection sectionInForm:self];
[self addSection:section];
return section;
}
- (NSArray *)tableItems
{
NSMutableArray *tableItems = [NSMutableArray array];
for (RKFormSection *section in _sections) {
[tableItems addObjectsFromArray:section.objects];
}
return [NSArray arrayWithArray:tableItems];
}
#pragma mark - Proxies for Section 0
- (void)addTableItem:(RKTableItem *)tableItem
{
[[self returnOrInstantiateFirstSection] addTableItem:tableItem];
}
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType usingBlock:(void (^)(RKControlTableItem *tableItem))block
{
[[self returnOrInstantiateFirstSection] addRowForAttribute:attributeKeyPath withControlType:controlType usingBlock:block];
}
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType
{
[self addRowForAttribute:attributeKeyPath withControlType:controlType usingBlock:nil];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control usingBlock:(void (^)(RKControlTableItem *tableItem))block
{
[[self returnOrInstantiateFirstSection] addRowMappingAttribute:attributeKeyPath toKeyPath:controlKeyPath onControl:control usingBlock:block];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control
{
[self addRowMappingAttribute:attributeKeyPath toKeyPath:controlKeyPath onControl:control usingBlock:nil];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass usingBlock:(void (^)(RKTableItem *tableItem))block
{
[[self returnOrInstantiateFirstSection] addRowMappingAttribute:attributeKeyPath toKeyPath:cellKeyPath onCellWithClass:cellClass usingBlock:block];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass
{
[self addRowMappingAttribute:attributeKeyPath toKeyPath:cellKeyPath onCellWithClass:cellClass usingBlock:nil];
}
- (RKTableItem *)tableItemForAttribute:(NSString *)attributeKeyPath
{
for (RKTableItem *tableItem in self.tableItems) {
if ([[tableItem.userData valueForKey:@"__RestKit__attributeKeyPath"] isEqualToString:attributeKeyPath]) {
return tableItem;
}
}
return nil;
}
- (RKControlTableItem *)controlTableItemForAttribute:(NSString *)attributeKeyPath
{
RKTableItem *tableItem = [self tableItemForAttribute:attributeKeyPath];
return [tableItem isKindOfClass:[RKControlTableItem class]] ? (RKControlTableItem *)tableItem : nil;
}
- (UIControl *)controlForAttribute:(NSString *)attributeKeyPath
{
RKControlTableItem *tableItem = [self controlTableItemForAttribute:attributeKeyPath];
return tableItem.control;
}
#pragma mark - Actions
// TODO: This needs thorough unit testing...
/**
TODO: There is an alternate approach for the implementation here. What we may want to do instead of tracking
the mapping like this is use KVO on the control and/or table cells that are tracking attributes and maintain an internal
dictionary of the attribute names -> values currently set on the controls. We would then just fire up the mapping operation
instead of doing this. It may be cleaner...
*/
- (BOOL)commitValuesToObject
{
// Serialize the data out of the form
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[self.object class]];
NSMutableDictionary *controlValues = [NSMutableDictionary dictionaryWithCapacity:[self.tableItems count]];
for (RKTableItem *tableItem in self.tableItems) {
RKAttributeMapping *controlMapping = [tableItem.userData objectForKey:@"__RestKit__attributeToControlMapping"];
if (controlMapping) {
id controlValue = nil;
NSString *attributeKeyPath = attributeKeyPath = [controlMapping.sourceKeyPath stringByReplacingOccurrencesOfString:@"userData.__RestKit__object." withString:@""];
NSString *controlValueKeyPath = controlMapping.destinationKeyPath;
// TODO: Another informal protocol. Document me...
if ([tableItem isKindOfClass:[RKControlTableItem class]]) {
// Get the value out of the control and store it on the dictionary
controlValue = [tableItem performSelector:@selector(controlValue)];
if (! controlValue) {
RKLogTrace(@"Unable to directly fetch controlValue from table item. Asking tableItem for valueForKeyPath: %@", controlValueKeyPath);
controlValue = [tableItem valueForKeyPath:controlValueKeyPath];
}
} else {
// We are not a control cell, so we need to get the value directly from the table cell
UITableViewCell *cell = [self.tableController cellForObject:tableItem];
NSAssert(cell, @"Attempted to serialize value out of nil table cell");
NSAssert([cell isKindOfClass:[UITableViewCell class]], @"Expected cellForObject to return a UITableViewCell, but got a %@", NSStringFromClass([cell class]));
RKLogTrace(@"Asking cell %@ for valueForKeyPath:%@", cell, controlValueKeyPath);
controlValue = [cell valueForKeyPath:controlValueKeyPath];
}
RKLogTrace(@"Extracted form value for attribute '%@': %@", attributeKeyPath, controlValue);
if (controlValue) {
[controlValues setValue:controlValue forKey:attributeKeyPath];
}
[objectMapping mapAttributes:attributeKeyPath, nil];
} else {
// TODO: Logging!!
}
}
RKLogTrace(@"Object mapping form state into target object '%@' with values: %@", self.object, controlValues);
objectMapping.performKeyValueValidation = NO; // TODO: Temporary...
RKMappingOperation *operation = [RKMappingOperation mappingOperationFromObject:controlValues toObject:self.object withMapping:objectMapping];
NSError *error = nil;
BOOL success = [operation performMapping:&error];
if (!success) {
RKLogWarning(@"Serialization to the target object failed with error: %@", error);
}
return success;
}
- (void)submit
{
if ([self commitValuesToObject]) {
// TODO: Add validations?
if (self.onSubmit) self.onSubmit();
} else {
// TODO: What to do...
}
}
- (void)validate
{
// TODO: Implement me at some point...
}
#pragma mark - Subclass Hooks
- (void)willLoadInTableController:(RKTableController *)tableController
{
}
- (void)didLoadInTableController:(RKTableController *)tableController
{
_tableController = tableController;
}
#pragma mark - Key Value Observing
- (void)addObserverForAttribute:(NSString *)attributeKeyPath
{
if (! [_observedAttributes containsObject:attributeKeyPath]) {
[self.object addObserver:self forKeyPath:attributeKeyPath options:NSKeyValueObservingOptionNew context:nil];
[_observedAttributes addObject:attributeKeyPath];
}
}
- (void)removeObserverForAttribute:(NSString *)attributeKeyPath
{
if ([_observedAttributes containsObject:attributeKeyPath]) {
[self.object removeObserver:self forKeyPath:attributeKeyPath];
[_observedAttributes removeObject:attributeKeyPath];
}
}
- (void)removeObserverForAttributes
{
for (NSString *keyPath in _observedAttributes) { [self.object removeObserver:self forKeyPath:keyPath]; };
[_observedAttributes removeAllObjects];
}
- (void)formSection:(RKFormSection *)formSection didAddTableItem:(RKTableItem *)tableItem forAttributeAtKeyPath:(NSString *)attributeKeyPath
{
[self addObserverForAttribute:attributeKeyPath];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSAssert(object == self.object, @"Received unexpected KVO message for object that form is not bound to: %@", object);
RKLogTrace(@"Received KVO message for keyPath (%@) for object (%@)", keyPath, object);
// TODO: We should use a notification to tell the table view about the attribute change.
// I don't like that the form knows about the tableController...
// TODO: Need to let you configure the row animations...
RKTableItem *tableItem = [self tableItemForAttribute:keyPath];
[self.tableController reloadRowForObject:tableItem withRowAnimation:UITableViewRowAnimationFade];
}
- (void)reloadObjectOnContextDidSaveNotification:(NSNotification *)notification
{
NSManagedObjectContext *context = (NSManagedObjectContext *)notification.object;
NSSet *deletedObjects = [notification.userInfo objectForKey:NSDeletedObjectsKey];
NSSet *updatedObjects = [notification.userInfo objectForKey:NSUpdatedObjectsKey];
if ([deletedObjects containsObject:self.object]) {
RKLogWarning(@"Object was deleted while being display in a RKForm. Interface may no longer function as expected.");
[self removeObserverForAttributes];
[_object release];
_object = nil;
} else if ([updatedObjects containsObject:self.object]) {
RKLogDebug(@"Object was updated while being displayed in a RKForm. Refreshing...");
[context refreshObject:_object mergeChanges:YES];
}
}
@end

View File

@@ -1,49 +0,0 @@
//
// RKFormSection.h
// RestKit
//
// Created by Blake Watters on 8/23/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 "RKTableSection.h"
#import "RKForm.h"
@interface RKFormSection : RKTableSection
@property (nonatomic, assign) RKForm *form;
@property (nonatomic, readonly) id object;
+ (id)sectionInForm:(RKForm *)form;
+ (id)sectionUsingBlock:(void (^)(RKFormSection *))block;
- (id)initWithForm:(RKForm *)form;
- (void)addTableItem:(RKTableItem *)tableItem;
// TODO: We could get rid of the block forms and just pass nil?
// TODO: These should probably be addTableItem for clarity???
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType;
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType usingBlock:(void (^)(RKControlTableItem *tableItem))block;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control usingBlock:(void (^)(RKControlTableItem *tableItem))block;
// Map an attribute to a keyPath on a particular cell class
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass;
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass usingBlock:(void (^)(RKTableItem *tableItem))block;
- (void)addMappingFromAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)keyPath forTableItem:(RKTableItem *)tableItem;
@end

View File

@@ -1,187 +0,0 @@
//
// RKFormSection.m
// RestKit
//
// Created by Blake Watters on 8/23/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 "RKFormSection.h"
@implementation RKFormSection
@synthesize form = _form;
+ (id)sectionInForm:(RKForm *)form
{
return [[[self alloc] initWithForm:form] autorelease];
}
+ (id)sectionUsingBlock:(void (^)(RKFormSection *))block
{
RKFormSection *section = [self section];
block(section);
return section;
}
- (id)initWithForm:(RKForm *)form {
self = [super init];
if (self) {
self.form = form;
}
return self;
}
- (id)object
{
return self.form.object;
}
- (void)addTableItem:(RKTableItem *)tableItem
{
// We assume if you haven't configured any mappings by
// the time the item is added to the section, you probably want the defaults
if ([tableItem.cellMapping.attributeMappings count] == 0) {
[tableItem.cellMapping addDefaultMappings];
}
// TODO: WTF? _objects is declared @protected but using _objects here fails to build...
[(NSMutableArray *)self.objects addObject:tableItem];
}
- (UIControl *)controlWithType:(RKFormControlType)controlType
{
UIControl *control = nil;
switch (controlType) {
case RKFormControlTypeTextField:
case RKFormControlTypeTextFieldSecure:;
UITextField *textField = [[[UITextField alloc] init] autorelease];
textField.secureTextEntry = (controlType == RKFormControlTypeTextFieldSecure);
control = (UIControl *)textField;
break;
case RKFormControlTypeSwitch:;
control = [(UIControl *)[UISwitch new] autorelease];
break;
case RKFormControlTypeSlider:;
control = [(UIControl *)[UISlider new] autorelease];
break;
case RKFormControlTypeLabel:;
control = [(UIControl *)[UILabel new] autorelease];
break;
case RKFormControlTypeUnknown:
default:
break;
}
control.backgroundColor = [UIColor clearColor];
return control;
}
- (NSString *)keyPathForControl:(UIControl *)control
{
if ([control isKindOfClass:[UITextField class]] ||
[control isKindOfClass:[UILabel class]]) {
return @"text";
} else if ([control isKindOfClass:[UISwitch class]]) {
return @"on";
} else if ([control isKindOfClass:[UISlider class]]) {
return @"value";
} else {
[NSException raise:NSInvalidArgumentException format:@"*** -[%@ %@]: unable to define mapping for control type %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), NSStringFromClass([control class])];
}
return nil;
}
- (void)addAttributeMapping:(RKAttributeMapping *)attributeMapping forKeyPath:(NSString *)attributeKeyPath toTableItem:(RKTableItem *)tableItem
{
[tableItem.cellMapping addAttributeMapping:attributeMapping];
// Use KVC storage to associate the table item with object being mapped
// TODO: Move these to constants...
[tableItem.userData setValue:self.object forKey:@"__RestKit__object"];
[tableItem.userData setValue:attributeKeyPath forKey:@"__RestKit__attributeKeyPath"];
[tableItem.userData setValue:attributeMapping forKey:@"__RestKit__attributeToControlMapping"];
[self.form formSection:self didAddTableItem:tableItem forAttributeAtKeyPath:attributeKeyPath];
[self addTableItem:tableItem];
}
- (void)addMappingFromAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)keyPath forTableItem:(RKTableItem *)tableItem
{
RKAttributeMapping *attributeMapping = [[RKAttributeMapping new] autorelease];
attributeMapping.sourceKeyPath = [NSString stringWithFormat:@"userData.__RestKit__object.%@", attributeKeyPath];
attributeMapping.destinationKeyPath = keyPath;
// TODO: This is duplicating code...
[tableItem.cellMapping addAttributeMapping:attributeMapping];
// Use KVC storage to associate the table item with object being mapped
// TODO: Move these to constants...
[tableItem.userData setValue:self.object forKey:@"__RestKit__object"];
[tableItem.userData setValue:attributeKeyPath forKey:@"__RestKit__attributeKeyPath"];
[tableItem.userData setValue:attributeMapping forKey:@"__RestKit__attributeToControlMapping"];
// [self addAttributeMapping:attributeMapping forKeyPath:attributeKeyPath toTableItem:tableItem];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control usingBlock:(void (^)(RKControlTableItem *tableItem))block {
RKControlTableItem *tableItem = [RKControlTableItem tableItemWithControl:control];
RKAttributeMapping *attributeMapping = [[RKAttributeMapping new] autorelease];
attributeMapping.sourceKeyPath = [NSString stringWithFormat:@"userData.__RestKit__object.%@", attributeKeyPath];
attributeMapping.destinationKeyPath = [NSString stringWithFormat:@"control.%@", controlKeyPath];
[self addAttributeMapping:attributeMapping forKeyPath:attributeKeyPath toTableItem:tableItem];
if (block) block(tableItem);
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)controlKeyPath onControl:(UIControl *)control
{
[self addRowMappingAttribute:attributeKeyPath toKeyPath:controlKeyPath onControl:control usingBlock:nil];
}
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType usingBlock:(void (^)(RKControlTableItem *tableItem))block
{
id control = [self controlWithType:controlType];
NSString *controlKeyPath = [self keyPathForControl:control];
[self addRowMappingAttribute:attributeKeyPath toKeyPath:controlKeyPath onControl:control usingBlock:block];
}
- (void)addRowForAttribute:(NSString *)attributeKeyPath withControlType:(RKFormControlType)controlType
{
[self addRowForAttribute:attributeKeyPath withControlType:controlType usingBlock:nil];
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass usingBlock:(void (^)(RKTableItem *tableItem))block
{
RKTableItem *tableItem = [RKTableItem tableItem];
tableItem.cellMapping.cellClass = cellClass;
RKAttributeMapping *attributeMapping = [[RKAttributeMapping new] autorelease];
attributeMapping.sourceKeyPath = [NSString stringWithFormat:@"userData.__RestKit__object.%@", attributeKeyPath];
attributeMapping.destinationKeyPath = cellKeyPath;
[self addAttributeMapping:attributeMapping forKeyPath:attributeKeyPath toTableItem:tableItem];
if (block) block(tableItem);
}
- (void)addRowMappingAttribute:(NSString *)attributeKeyPath toKeyPath:(NSString *)cellKeyPath onCellWithClass:(Class)cellClass
{
[self addRowMappingAttribute:attributeKeyPath toKeyPath:cellKeyPath onCellWithClass:cellClass usingBlock:nil];
}
@end

View File

@@ -24,7 +24,6 @@
#import "RKTableSection.h"
#import "RKTableViewCellMappings.h"
#import "RKTableItem.h"
#import "RKForm.h"
#import "RKObjectManager.h"
#import "RKObjectMapping.h"
#import "RKObjectLoader.h"
@@ -92,23 +91,6 @@
- (void)loadTableFromResourcePath:(NSString *)resourcePath;
- (void)loadTableFromResourcePath:(NSString *)resourcePath usingBlock:(void (^)(RKObjectLoader *objectLoader))block;
///-----------------------------------------------------------------------------
/** @name Forms */
///-----------------------------------------------------------------------------
/**
The form that the table has been loaded with (if any)
*/
@property (nonatomic, retain, readonly) RKForm *form;
/**
Loads the table with the contents of the specified form object.
Forms are used to build content entry and editing interfaces for objects.
@see RKForm
*/
- (void)loadForm:(RKForm *)form;
///-----------------------------------------------------------------------------
/// @name Managing Sections
///-----------------------------------------------------------------------------

View File

@@ -21,7 +21,6 @@
#import "RKTableController.h"
#import "RKAbstractTableController_Internals.h"
#import "RKLog.h"
#import "RKFormSection.h"
#import "NSArray+RKAdditions.h"
#import "RKMappingOperation.h"
#import "RKMappingOperationDataSource.h"
@@ -37,7 +36,6 @@
@implementation RKTableController
@dynamic delegate;
@synthesize form = _form;
@synthesize sectionNameKeyPath = _sectionNameKeyPath;
@synthesize sections = _sections;
@@ -63,7 +61,6 @@
- (void)dealloc
{
[self removeObserver:self forKeyPath:@"sections"];
[_form release];
[_sectionNameKeyPath release];
[_sections release];
@@ -268,28 +265,6 @@
[self loadTableWithObjectLoader:objectLoader];
}
#pragma mark - Forms
- (void)loadForm:(RKForm *)form
{
[form retain];
[_form release];
_form = form;
// The form replaces the content in the table
[self removeAllSections:NO];
[form willLoadInTableController:self];
for (RKFormSection *section in form.sections) {
NSUInteger sectionIndex = [form.sections indexOfObject:section];
section.objects = [self objectsWithHeaderAndFooters:section.objects forSection:sectionIndex];
[self addSection:(RKTableSection *)section];
}
[self didFinishLoad];
[form didLoadInTableController:self];
}
#pragma mark - UITableViewDataSource methods
- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

View File

@@ -24,10 +24,7 @@
#import "RKTableController.h"
#import "RKTableSection.h"
#import "RKTableItem.h"
#import "RKControlTableItem.h"
#import "RKFetchedResultsTableController.h"
#import "RKForm.h"
#import "RKFormSection.h"
#import "RKRefreshTriggerView.h"
#import "RKObjectManager+RKTableController.h"
#import "UIImage+RKAdditions.h"

View File

@@ -608,16 +608,8 @@
25B6E91E14CF778D00B1E881 /* RKAbstractTableController.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90314CF778D00B1E881 /* RKAbstractTableController.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E92014CF778D00B1E881 /* RKAbstractTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E90414CF778D00B1E881 /* RKAbstractTableController.m */; };
25B6E92314CF778D00B1E881 /* RKAbstractTableController_Internals.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90614CF778D00B1E881 /* RKAbstractTableController_Internals.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E92514CF778D00B1E881 /* RKControlTableItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90714CF778D00B1E881 /* RKControlTableItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E92714CF778D00B1E881 /* RKControlTableItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E90814CF778D00B1E881 /* RKControlTableItem.m */; };
25B6E92914CF778D00B1E881 /* RKControlTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90914CF778D00B1E881 /* RKControlTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E92B14CF778D00B1E881 /* RKControlTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E90A14CF778D00B1E881 /* RKControlTableViewCell.m */; };
25B6E92D14CF778D00B1E881 /* RKFetchedResultsTableController.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90B14CF778D00B1E881 /* RKFetchedResultsTableController.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E92F14CF778D00B1E881 /* RKFetchedResultsTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E90C14CF778D00B1E881 /* RKFetchedResultsTableController.m */; };
25B6E93114CF778D00B1E881 /* RKForm.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90D14CF778D00B1E881 /* RKForm.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E93314CF778D00B1E881 /* RKForm.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E90E14CF778D00B1E881 /* RKForm.m */; };
25B6E93514CF778D00B1E881 /* RKFormSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E90F14CF778D00B1E881 /* RKFormSection.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E93714CF778D00B1E881 /* RKFormSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E91014CF778D00B1E881 /* RKFormSection.m */; };
25B6E93914CF778D00B1E881 /* RKTableController.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E91114CF778D00B1E881 /* RKTableController.h */; settings = {ATTRIBUTES = (Public, ); }; };
25B6E93B14CF778D00B1E881 /* RKTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B6E91214CF778D00B1E881 /* RKTableController.m */; };
25B6E93D14CF778D00B1E881 /* RKTableItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B6E91314CF778D00B1E881 /* RKTableItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1170,16 +1162,8 @@
25B6E90314CF778D00B1E881 /* RKAbstractTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKAbstractTableController.h; sourceTree = "<group>"; };
25B6E90414CF778D00B1E881 /* RKAbstractTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKAbstractTableController.m; sourceTree = "<group>"; };
25B6E90614CF778D00B1E881 /* RKAbstractTableController_Internals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKAbstractTableController_Internals.h; sourceTree = "<group>"; };
25B6E90714CF778D00B1E881 /* RKControlTableItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKControlTableItem.h; sourceTree = "<group>"; };
25B6E90814CF778D00B1E881 /* RKControlTableItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKControlTableItem.m; sourceTree = "<group>"; };
25B6E90914CF778D00B1E881 /* RKControlTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKControlTableViewCell.h; sourceTree = "<group>"; };
25B6E90A14CF778D00B1E881 /* RKControlTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKControlTableViewCell.m; sourceTree = "<group>"; };
25B6E90B14CF778D00B1E881 /* RKFetchedResultsTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKFetchedResultsTableController.h; sourceTree = "<group>"; };
25B6E90C14CF778D00B1E881 /* RKFetchedResultsTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKFetchedResultsTableController.m; sourceTree = "<group>"; };
25B6E90D14CF778D00B1E881 /* RKForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKForm.h; sourceTree = "<group>"; };
25B6E90E14CF778D00B1E881 /* RKForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKForm.m; sourceTree = "<group>"; };
25B6E90F14CF778D00B1E881 /* RKFormSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKFormSection.h; sourceTree = "<group>"; };
25B6E91014CF778D00B1E881 /* RKFormSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKFormSection.m; sourceTree = "<group>"; };
25B6E91114CF778D00B1E881 /* RKTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKTableController.h; sourceTree = "<group>"; };
25B6E91214CF778D00B1E881 /* RKTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKTableController.m; sourceTree = "<group>"; };
25B6E91314CF778D00B1E881 /* RKTableItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKTableItem.h; sourceTree = "<group>"; };
@@ -2122,16 +2106,8 @@
25B6E90314CF778D00B1E881 /* RKAbstractTableController.h */,
25B6E90414CF778D00B1E881 /* RKAbstractTableController.m */,
25B6E90614CF778D00B1E881 /* RKAbstractTableController_Internals.h */,
25B6E90714CF778D00B1E881 /* RKControlTableItem.h */,
25B6E90814CF778D00B1E881 /* RKControlTableItem.m */,
25B6E90914CF778D00B1E881 /* RKControlTableViewCell.h */,
25B6E90A14CF778D00B1E881 /* RKControlTableViewCell.m */,
25B6E90B14CF778D00B1E881 /* RKFetchedResultsTableController.h */,
25B6E90C14CF778D00B1E881 /* RKFetchedResultsTableController.m */,
25B6E90D14CF778D00B1E881 /* RKForm.h */,
25B6E90E14CF778D00B1E881 /* RKForm.m */,
25B6E90F14CF778D00B1E881 /* RKFormSection.h */,
25B6E91014CF778D00B1E881 /* RKFormSection.m */,
25B6E91114CF778D00B1E881 /* RKTableController.h */,
25B6E91214CF778D00B1E881 /* RKTableController.m */,
25B6E91314CF778D00B1E881 /* RKTableItem.h */,
@@ -2358,11 +2334,7 @@
49D275AD14C9F3020090845D /* RKISO8601DateFormatter.h in Headers */,
25B6E91E14CF778D00B1E881 /* RKAbstractTableController.h in Headers */,
25B6E92314CF778D00B1E881 /* RKAbstractTableController_Internals.h in Headers */,
25B6E92514CF778D00B1E881 /* RKControlTableItem.h in Headers */,
25B6E92914CF778D00B1E881 /* RKControlTableViewCell.h in Headers */,
25B6E92D14CF778D00B1E881 /* RKFetchedResultsTableController.h in Headers */,
25B6E93114CF778D00B1E881 /* RKForm.h in Headers */,
25B6E93514CF778D00B1E881 /* RKFormSection.h in Headers */,
25B6E93914CF778D00B1E881 /* RKTableController.h in Headers */,
25B6E93D14CF778D00B1E881 /* RKTableItem.h in Headers */,
25B6E94114CF778D00B1E881 /* RKTableSection.h in Headers */,
@@ -2914,11 +2886,7 @@
49D2759F14C9EF1E0090845D /* ISO8601DateFormatter.m in Sources */,
49D275AF14C9F3020090845D /* RKISO8601DateFormatter.m in Sources */,
25B6E92014CF778D00B1E881 /* RKAbstractTableController.m in Sources */,
25B6E92714CF778D00B1E881 /* RKControlTableItem.m in Sources */,
25B6E92B14CF778D00B1E881 /* RKControlTableViewCell.m in Sources */,
25B6E92F14CF778D00B1E881 /* RKFetchedResultsTableController.m in Sources */,
25B6E93314CF778D00B1E881 /* RKForm.m in Sources */,
25B6E93714CF778D00B1E881 /* RKFormSection.m in Sources */,
25B6E93B14CF778D00B1E881 /* RKTableController.m in Sources */,
25B6E93F14CF778D00B1E881 /* RKTableItem.m in Sources */,
25B6E94314CF778D00B1E881 /* RKTableSection.m in Sources */,