Skip to content

Commit

Permalink
Add support for NSFormatter
Browse files Browse the repository at this point in the history
  • Loading branch information
ziogaschr committed Sep 18, 2015
1 parent 08eaf70 commit 2c972c5
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 7 deletions.
7 changes: 7 additions & 0 deletions Examples/Objective-C/Examples/ExamplesFormViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#import "CustomRowsViewController.h"
#import "AccessoryViewFormViewController.h"
#import "PredicateFormViewController.h"
#import "FormattersViewController.h"

NSString * const kTextFieldAndTextView = @"TextFieldAndTextView";
NSString * const kSelectors = @"Selectors";
Expand All @@ -46,6 +47,7 @@
NSString * const kMultivaluedOnlyInsert = @"MultivaluedOnlyInsert";
NSString * const kMultivaluedOnlyDelete = @"MultivaluedOnlyDelete";
NSString * const kValidations= @"Validations";
NSString * const kFormatters = @"Formatters";

@interface ExamplesFormViewController ()

Expand Down Expand Up @@ -113,6 +115,11 @@ -(void)initializeForm
row.action.viewControllerClass = [DatesFormViewController class];
[section addFormRow:row];

// NSFormatters
row = [XLFormRowDescriptor formRowDescriptorWithTag:kFormatters rowType:XLFormRowDescriptorTypeButton title:@"NSFormatter Support"];
row.action.viewControllerClass = [FormattersViewController class];
[section addFormRow:row];

// Others
row = [XLFormRowDescriptor formRowDescriptorWithTag:kOthes rowType:XLFormRowDescriptorTypeButton title:@"Other Rows"];
row.action.formSegueIdenfifier = @"OthersFormViewControllerSegue";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// FormattersViewController.h
// XLForm
//
// Created by Freddy Henin on 12/29/14.
// Copyright (c) 2014 Xmartlabs. All rights reserved.
//

#import "XLFormViewController.h"

@interface FormattersViewController : XLFormViewController

@end
115 changes: 115 additions & 0 deletions Examples/Objective-C/Examples/Formatters/FormattersViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// FormattersViewController.m
// XLForm
//
// Created by Freddy Henin on 12/29/14.
// Copyright (c) 2014 Xmartlabs. All rights reserved.
//

#import <Foundation/Foundation.h>


#import "XLForm.h"

#import "FormattersViewController.h"

#import <SHSPhoneComponent/SHSPhoneNumberFormatter+UserConfig.h>


// Simple little class to demonstraite currency formatting. Unfortunally we have to subclass
// NSNumberFormatter to work aroundn some long known rounding bugs with NSNumberFormatter
// http://stackoverflow.com/questions/12580162/nsstring-to-nsdate-conversion-issue
@interface CurrencyFormatter : NSNumberFormatter

@property (readonly) NSDecimalNumberHandler *roundingBehavior;

@end

@implementation CurrencyFormatter

- (id) init
{
self = [super init];
if (self) {
[self setNumberStyle: NSNumberFormatterCurrencyStyle];
[self setGeneratesDecimalNumbers:YES];

NSUInteger currencyScale = [self maximumFractionDigits];

_roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:currencyScale raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];

}

return self;
}

//- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
//{
// NSDecimalNumber *number;
// BOOL success = [super getObjectValue:&number forString:string errorDescription:error];
//
// if (success) {
// *anObject = [number decimalNumberByRoundingAccordingToBehavior:_roundingBehavior];
// }
// else {
// *anObject = nil;
// }
//
// return success;
//}

@end

@interface FormattersViewController ()
@end

@implementation FormattersViewController

-(id)init
{
XLFormDescriptor * formDescriptor = [XLFormDescriptor formDescriptorWithTitle:@"Text Fields"];
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;

formDescriptor.assignFirstResponderOnShow = NO;

section = [XLFormSectionDescriptor formSection];
section.title = @"NSFormatter Support";
section.footerTitle = @"Rows can be configured to use the formatter as you type or to toggle on and off during for display/editing. You will most likely need custom NSFormatter objects to do on the fly formatting since NSNumberFormatter is pretty limited in this regard.";
[formDescriptor addFormSection:section];

// Phone
SHSPhoneNumberFormatter *formatter = [[SHSPhoneNumberFormatter alloc] init];
[formatter setDefaultOutputPattern:@"(###) ###-####" imagePath:nil];
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"phone" rowType:XLFormRowDescriptorTypePhone title:@"US Phone"];
row.valueFormatter = formatter;
[row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];

row.useValueFormatterDuringInput = YES;
[section addFormRow:row];

