Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adds a fix to forms generated from CoreData, to ensure that overriden…

… fields are used. Also adds simple form generation from CoreData object model, by subclassing SurveyModelForm
  • Loading branch information...
commit 7ce6c34fe1f5936875074d6f5eb1a274d0a25c27 1 parent 5a71136
@wess authored
View
68 README.md
@@ -1,19 +1,19 @@
# Survey
-> Survey is a library to simplify the process of creating and validating forms. This library is loosely based on CoreData and Django forms.
+Survey is a library to simplify the process of creating and validating forms. This library is loosely based on CoreData and Django forms.
-## To-do: (Just starting development, much more to come)
+## TODO: (Just starting development, much more to come)
* More Validators
-* Generate forms from ManagedObject models
-* Block based form actions.
+* Create save/update methods on forms generated from managedObjectModels
+* Create ability to attach UIView to a field to show error messages.
## Setting up
-> To set up, place the Survey project file into your project, link to the libSurvey.a framework and add it as a target dependency, then just #import <Survey/Survey.h> and go to town!
+To set up, place the Survey project file into your project, add it as a target dependency, link to the libSurvey.a framework, then just #import <Survey/Survey.h> and go to town!
## Example Form Model:
-> Setting up a form is pretty simple, you just subclass SurveyFormModel and set up properties for the fields you want. Then, in the implementation, set up each field with the properties you want.
+Setting up a form is pretty simple, you just subclass SurveyFormModel and set up properties for the fields you want. Then, in the implementation, set up each field with the properties you want.
-> Be sure to checkout SurveyEmailField to see how easy it is to create custom fields to use. the email field example below has been updated to use that custom field.
+Be sure to checkout SurveyEmailField to see how easy it is to create custom fields to use. the email field example below has been updated to use that custom field.
```objectivec
@@ -108,7 +108,7 @@
```
## Using the form
-> Using the form is also pretty simple, you just init the form and then when you want to use it, you just check that it's valid then grab the values you need.
+Using the form is also pretty simple, you just init the form and then when you want to use it, you just check that it's valid then grab the values you need.
```objectivec
@@ -149,7 +149,7 @@ if(registerForm.isValid)
```
## Using the object form
-> Using an object form model is exactly like using a regular form model. The only difference is when you create a new
+Using an object form model is exactly like using a regular form model. The only difference is when you create a new
instance you will provide it with an NSEntityDescription.
``` objectivec
@@ -159,6 +159,56 @@ WCModelForm *form = [[WCModelForm alloc] initWithEntityDescription:entityDescrip
```
+### Simplified Object Form
+You can now use SurveyModelForm to create forms, even easier than SurveyObjectModelForm, just by subclassing and little setup. You don't have to override any fields if you don't want to, Survey will do it's best to create the form straight from the object model. We still have the weird ordering issue so be sure to use +(NSArray *)fields if you want to order the fields yourself. You can pick and chose which fields to override, or all, or none. The form then works just like a regular form would, with isValid, etc..
+
+``` objectivec
+// WCEasyModelForm.h
+
+#import <Survey/SurveyModelForm.h>
+#import <Survey/SurveyField.h>
+
+@interface WCEasyModelForm : SurveyModelForm
+@property (strong, nonatomic) SurveyField *lastname;
+@end
+
+
+// WCEasyModelForm.m
+
+#import "WCEasyModelForm.h"
+#import "WCCoreData.h"
+#import "Person.h"
+
+@implementation WCEasyModelForm
+
++ (Class)managedObjectClass
+{
+ return [Person class];
+}
+
++ (NSManagedObjectContext *)managedObjectContext
+{
+ return [[WCCoreData instance] managedObjectContext];
+}
+
+- (SurveyField *)lastname
+{
+ SurveyField *field = [SurveyField fieldWithPlaceholder:@"Wooooyaaa"];
+ field.isRequired = YES;
+
+ return field;
+}
+
++ (NSArray *)fields
+{
+ return @[@"firstname", @"lastname"];
+}
+
+@end
+
+
+```
+
## If you need me
* [Github](http://www.github.com/wess)
* [@WessCope](http://www.twitter.com/wesscope)
View
4 Survey.podspec
@@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = "Survey"
- s.version = "0.0.6"
+ s.version = "0.1.0"
s.summary = "Survey is a library to simplify the process of creating and validating forms. This library is loosely based on CoreData and Django forms."
s.homepage = "http://github.com/wess/Survey"
s.license = 'MIT'
s.author = { "Wess Cope" => "wcope@me.com" }
s.ios.deployment_target = '5.0'
- s.source = { :git => "https://github.com/wess/Survey.git", :tag => "0.0.6" }
+ s.source = { :git => "https://github.com/wess/Survey.git", :tag => "0.1.0" }
s.source_files = 'Survey/Classes/*.{h,m}'
s.requires_arc = true
s.framework = 'UIKit'
View
8 Survey.xcodeproj/project.pbxproj
@@ -28,6 +28,8 @@
082D3982162C859400973067 /* SurveyValidators.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 082D3948162C82C200973067 /* SurveyValidators.h */; };
082D398F162C8F3E00973067 /* SurveyFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 082D398E162C8F3E00973067 /* SurveyFieldCell.m */; };
082D3993162C97A100973067 /* SurveyFieldCell.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 082D398D162C8F3E00973067 /* SurveyFieldCell.h */; };
+ 08C0C07A16AEE89F0001CBE8 /* SurveyModelForm.m in Sources */ = {isa = PBXBuildFile; fileRef = 08C0C07916AEE89F0001CBE8 /* SurveyModelForm.m */; };
+ 08C0C08016AEED830001CBE8 /* SurveyModelForm.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 08C0C07816AEE89F0001CBE8 /* SurveyModelForm.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -47,6 +49,7 @@
dstPath = "include/${PRODUCT_NAME}";
dstSubfolderSpec = 16;
files = (
+ 08C0C08016AEED830001CBE8 /* SurveyModelForm.h in CopyFiles */,
08296A71167BC1EF00B4B31E /* SurveyDynamicObject.h in CopyFiles */,
08296A6C167BBA3200B4B31E /* SurveyObjectModelForm.h in CopyFiles */,
0823592C163B013500DBD15E /* SurveyEmailField.h in CopyFiles */,
@@ -86,6 +89,8 @@
082D3954162C835300973067 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
082D398D162C8F3E00973067 /* SurveyFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SurveyFieldCell.h; sourceTree = "<group>"; };
082D398E162C8F3E00973067 /* SurveyFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SurveyFieldCell.m; sourceTree = "<group>"; };
+ 08C0C07816AEE89F0001CBE8 /* SurveyModelForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SurveyModelForm.h; sourceTree = "<group>"; };
+ 08C0C07916AEE89F0001CBE8 /* SurveyModelForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SurveyModelForm.m; sourceTree = "<group>"; };
08C867F8162CE99200B98C14 /* SurveyExample.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SurveyExample.xcodeproj; path = SurveyExample/SurveyExample.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -230,6 +235,8 @@
children = (
082D3944162C82C200973067 /* SurveyForm.h */,
082D3945162C82C200973067 /* SurveyForm.m */,
+ 08C0C07816AEE89F0001CBE8 /* SurveyModelForm.h */,
+ 08C0C07916AEE89F0001CBE8 /* SurveyModelForm.m */,
);
name = Form;
sourceTree = "<group>";
@@ -352,6 +359,7 @@
0823592B163AFF8700DBD15E /* SurveyEmailField.m in Sources */,
08296A07167BA06500B4B31E /* SurveyObjectModelForm.m in Sources */,
08296A70167BC1BC00B4B31E /* SurveyDynamicObject.m in Sources */,
+ 08C0C07A16AEE89F0001CBE8 /* SurveyModelForm.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
8 Survey/Classes/SurveyForm.m
@@ -158,13 +158,7 @@ - (NSArray *)fields
{
__block NSDictionary *properties = (propertiesForClass([_model class]));
__block NSUInteger idx = 0;
-
- if([properties objectForKey:@"entityDescription"])
- {
- SurveyObjectModelForm *formInstance = (SurveyObjectModelForm *)_model;
- properties = formInstance.properties;
- }
-
+
[properties enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *propType, BOOL *stop) {
SurveyField *fieldObject = [self setupFieldObject:(SurveyField *)[_model valueForKey:key] withKey:key];
[fieldsArray addObject:fieldObject];
View
15 Survey/Classes/SurveyModelForm.h
@@ -0,0 +1,15 @@
+//
+// SurveyModelForm.h
+// Survey
+//
+// Created by Wess Cope on 1/22/13.
+// Copyright (c) 2013 Wess Cope. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "SurveyObjectModelForm.h"
+
+@interface SurveyModelForm : SurveyObjectModelForm
++ (Class)managedObjectClass;
++ (NSManagedObjectContext *)managedObjectContext;
+@end
View
37 Survey/Classes/SurveyModelForm.m
@@ -0,0 +1,37 @@
+//
+// SurveyModelForm.m
+// Survey
+//
+// Created by Wess Cope on 1/22/13.
+// Copyright (c) 2013 Wess Cope. All rights reserved.
+//
+
+#import "SurveyModelForm.h"
+
+@implementation SurveyModelForm
+
+- (id)init
+{
+ NSString *entityName = NSStringFromClass([[self class] managedObjectClass]);
+ NSManagedObjectContext *context = [[self class] managedObjectContext];
+ NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
+
+ self = [super initWithEntityDescription:entityDescription];
+ if(self)
+ {
+
+ }
+ return self;
+}
+
++ (Class)managedObjectClass
+{
+ @throw [NSException exceptionWithName:@"com.Survey.ModelForm.Error" reason:@"SurveyModelForm subclass requires managedObjectClass method to be overidden" userInfo:nil];
+}
+
++ (NSManagedObjectContext *)managedObjectContext
+{
+ @throw [NSException exceptionWithName:@"com.Survey.ModelForm.Error" reason:@"SurveyModelForm subclass requires managedObjectContext to be overidden" userInfo:nil];
+}
+
+@end
View
36 Survey/Classes/SurveyObjectModelForm.m
@@ -31,6 +31,20 @@ - (id)initWithEntityDescription:(NSEntityDescription *)entityDescription
self.entityDescription = entityDescription;
[self processEntityDescription];
+
+ NSDictionary *classProperties = propertiesForClass([self class]);
+
+ [classProperties enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *propertyType, BOOL *stop) {
+ if([[propertyType lowercaseString] isEqualToString:@"surveyfield"])
+ {
+ SEL selector = NSSelectorFromString(key);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ [self setValue:[self performSelector:selector] forKey:key];
+#pragma clang diagnostic pop
+ }
+ }];
+
}
return self;
}
@@ -38,14 +52,17 @@ - (id)initWithEntityDescription:(NSEntityDescription *)entityDescription
- (void)processEntityDescription
{
NSArray *properties = [self.entityDescription properties];
+
[properties enumerateObjectsUsingBlock:^(NSAttributeDescription *attribute, NSUInteger idx, BOOL *stop) {
- NSString *name = [attribute.name copy];
NSInteger isOptional = attribute.isOptional;
- SurveyField *field = [SurveyField fieldWithPlaceholder:[name capitalizedString]];
- field.isRequired = ![@(isOptional) boolValue];
-
- [self setValue:field forKey:name];
+ if(![self getObjectForKey:attribute.name])
+ {
+ SurveyField *field = [SurveyField fieldWithPlaceholder:[attribute.name capitalizedString]];
+ field.isRequired = ![@(isOptional) boolValue];
+
+ [self setValue:field forKey:attribute.name];
+ }
}];
}
@@ -79,14 +96,7 @@ - (SurveyForm *)form
- (NSArray *)fields
{
- SurveyForm *form = [self form];
-
- NSMutableArray *formFields = [[NSMutableArray alloc] init];
-
- for(SurveyField *field in form.fields)
- [formFields addObject:field.field];
-
- return [NSArray arrayWithArray:formFields];
+ return [[[self form] fields] valueForKeyPath:@"field"]; //;[NSArray arrayWithArray:formFields];
}
- (BOOL)isValid
View
14 SurveyExample/SurveyExample.xcodeproj/project.pbxproj
@@ -12,6 +12,7 @@
08296A65167BB93D00B4B31E /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08296A64167BB93D00B4B31E /* CoreData.framework */; };
08296A68167BB99B00B4B31E /* Person.m in Sources */ = {isa = PBXBuildFile; fileRef = 08296A67167BB99A00B4B31E /* Person.m */; };
08296A75167BC6A000B4B31E /* WCModelForm.m in Sources */ = {isa = PBXBuildFile; fileRef = 08296A74167BC6A000B4B31E /* WCModelForm.m */; };
+ 08C0C07F16AEED360001CBE8 /* WCEasyModelForm.m in Sources */ = {isa = PBXBuildFile; fileRef = 08C0C07E16AEED360001CBE8 /* WCEasyModelForm.m */; };
08C867DC162CE99200B98C14 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08C867DB162CE99200B98C14 /* UIKit.framework */; };
08C867DE162CE99200B98C14 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08C867DD162CE99200B98C14 /* Foundation.framework */; };
08C867E0162CE99200B98C14 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08C867DF162CE99200B98C14 /* CoreGraphics.framework */; };
@@ -36,6 +37,8 @@
08296A67167BB99A00B4B31E /* Person.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Person.m; sourceTree = "<group>"; };
08296A73167BC6A000B4B31E /* WCModelForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WCModelForm.h; sourceTree = "<group>"; };
08296A74167BC6A000B4B31E /* WCModelForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WCModelForm.m; sourceTree = "<group>"; };
+ 08C0C07D16AEED360001CBE8 /* WCEasyModelForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WCEasyModelForm.h; sourceTree = "<group>"; };
+ 08C0C07E16AEED360001CBE8 /* WCEasyModelForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WCEasyModelForm.m; sourceTree = "<group>"; };
08C867D7162CE99200B98C14 /* SurveyExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SurveyExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
08C867DB162CE99200B98C14 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
08C867DD162CE99200B98C14 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -120,6 +123,15 @@
name = ModelForm;
sourceTree = "<group>";
};
+ 08C0C07B16AEED290001CBE8 /* EasyModelForm */ = {
+ isa = PBXGroup;
+ children = (
+ 08C0C07D16AEED360001CBE8 /* WCEasyModelForm.h */,
+ 08C0C07E16AEED360001CBE8 /* WCEasyModelForm.m */,
+ );
+ name = EasyModelForm;
+ sourceTree = "<group>";
+ };
08C867CC162CE99200B98C14 = {
isa = PBXGroup;
children = (
@@ -188,6 +200,7 @@
08C86800162CE9B400B98C14 /* Form */ = {
isa = PBXGroup;
children = (
+ 08C0C07B16AEED290001CBE8 /* EasyModelForm */,
08296A72167BC69400B4B31E /* ModelForm */,
08296A6A167BB9CF00B4B31E /* RegisterForm */,
);
@@ -277,6 +290,7 @@
08296A22167BB7FB00B4B31E /* WCCoreData.m in Sources */,
08296A68167BB99B00B4B31E /* Person.m in Sources */,
08296A75167BC6A000B4B31E /* WCModelForm.m in Sources */,
+ 08C0C07F16AEED360001CBE8 /* WCEasyModelForm.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
15 SurveyExample/SurveyExample/WCEasyModelForm.h
@@ -0,0 +1,15 @@
+//
+// WCEasyModelForm.h
+// SurveyExample
+//
+// Created by Wess Cope on 1/22/13.
+// Copyright (c) 2013 Wess Cope. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Survey/SurveyModelForm.h>
+#import <Survey/SurveyField.h>
+
+@interface WCEasyModelForm : SurveyModelForm
+@property (strong, nonatomic) SurveyField *lastname;
+@end
View
38 SurveyExample/SurveyExample/WCEasyModelForm.m
@@ -0,0 +1,38 @@
+//
+// WCEasyModelForm.m
+// SurveyExample
+//
+// Created by Wess Cope on 1/22/13.
+// Copyright (c) 2013 Wess Cope. All rights reserved.
+//
+
+#import "WCEasyModelForm.h"
+#import "WCCoreData.h"
+#import "Person.h"
+
+@implementation WCEasyModelForm
+
++ (Class)managedObjectClass
+{
+ return [Person class];
+}
+
++ (NSManagedObjectContext *)managedObjectContext
+{
+ return [[WCCoreData instance] managedObjectContext];
+}
+
+- (SurveyField *)lastname
+{
+ SurveyField *field = [SurveyField fieldWithPlaceholder:@"Wooooyaaa"];
+ field.isRequired = YES;
+
+ return field;
+}
+
++ (NSArray *)fields
+{
+ return @[@"firstname", @"lastname"];
+}
+
+@end
View
1  SurveyExample/SurveyExample/WCModelForm.h
@@ -11,4 +11,5 @@
#import <Survey/SurveyField.h>
@interface WCModelForm : SurveyObjectModelForm
+@property (strong, nonatomic) SurveyField *lastname;
@end
View
10 SurveyExample/SurveyExample/WCRegisterFormViewController.m
@@ -9,10 +9,12 @@
#import "WCRegisterFormViewController.h"
#import "WCCoreData.h"
#import "WCModelForm.h"
+#import "WCEasyModelForm.h"
@interface WCRegisterFormViewController ()
//@property (strong, nonatomic) WCRegisterForm *registerForm;
-@property (strong, nonatomic) WCModelForm *registerForm;
+//@property (strong, nonatomic) WCModelForm *registerForm;
+@property (strong, nonatomic) WCEasyModelForm *registerForm;
- (void)buttonAction:(id)sender;
@end
@@ -25,8 +27,10 @@ - (id)init
{
// _registerForm = [[WCRegisterForm alloc] init];
- NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[WCCoreData instance].managedObjectContext];
- _registerForm = [[WCModelForm alloc] initWithEntityDescription:entityDescription];
+// NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[WCCoreData instance].managedObjectContext];
+// _registerForm = [[WCModelForm alloc] initWithEntityDescription:entityDescription];
+
+ _registerForm = [[WCEasyModelForm alloc] init];
}
return self;
}
View
1  SurveyExample/SurveyExample/main.m
@@ -7,7 +7,6 @@
//
#import <UIKit/UIKit.h>
-
#import "WCAppDelegate.h"
int main(int argc, char *argv[])
Please sign in to comment.
Something went wrong with that request. Please try again.