How to do validation on multiple textfields in objective c - uitextfield

I m creating an application in which I am dynamically displaying components according to web service data.When I have more than one textfields , I am not able to do the validation correctly/it is not properly executing the delegate methods.If I click on the second textfield after typing something on the first textfield, the code which I have written in textFieldDidEndEditing for validation never gets executed for textfield1.
I m using the same variable for textfields in a loop like this:
for(int i=0;i<[textfields count];i++)
{
_barcodeTextfield = [UITextField alloc] init];
_barcodeTextfield.delegate = self;
[QuestionView addSubView:_barcodeTextField];
}
And the validation method is written in textfieldDidEndEditing method for displaying an alert if the validation fails.
like
if(textField== _barcodeTextField)
{
//do the validation
}
but this doesn't get executed for the first textfield when I move the cursor to the second one.Thank you very much for any help in advance.

In your for loop, add tags as well to UITextField.
for(int i=0;i<[textfields count];i++) {
_barcodeTextfield = [UITextField alloc] init];
_barcodeTextfield.delegate = self;
_barcodeTextfield.tag = i;
[QuestionView addSubView:_barcodeTextField];
}
You should collect the text immediately after it is entered by setting the delegate of the text field to your view controller
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag == 1) {
// Store the first name in a property, or array, or something.
} Continue the same for other textfields
//Perform Validation
[self performValidation];
}
PerformValidation will be something like this.
-(void)performValidation {
if (firstProperty.length == 0) {
//Display alert
}
}