// Currency
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"currency" rowType:XLFormRowDescriptorTypeDecimal title:@"USD"];
CurrencyFormatter *numberFormatter = [[CurrencyFormatter alloc] init];
row.valueFormatter = numberFormatter;
row.value = [NSDecimalNumber numberWithDouble:9.95];
[row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
[section addFormRow:row];

// Accounting
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"percent" rowType:XLFormRowDescriptorTypeNumber title:@"Test Score"];
NSNumberFormatter *acctFormatter = [[NSNumberFormatter alloc] init];
[acctFormatter setNumberStyle:NSNumberFormatterPercentStyle];
row.valueFormatter = acctFormatter;
row.value = @(0.75);
[row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
[section addFormRow:row];

section = [XLFormSectionDescriptor formSection];
[formDescriptor addFormSection:section];

return [super initWithForm:formDescriptor];

}

@end
1 change: 1 addition & 0 deletions Examples/Objective-C/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ pod 'AFNetworking', '~> 2.0', :inhibit_warnings => true
pod 'XLData', :git => 'https://github.com/xmartlabs/XLData.git', :commit => '1f9019b56242a2019c7f7e11ec4ef823c397ebcf', :inhibit_warnings => true
pod 'JVFloatLabeledTextField', '1.0.2', :inhibit_warnings => true
pod 'AXRatingView', '1.0.3', :inhibit_warnings => true
pod 'SHSPhoneComponent'
50 changes: 50 additions & 0 deletions Examples/Objective-C/Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
PODS:
- AFNetworking (2.5.2):
- AFNetworking/NSURLConnection (= 2.5.2)
- AFNetworking/NSURLSession (= 2.5.2)
- AFNetworking/Reachability (= 2.5.2)
- AFNetworking/Security (= 2.5.2)
- AFNetworking/Serialization (= 2.5.2)
- AFNetworking/UIKit (= 2.5.2)
- AFNetworking/NSURLConnection (2.5.2):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/NSURLSession (2.5.2):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/Reachability (2.5.2)
- AFNetworking/Security (2.5.2)
- AFNetworking/Serialization (2.5.2)
- AFNetworking/UIKit (2.5.2):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- AXRatingView (1.0.3)
- JVFloatLabeledTextField (1.0.2)
- SHSPhoneComponent (2.15)
- XLDataLoader (1.1.0):
- AFNetworking (~> 2.0)
- XLForm (2.2.0)

DEPENDENCIES:
- AFNetworking (~> 2.0)
- AXRatingView (= 1.0.3)
- JVFloatLabeledTextField (= 1.0.2)
- SHSPhoneComponent
- XLDataLoader (~> 1.1)
- XLForm (from `../../`)

EXTERNAL SOURCES:
XLForm:
:path: ../../

SPEC CHECKSUMS:
AFNetworking: fefbce9660acb17f48ae0011292d4da0f457bf36
AXRatingView: ccaadc1bbda99a4b7e1d556059482d2b933a9f4e
JVFloatLabeledTextField: 58a3a32cfb800e5b224f676987e7c13abf50a14d
SHSPhoneComponent: 4cec0653a150ad63cbc52b0c8b29ce2d3c9c26f0
XLDataLoader: 7d466e086f4b6ecd144e880be8232adbe80aef52
XLForm: 799e61ef230f519914e722bf032b19a597223c19

