Tuesday, February 10, 2009

Long Text Generic Editing Controller

Another in my series of generic controller classes intended to be used in a navigation application. This one is for editing longer text. It uses a UITextView instead of a UITextField. There seems to be a bug in UITextView that's keeping me from changing the insertion point to the end of the text, but I have a bug report open with Apple on that, so hopefully either Apple will fix it, or tell me how to work around it. In the meantime, when editing existing values, the user will have to tap at the end of the text before typing.



Its use is nearly identical to the previous generic controller classes I posted. Just set your controller class as the generic controller class' delegate, set the string value you want to let the user edit, then implement the delegate method to get notified of the new value if the user makes any changes.

And here is the code

LongTextFieldViewController.h
//
// LongTextFieldViewController.h
// iContractor
//
// Created by Jeff LaMarche on 2/10/09.
// Copyright 2009 Jeff LaMarche Consulting. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol LongTextFieldEditingViewControllerDelegate <NSObject>
@required
- (void)takeNewString:(NSString *)newValue;
- (UINavigationController *)navController; // Return the navigation controller
@end


@interface LongTextFieldViewController : UITableViewController
{
NSString *string;
UITextView *textView;

id<LongTextFieldEditingViewControllerDelegate> delegate;
}
@property (nonatomic, retain) NSString *string;
@property (nonatomic, retain) IBOutlet UITextView *textView;
@property (nonatomic, assign) id <LongTextFieldEditingViewControllerDelegate> delegate;
- (void)cancel;
- (void)save;
@end



LongTextFieldViewController.m
//
// LongTextFieldViewController.m
// iContractor
//
// Created by Jeff LaMarche on 2/10/09.
// Copyright 2009 Jeff LaMarche Consulting. All rights reserved.
//

#import "LongTextFieldViewController.h"


@implementation LongTextFieldViewController
@synthesize string;
@synthesize textView;
@synthesize delegate;
- (void)cancel
{
[[self.delegate navController] popViewControllerAnimated:YES];
}
- (void)save
{
[self.delegate takeNewString:textView.text];
[[self.delegate navController] popViewControllerAnimated:YES];
}
#pragma mark -
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{


NSUInteger firstRowIndices[] = {0,0};
NSIndexPath *firstRowPath = [NSIndexPath indexPathWithIndexes:firstRowIndices length:2];
UITableViewCell *firstCell = [self.tableView cellForRowAtIndexPath:firstRowPath];
UITextView *firstCellTextField = nil;
for (UIView *oneView in firstCell.contentView.subviews)
{
if ([oneView isMemberOfClass:[UITextView class]])
firstCellTextField = (UITextView *)oneView;
}
[firstCellTextField becomeFirstResponder];



UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(@"Cancel", @"Cancel - for button to cancel changes")
style:UIBarButtonItemStylePlain
target:self
action:@selector(cancel)]
;
self.navigationItem.leftBarButtonItem = cancelButton;
[cancelButton release];
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(@"Save", @"Save - for button to save changes")
style:UIBarButtonItemStylePlain
target:self
action:@selector(save)]
;
self.navigationItem.rightBarButtonItem = saveButton;
[saveButton release];

[super viewWillAppear:animated];
}
- (void)dealloc
{
[string release];
[textView release];
[super dealloc];
}

#pragma mark Tableview methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *LongTextFieldCellIdentifier = @"LongTextFieldCellIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LongTextFieldCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:LongTextFieldCellIdentifier] autorelease];
UITextView *theTextView = [[UITextView alloc] initWithFrame:CGRectMake(10.0, 10.0, 280.0, 161.0)];
theTextView.editable = YES;
theTextView.text = string;
theTextView.font = [UIFont systemFontOfSize:14.0];
[theTextView becomeFirstResponder];
self.textView = theTextView;
[[cell contentView] addSubview:theTextView];
[theTextView release];
}
// This doesn't work - no matter where I put it. It's almost as if this property is readonly
textView.selectedRange = NSMakeRange([string length], 0);;


return cell;
}

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Nothing for now
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 181.0;
}
@end


No comments:

Post a Comment