Because of this complexity of adding validation to textfields I have crated a class JSInputField (which is subclass of UITextField). You can add any validation to the textfield with a single line of code.
JSInputField *inputField = [[JSInputField alloc] initWithFrame:CGRectMake(10, 100, 300, 50)];
[self.view addSubview:inputField];
[inputField setPlaceholder:#"Input Text"];
[inputField setRoundedCorners:UIRectCornerAllCorners];
[inputField addValidationRule:JSCreateRuleNotNullValue]; //This will validate field for null value. It will show error if field is empty.
[inputField addValidationRule:JSCreateRuleLength(10)]; //This will validate field for string of length equal to or less than 10.
JSInputField *inputField = [[JSInputField alloc] initWithFrame:CGRectMake(10, 100, 300, 50)];
[self.view addSubview:inputField];
[inputField setPlaceholder:#"Input Number"];
[inputField setRoundedCorners:UIRectCornerAllCorners];
[inputField addValidationRule:JSCreateRuleNotNullValue]; //This will validate field for null value. It will show error if field is empty.
[inputField addValidationRule:JSCreateRuleNumeric(0)]; //This will validate field for numeric values and restrict to enter value upto 0 decimal places.

Related

Core Data Exporting all tables

I have an app that creates individual events and stores them in core data. What I need to do it load one individually and then export it by email. The code below works except it exports every event where I need it to just export the index path selected one. The code does load the appropriate record because the NSLog (#"My record is: %#", currentItem); does display only the settings for that event but when the data is exported to email all events are sent. I need the selected event with the event name to export. Any thoughts?
NSInteger index = exportevent.tag;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
CDBaseItem *rawRecord = [self.fetchedResultsController objectAtIndexPath:indexPath];
CDSurveyItem *surveyItem = [CDSurveyItem castObject:rawRecord];
self.recordEditID = [rawRecord.objectID URIRepresentation];
NSManagedObjectID *objectId = [self.managedObjectContext.persistentStoreCoordinator managedObjectIDForURIRepresentation:self.recordEditID];
TSPItem *currentItem = [self.managedObjectContext objectWithID:objectId];
NSString *eventName = nil;
if (currentItem.eventname) {
eventName = currentItem.eventname;
}
else if (surveyItem.eventname) {
eventName = surveyItem.eventname;
}
[self setSelection:indexPath];
if (self.selection)
{
if (currentItem)
{
NSLog (#"My record is: %#", currentItem);
NSData *export = [CDJSONExporter exportContext:currentItem.managedObjectContext auxiliaryInfo:nil];
MFMailComposeViewController *composeVC1 = [[MFMailComposeViewController alloc] init];
composeVC1 = [[MFMailComposeViewController alloc] init];
composeVC1.mailComposeDelegate = self;
[composeVC1 setSubject:[NSString stringWithFormat:#"Settings From %# Event", eventName]];
[composeVC1 setMessageBody:[NSString stringWithFormat:#"Here is the event settings. Simply press on the attachment and then choose Open in iPIX"] isHTML:NO];
[composeVC1 addAttachmentData:export mimeType:#"application/octet-stream" fileName:[NSString stringWithFormat:#"%#.ipix", eventName]];
[self presentViewController:composeVC1 animated:NO completion:^(void){}];
}
[self setSelection:nil];
}
Your NSLog may be correct, but you're not exporting the thing that you're printing. In this line (which I assume is a reference to this project):
NSData *export = [CDJSONExporter exportContext:currentItem.managedObjectContext auxiliaryInfo:nil];
You're telling CDJSONExporter to export the context, not a single object. You get every object because that is what CDJSONExporter does. It gets everything it can find in the context and gives you a data object. It's not designed to do what you're asking it to do.
If you want to convert a single object to JSON, you could
Roll your own JSON conversion code. Since you know what the object looks like, this would be easy. Or...
Implement Encodable on your model object and then use JSONEncoder to convert to JSON. Or...
Find some other open source project that does what you want, instead of this one which does not.

NSOutlineView cell based getting column from the fieldEditor

I've an old project with an outlineView cell based and I want to make an NSAlert if one of the cell has an incorrect value before "outlinView setObjectValue:" get called. I need to know where is located and what I've tried is this w/o success:
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
if ([control isEqualTo: myOutline]) {
id item = [myOutline itemAtRow:[myOutline selectedRow]]; // ok
NSInteger columnNum = [myOutline columnForView:fieldEditor];
NSLog(#"columnNum = %ld", (long) columnNum); // bad, wrong column, it print 0 but the cell is at column 3
TreeObj *data = (TreeObj *)[item representedObject];
// .... rest of the code, return NO if the value is not correct ..
}
return YES;
}
The "fieldEditor" appear not good to find out the right column because is not the one expected (by me) ..its superview is _NSKeyboardFocusClipView (??). Suggestion appreciated, and feel free to post swift code as well
(EDIT) corrected code accepted from #Willeke:
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
if ([control isEqualTo: myOutline]) {
id item = [myOutline itemAtRow:[myOutline selectedRow]]; // ok
NSTableColumn *tableCoumn = [[myOutline tableColumns] objectAtIndex:[myOutline editedColumn]];
TreeObj *data = (TreeObj *)[item representedObject];
if ([tableCoumn.identifier isEqualToString:#"theRightColumn"]) {
// .... rest of the code, return NO if the value is not correct and display the alert..
}
}
return YES;
}
The edited row and column are properties editedRow and editedColumn of NSTableView, the superclass of NSOutlineView. The column you're after is [myOutline editedColumn] or myOutline.editedColumn.

Change NSTextField text color, based on validation (bind)

I have a NSTextField with bindings that uses validation - if the value is invalid, the set is never called; if the user tries leave the field with an invalid value, the application shows an error alert with 2 choices (discard or continue editing), and so on...
To have a better UI, I want to change the text color within the validation:
-(BOOL)validateMinValue:(id *)ioValue error:(NSError * __autoreleasing *)outError
{
ParameterValue * param=*ioValue;
if(*ioValue==nil || param.internalValue>_data->maxValue)
{
if (outError != NULL) {
NSString *errorString = #"Minimum value must be less than the maximum value.";
NSDictionary *userInfoDict = #{ NSLocalizedDescriptionKey : errorString };
*outError = [[NSError alloc] initWithDomain:#"minValue-maxValue"
code:1
userInfo:userInfoDict];
}
_minValueField.textColor=[NSColor redColor];
return NO;
}
_minValueField.textColor=[NSColor whiteColor];
return YES;
}
The problem is that, if the users tries to leave the field with an invalid value and if he chooses the "discard change" option on the alert, the value is discarded, but the textcolor continues red (because the systems doesn't re-validate the value that it knows that is valid).
Any suggestions?

Push query object to view controller

I have a query that grabs 10 objects, and I am trying to have an action that shows you a window with more information on the object selected, I am just new to Xcode and cannot figure out how to push the information to the new view controller. Here is the code I have that creates the query.
PFQuery *query = [PFQuery queryWithClassName:#"Arcade"];
CLLocation *currentLocation = locationManager.location;
PFGeoPoint *userLocation =
[PFGeoPoint geoPointWithLatitude:currentLocation.coordinate.latitude
longitude:currentLocation.coordinate.longitude];
query.limit = 10;
[query whereKey:kPAWParseLocationKey nearGeoPoint:userLocation withinMiles:kPAWWallPostMaximumSearchDistance];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d scores.", objects.count);
// Do something with the found objects
int i = 0;
for (PFObject *object in objects) {
if (i >= [self.EventTitles count]) break;//to make sure we only write up to the max number of UILabels available in EventTitles
[(UILabel *)self.EventTitles[i] setText:[object objectForKey:#"name"]];//I assume the "objectId" property of object is an NSString!
i++;
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
and this is the action to push to the new view controller:
-(IBAction)DetailEvent1:(id)sender{
TableDetailViewController *objDetail = [[TableDetailViewController alloc] initWithNibName:#"TableDetailViewController" bundle:nil];
[self addChildViewController:objDetail];
objDetail.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, self.view.bounds.size.height - 0.0f);
[self.view addSubview:objDetail.view];
}
If someone could help me write the one line of code that needs to be added to the DetailEvent1 action so that the chosen object is pushed I would greatly appreciate it.
TableDetailViewController *objDetail =
[[TableDetailViewController alloc]
initWithNibName:#"TableDetailViewController" bundle:nil];
objDetail.query = self.query
In other words, this is the moment you are creating the next view controller. The two view controllers are now in contact (self and objDetail). So this is the moment to pass data across from the one to the other.
Of course, there is no TableDetailViewController property query. Not yet! But you're going to make one, don't you see - so that you can make this exact move.
Oh, and perhaps there is no query property in self either. But you will need one, because you need a way to hold on to the query that you got in that first method so that it is still available to you in the second method. The way to share data between methods of the same object is very often thru a property.
See also this example from my book:
- (void)showItemsForRow: (NSIndexPath*) indexPath {
// create subtable of tracks and go there
TrackViewController *t =
[[TrackViewController alloc] initWithMediaItemCollection:
(self.albums)[indexPath.row]];
[self.navigationController pushViewController:t animated:YES];
}
In that example, I've gone even further: I've actually given TrackViewController a designated initializer so that I can create it and hand it the data all in one line.

ABPeoplePickerNavigationController completion handler trying to find text in the cells and get Null

Got a ABPeoplePickerNavigationController and after its displayed I want to search through the cells and find the text i.e. user names displayed. I then want to check the users if they are contained in a coredata NSSet... My issue, I can't seem to get the text back from the cells just Null. I know the cells are the correct ones as I can happily play with the cell accessory type. Sample code shown:
[self presentViewController:picker animated:YES completion:^{
// Find the picker tableViewController
UIView *view = picker.topViewController.view;
UITableView *tableView = nil;
for(UIView *uv in view.subviews)
{
if([uv isKindOfClass:[UITableView class]])
{
tableView = (UITableView*)uv;
break;
}
}
// Check tableView not Null then Loop occurs here with this code in it always giving me Null
// I know the tables populated and displayed at this point so why Null ?
.......
NSString *a = [[[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:x]] detailTextLabel] text];
.......
}];
Starting to think this could be related to ios6 privacy controls ?

Resources