COCOAPODS: 0.36.3
15 changes: 15 additions & 0 deletions Examples/Objective-C/XLForm.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
BFE91AFB1AE159B200DE5231 /* BasicPredicateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */; };
D51B8B2C19126664008C0478 /* XLFormCustomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D51B8B2B19126664008C0478 /* XLFormCustomCell.m */; };
DEA6EF911B57D6CC000F4893 /* HTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */; };
DEB8235C1AD5529A00AF9FE2 /* FormattersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -124,6 +125,8 @@
D51B8B2B19126664008C0478 /* XLFormCustomCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormCustomCell.m; path = Examples/Others/CustomCells/XLFormCustomCell.m; sourceTree = "<group>"; };
DEA6EF8F1B57D6CC000F4893 /* HTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSessionManager.h; path = Examples/Selectors/HTTPSessionManager.h; sourceTree = "<group>"; };
DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPSessionManager.m; path = Examples/Selectors/HTTPSessionManager.m; sourceTree = "<group>"; };
DEB8235A1AD5529A00AF9FE2 /* FormattersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormattersViewController.h; sourceTree = "<group>"; };
DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FormattersViewController.m; sourceTree = "<group>"; };
F6DF43B7BBF44F72A4493E8E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -309,6 +312,7 @@
282EB2791AB5FD66004A736F /* AccessoryViews */,
3CDAFC741AB0AEE5000F75B6 /* CustomRows */,
28F89F2B1AA4E99500E90218 /* Validations */,
DEB823591AD5529A00AF9FE2 /* Formatters */,
283C6B7A1999BA1B00A5283D /* UICustomization */,
28A76624193251E500D69546 /* AppDelegate.m */,
28A8083C190D903D009D77F8 /* StoryboardExample */,
Expand Down Expand Up @@ -448,6 +452,16 @@
name = SessionManager;
sourceTree = "<group>";
};
DEB823591AD5529A00AF9FE2 /* Formatters */ = {
isa = PBXGroup;
children = (
DEB8235A1AD5529A00AF9FE2 /* FormattersViewController.h */,
DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */,
);
name = Formatters;
path = Examples/Formatters;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -576,6 +590,7 @@
2843EB4718D4915800F13E2B /* ExamplesFormViewController.m in Sources */,
BF9DB1D61AE0436600B985E7 /* PredicateFormViewController.m in Sources */,
BFE91AFB1AE159B200DE5231 /* BasicPredicateViewController.m in Sources */,
DEB8235C1AD5529A00AF9FE2 /* FormattersViewController.m in Sources */,
2843EB5218D4CFC700F13E2B /* OthersFormViewController.m in Sources */,
2843EB4B18D496F600F13E2B /* SelectorsFormViewController.m in Sources */,
28468EA418EF41D300DBB015 /* InputsFormViewController.m in Sources */,
Expand Down
46 changes: 39 additions & 7 deletions XLForm/XL/Cell/XLFormTextFieldCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ -(void)update

self.textLabel.text = ((self.rowDescriptor.required && self.rowDescriptor.title && self.rowDescriptor.sectionDescriptor.formDescriptor.addAsteriskToRequiredRowsTitle) ? [NSString stringWithFormat:@"%@*", self.rowDescriptor.title] : self.rowDescriptor.title);

self.textField.text = self.rowDescriptor.value ? [self.rowDescriptor.value displayText] : self.rowDescriptor.noValueDisplayText;
self.textField.text = self.rowDescriptor.value ? [self.rowDescriptor displayTextValue] : self.rowDescriptor.noValueDisplayText;
[self.textField setEnabled:!self.rowDescriptor.isDisabled];
self.textField.textColor = self.rowDescriptor.isDisabled ? [UIColor grayColor] : [UIColor blackColor];
self.textField.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
Expand Down Expand Up @@ -265,11 +265,22 @@ - (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self.formViewController beginEditing:self.rowDescriptor];
[self.formViewController textFieldDidBeginEditing:textField];
// set the input to the raw value if we have a formatter and it shouldn't be used during input
if (self.rowDescriptor.valueFormatter) {
self.textField.text = [self.rowDescriptor editTextValue];
}
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
// process text change before we stick a formatted value in the UITextField
[self textFieldDidChange:textField];

// losing input, replace the text field with the formatted value
if (self.rowDescriptor.valueFormatter) {
self.textField.text = [self.rowDescriptor.value displayText];
}

[self.formViewController endEditing:self.rowDescriptor];
[self.formViewController textFieldDidEndEditing:textField];
}
Expand All @@ -279,12 +290,33 @@ - (void)textFieldDidEndEditing:(UITextField *)textField

- (void)textFieldDidChange:(UITextField *)textField{
if([self.textField.text length] > 0) {
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeNumber] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDecimal]){
self.rowDescriptor.value = @([self.textField.text doubleValue]);
} else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeInteger]){
self.rowDescriptor.value = @([self.textField.text integerValue]);
} else {
self.rowDescriptor.value = self.textField.text;
BOOL didUseFormatter = NO;

if (self.rowDescriptor.valueFormatter && self.rowDescriptor.useValueFormatterDuringInput)
{
// use generic getObjectValue:forString:errorDescription and stringForObjectValue
NSString *errorDescription = nil;
NSString *objectValue = nil;

if ([ self.rowDescriptor.valueFormatter getObjectValue:&objectValue forString:textField.text errorDescription:&errorDescription]) {
NSString *formattedValue = [self.rowDescriptor.valueFormatter stringForObjectValue:objectValue];

self.rowDescriptor.value = objectValue;
textField.text = formattedValue;
didUseFormatter = YES;
}
}

// only do this conversion if we didn't use the formatter
if (!didUseFormatter)
{
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeNumber] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDecimal]){
self.rowDescriptor.value = @([self.textField.text doubleValue]);
} else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeInteger]){
self.rowDescriptor.value = @([self.textField.text integerValue]);
} else {
self.rowDescriptor.value = self.textField.text;
}
}
} else {
self.rowDescriptor.value = nil;
Expand Down
8 changes: 8 additions & 0 deletions XLForm/XL/Descriptors/XLFormRowDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ typedef void(^XLOnChangeBlock)(id __nullable oldValue,id __nullable newValue,XLF
@property UITableViewCellStyle cellStyle;

@property (copy, nullable) XLOnChangeBlock onChangeBlock;
@property BOOL useValueFormatterDuringInput;
@property NSFormatter *valueFormatter;

// returns the display text for the row descriptor, taking into account NSFormatters and default placeholder values
- (NSString*) displayTextValue;

// returns the editing text value for the row descriptor, taking into account NSFormatters.
- (NSString*) editTextValue;

@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfig;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigIfDisabled;
Expand Down
Loading

0 comments on commit 2c972c5

Please sign in to comment.