I have problem in my project in the search bar code.
Inside the app I added a search bar to my table view at run time. The search worked fine only 2 times!
If I tried to search for third time the search bar did not allow me to enter any input, and returns me to the home page of the app.
// staffArr Array to store the staff objects
// tableData store the data that will display in table
- (void)viewDidLoad {
[super viewDidLoad];
tableData = [[NSMutableArray alloc] init];
[tableData addObjectsFromArray:staffArr];
self.disableViewOverlay = [[UIView alloc]
initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
self.disableViewOverlay.backgroundColor=[UIColor blackColor];
self.disableViewOverlay.alpha = 0;
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[self searchBar:searchBar activate:YES];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
searchBar.text=#"";
[self searchBar:searchBar activate:NO];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self.tableData removeAllObjects];
if([searchBar.text isEqualToString:#""]|| searchBar.text==nil){
[staffTAB reloadData];
return;}
for(NSInteger i=0;i<staffArr.count;i++)
{
staff *sta = (staff *)[self.staffArr objectAtIndex:i];
NSString *name =sta.staff_name;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSRange r = [name rangeOfString:searchBar.text];
if(r.location != NSNotFound)
{
if(r.location== 0)// checking only the start of the names.
{
[tableData addObject:sta];
}
}
[pool release];
}
[self searchBar:searchBar activate:NO];
[self.staffTAB reloadData];
}
- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active
{
self.staffTAB.allowsSelection = !active;
self.staffTAB.scrollEnabled = !active;
if (!active)
{
[disableViewOverlay removeFromSuperview];
[searchBar resignFirstResponder];
}
else
{
self.disableViewOverlay.alpha = 0;
[self.view addSubview:self.disableViewOverlay];
[UIView beginAnimations:#"FadeIn" context:nil];
[UIView setAnimationDuration:0.5];
self.disableViewOverlay.alpha = 0.6;
[UIView commitAnimations];
NSIndexPath *selected = [self.staffTAB indexPathForSelectedRow];
if (selected) {
[self.staffTAB deselectRowAtIndexPath:selected animated:NO];
}
}
[searchBar setShowsCancelButton:active animated:YES];
}
Thanks in advance
Related
I am adding a contact picker in my app, however, I do not want the search functionality.
How to hide/Remove the search bar on Contact Picker (ABPeoplePickerNavigationController)?
static BOOL foundSearchBar = NO;
- (void)findSearchBar:(UIView*)parent mark:(NSString*)mark {
for( UIView* v in [parent subviews] ) {
//if( foundSearchBar ) return;
NSLog(#"%#%#",mark,NSStringFromClass([v class]));
if( [v isKindOfClass:[UISearchBar class]] ) {
[(UISearchBar*)v setTintColor:[UIColor blackColor]];
v.hidden=YES;
// foundSearchBar = YES;
break;
}
if( [v isKindOfClass:[UITableView class]] ) {
CGRect temp =v.frame;
temp.origin.y=temp.origin.y-44;
temp.size.height=temp.size.height+44;
v.frame=temp;
//foundSearchBar = YES;
break;
}
[self findSearchBar:v mark:[mark stringByAppendingString:#"> "]];
}
}
call above method after picker is presented as below:
-(void)showPeoplePickerController
{
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
picker.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
// Display only a person's phone, email, and birthdate
NSArray *displayedItems = [NSArray arrayWithObjects:[NSNumber numberWithInt:kABPersonPhoneProperty],
[NSNumber numberWithInt:kABPersonEmailProperty],
[NSNumber numberWithInt:kABPersonBirthdayProperty],[NSNumber numberWithInt:kABPersonAddressProperty],nil];
picker.displayedProperties = displayedItems;
// Show the picker
[self presentViewController:picker animated:YES completion:nil];
[self findSearchBar:[picker view] mark:#"> "];
[picker release];
}
-(void)showAddressBook {
ABPeoplePickerNavigationController *addressBook = [[ABPeoplePickerNavigationController alloc] init];
[addressBook setPeoplePickerDelegate:self];
addressBook.delegate = self;
addressBook.navigationBar.topItem.title = #"iPhone Contacts";
UIView *view = addressBook.topViewController.view;
for (UIView *v in view.subviews) {
if ( [v isKindOfClass:[UITableView class]] ) {
CGRect temp = v.frame;
temp.origin.y = temp.origin.y - 44;
temp.size.height = temp.size.height + 44;
v.frame = temp;
}
}
[addressBook release];
}
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([navigationController isKindOfClass:[ABPeoplePickerNavigationController class]]) {
UISearchDisplayController *searchDisplayController = navigationController.topViewController.searchDisplayController;
[searchDisplayController.searchBar setHidden:YES];
}
}
Below is the code of ModelController.m:
- (id)init
{
self = [super init];
if (self) {
// Create the data model.
DataHandler *handler = [DataHandler defaultDataHandler];
[handler syncData];
NSInteger tempTotal=1;//[[DataHandler defaultDataHandler] getTotalContents];
NSMutableDictionary *favs=[Settings getSetting:kFavList];
if(favs!=nil){
tempTotal=[favs count]+1;
}
NSInteger TotalItems=tempTotal;//tempTotal>=6?tempTotal:6;
NSInteger PageSize=6;
NSInteger PageNo= (TotalItems/PageSize);
if(TotalItems%PageSize!=0){
PageNo++;
}
self.TotalPage=PageNo;
NSInteger i=0,temp=PageSize;
self.pageArray=[[NSMutableDictionary alloc] initWithCapacity:PageNo];
for (i=0; i<PageNo; i++) {
temp=(PageNo==i+1 && TotalItems%PageSize!=0)? TotalItems%PageSize:PageSize;
[self.pageArray setObject:[NSString stringWithFormat:#"%d",temp] forKey:[NSString stringWithFormat:#"%d",i+1]];
}
//NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//_pageData = [[dateFormatter monthSymbols] copy];
self.pageData=[self.pageArray allKeys];
}
return self;
}
- (HomeViewController *)viewControllerAtIndex:(NSUInteger)index {
NSLog(#"viewControllerAtIndex is called..");
// Return the data view controller for the given index.
if (([self.pageData count] == 0) || (index >= [self.pageData count])) {
return nil;
}
// Create a new view controller and pass suitable data.
HomeViewController *homeViewController = nil;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
homeViewController = [[[HomeViewController alloc] initWithNibName:#"HomeViewController_iPhone" bundle:nil] autorelease];
} else {
homeViewController = [[[HomeViewController alloc] initWithNibName:#"HomeViewController_iPad" bundle:nil] autorelease];
}
homeViewController.dataObject = [self.pageData objectAtIndex:index];
homeViewController.PageItemsCount= [[self.pageArray valueForKey:[NSString stringWithFormat:#"%d",index+1]] integerValue];
homeViewController.TotalPage=self.TotalPage;
homeViewController.CurrentPage=index+1;
return homeViewController;
}
- (NSUInteger)indexOfViewController:(HomeViewController *)viewController
{
// Return the index of the given data view controller.
// For simplicity, this implementation uses a static array of model objects and the view controller stores the model object; you can therefore use the model object to identify the index.
return viewController.CurrentPage-1;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [self indexOfViewController:(HomeViewController *)viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = [self indexOfViewController:(HomeViewController *)viewController];
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.pageData count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
This is working fine when I swipe the screen, but I also want to change screen on any button tap of main view page (in this case it's homeViewController.m), as it's code is very lengthy I didn't post code here.
can anyone tell me how to achieve this?
Thanks
Ashish
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:self.view cache:NO];
[UIView commitAnimations];
//Addd this line on click event of button action
You could simply try and animate the view transform like this (for a vertical flip):
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
animations:^(void) {
view.transform = CGAffineTransformMakeScale(1, -1);
}
completion:nil];
Thanks
This is a localized issue. I'm going to post a lot of code, and provide a lot of explanation. Hopefully... someone can help me with this.
In my application I have a "Facebook-style" menu. The iOS Facebook app, to be more specific. You can access this menu in two different ways. You may either touch the menu button, or swipe to open the menu. When one opens and closes the menu using the button, the tableView:didSelectRowAtIndexPath method fires perfectly upon touching the cell. When one opens and closes the menu using the swipe method... it does not. You have to touch the table cell twice for the method to fire. The code for these methods are exactly the same in several classes, however, this is the only one I have an issue with. Take a look; see if I'm dropping the ball somewhere:
#import "BrowseViewController.h"
#implementation BrowseViewController
#synthesize browseView, table, countriesArray, btnSideHome, btnSideBrowse, btnSideFave, btnSideNew, btnSideCall, btnSideBeset, btnSideEmail, btnSideCancelled, menuOpen, navBarTitle, mainSearchBar, tap;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.font = [UIFont fontWithName:#"STHeitiSC-Medium" size:20.0];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:1.0];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.text = #"Countries";
self.navBarTitle.titleView = label;
[label sizeToFit];
CheckNetworkStatus *networkCheck = [[CheckNetworkStatus alloc] init];
BOOL internetActive = [networkCheck checkNetwork];
if (internetActive) {
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
tap.delegate = self;
tap.cancelsTouchesInView = NO;
UISwipeGestureRecognizer *oneFingerSwipeLeft =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)];
[oneFingerSwipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[[self view] addGestureRecognizer:oneFingerSwipeLeft];
UISwipeGestureRecognizer *oneFingerSwipeRight =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
[oneFingerSwipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[[self view] addGestureRecognizer:oneFingerSwipeRight];
menuOpen = NO;
table.userInteractionEnabled = YES;
NSArray *countries = [[NSArray alloc] initWithObjects:#"United States", #"Canada", #"Mexico", nil];
self.countriesArray = countries;
} else {
//No interwebz, notify user and send them to the home page
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Connection Error" message:#"Failed to connect to the server. Please verify that you have an active internet connection and try again. If the problem persists, please call us at **********" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[message show];
PassportAmericaViewController *homeView = [[PassportAmericaViewController alloc]
initWithNibName:#"PassportAmericaViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:homeView animated:YES];
}
[super viewDidLoad];
}
-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection: (NSInteger)section
{
return [countriesArray count];
NSLog(#"Number of objecits in countriesArray: %i", [countriesArray count]);
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont fontWithName:#"STHeitiSC-Medium" size:20.0];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [countriesArray objectAtIndex:row];
return cell;
}
- (void)tableView:(UITableView *)table
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *countrySelected = [countriesArray objectAtIndex:indexPath.row];
Campground *_Campground = [[Campground alloc] init];
_Campground.country = countrySelected;
StateViewController *stateView = [[StateViewController alloc]
initWithNibName:#"StateView" bundle:[NSBundle mainBundle]];
stateView._Campground = _Campground;
[self.navigationController pushViewController:stateView animated:YES];
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(void) dismissKeyboard {
[mainSearchBar resignFirstResponder];
}
-(IBAction)goBack:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}
-(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if ([animationID isEqualToString:#"slideMenu"]){
UIView *sq = (__bridge UIView *) context;
[sq removeFromSuperview];
}
}
- (IBAction)menuTapped {
NSLog(#"Menu tapped");
CGRect frame = self.browseView.frame;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector( animationDidStop:finished:context: )];
[UIView beginAnimations:#"slideMenu" context:(__bridge void *)(self.browseView)];
if(!menuOpen) {
frame.origin.x = -212;
menuOpen = YES;
table.userInteractionEnabled = NO;
}
else
{
frame.origin.x = 0;
menuOpen = NO;
table.userInteractionEnabled = YES;
}
self.browseView.frame = frame;
[UIView commitAnimations];
}
-(IBAction) sideHome:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
PassportAmericaViewController *homeView = [[PassportAmericaViewController alloc]
initWithNibName:#"PassportAmericaViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:homeView animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideBrowse:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
BrowseViewController *browseView2 = [[BrowseViewController alloc]
initWithNibName:#"BrowseView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:browseView2 animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideBeset:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
BesetCampgroundMapViewController *besetMapView = [[BesetCampgroundMapViewController alloc]
initWithNibName:#"BesetCampgroundMapView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:besetMapView animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideFave:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
FavoritesViewController *faveView = [[FavoritesViewController alloc] initWithNibName:#"FavoritesView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:faveView animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideNew:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
NewCampgroundsViewController *theNewCampView = [[NewCampgroundsViewController alloc]
initWithNibName:#"NewCampgroundsView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:theNewCampView animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideCancelled:(id)sender{
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
menuOpen = NO;
CancelledCampgroundsViewController *cancCampView = [[CancelledCampgroundsViewController alloc]
initWithNibName:#"CancelledCampgroundsView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:cancCampView animated:YES];
table.userInteractionEnabled = YES;
}
-(IBAction) sideCall:(id)sender{
NSLog(#"Calling Passport America...");
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:**********"]];
table.userInteractionEnabled = YES;
}
-(IBAction) sideEmail:(id)sender{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"mailto:***************"]];
table.userInteractionEnabled = YES;
}
-(void) searchBarSearchButtonClicked: (UISearchBar *)searchBar {
SearchViewController *search = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:[NSBundle mainBundle]];
NSString *searchText = [[NSString alloc] initWithString:mainSearchBar.text];
search.searchText = searchText;
[self dismissKeyboard];
[self.navigationController pushViewController:search animated:YES];
table.userInteractionEnabled = YES;
menuOpen = NO;
CGRect frame = self.browseView.frame;
frame.origin.x = 0;
self.browseView.frame = frame;
}
-(void) swipeLeft:(UISwipeGestureRecognizer *)recognizer {
if (!menuOpen) {
CGRect frame = self.browseView.frame;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector( animationDidStop:finished:context: )];
[UIView beginAnimations:#"slideMenu" context:(__bridge void *)(self.browseView)];
frame.origin.x = -212;
menuOpen = YES;
self.browseView.frame = frame;
table.userInteractionEnabled = NO;
[UIView commitAnimations];
} else {
//menu already open, do nothing
}
}
-(void) swipeRight:(UISwipeGestureRecognizer *)recognizer {
if (!menuOpen) {
//menu closed, do nothing
} else {
CGRect frame = self.browseView.frame;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector( animationDidStop:finished:context: )];
[UIView beginAnimations:#"slideMenu" context:(__bridge void *)(self.browseView)];
frame.origin.x = 0;
menuOpen = NO;
self.browseView.frame = frame;
table.userInteractionEnabled = YES;
[UIView commitAnimations];
}
}
- (void) viewWillDisappear:(BOOL)animated {
[self.table deselectRowAtIndexPath:[self.table indexPathForSelectedRow] animated:animated];
[super viewWillDisappear:animated];
}
- (void)didReceiveMemoryWarning {
NSLog(#"Memory Warning!");
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
self.table = nil;
self.countriesArray = nil;
self.browseView = nil;
[super viewDidUnload];
}
#end
Determine which cell the swipe takes place in, compute the index path, and call didSelectRowAtIndexPath from your gestureRecognizer code.
I have a page controller and that method pageAction defined like this :
-(void)pageAction:(UIPageControl*)control
{
NSLog(#"page changed");
[self getVehicules];
[self.tableViewVehiculesPossedes release];
int page = pageControlVehiculePossedee.currentPage;
NSLog(#"page %d", page);
[self loadScrollViewWithPage:page];
CGRect frame = pageControlVehiculePossedee.frame;
frame.origin.x = (vosvehiculeScrollView.frame.size.width * page);
[vosvehiculeScrollView scrollRectToVisible:frame animated:YES];
pageControlUsed = YES;
}
Every time I change the page I need to display a tableview with some labels. Here is the code :
- (void)viewDidLoad
{
[super viewDidLoad];
[self getVehicules];
vosvehiculeScrollView.pagingEnabled = YES;
vosvehiculeScrollView.showsHorizontalScrollIndicator = NO;
vosvehiculeScrollView.showsVerticalScrollIndicator = NO;
vosvehiculeScrollView.scrollsToTop = NO;
pageControlVehiculePossedee.numberOfPages=[vehiculesPossede count];
pageControlVehiculePossedee.currentPage=0;
[self loadScrollViewWithPage:0];
[pageControlVehiculePossedee addTarget:self action:#selector(pageAction:) forControlEvents:UIControlEventValueChanged];
votreVehiculeLabel.text=#"Votre véhicule";
vehiculesPossedesArray = [[NSMutableArray alloc] initWithObjects:#"Annee modele", #"Transmission",#"Carburant", nil];
}
- (void) loadScrollViewWithPage: (int) page {
if (page < 0) return;
if (page >= [vehiculesPossede count]) return;
tableViewVehiculesPossedes=[[UITableView alloc] initWithFrame:CGRectMake(3, 80, 315, 171) style:UITableViewStyleGrouped];
tableViewVehiculesPossedes.tag=page;
tableViewVehiculesPossedes.bounces=NO;
tableViewVehiculesPossedes.backgroundColor=[UIColor clearColor];
[tableViewVehiculesPossedes setDelegate:self];
[tableViewVehiculesPossedes setDataSource:self];
[self.vosvehiculeScrollView addSubview:tableViewVehiculesPossedes];
nameVehiculeLabel.text=[[vehiculesPossede objectAtIndex:page] valueForKey:#"modele"];
self.transmissionString=[[vehiculesPossede objectAtIndex:page]valueForKey:#"transmision"];
self.carburantString=[[vehiculesPossede objectAtIndex:page] valueForKey:#"carburant"];
self.anneeModelString=[[vehiculesPossede objectAtIndex:page] valueForKey:#"modele_annee"];
self.anneeString=[[vehiculesPossede objectAtIndex:page]valueForKey:#"annee"];
if(page==0){
NSLog(#"0");
self.transmissionString=#"ttt";
}
else NSLog(#"1");
}
The problem is that even I put [self.tableViewVehiculesPossedes release]; on the change page method, the tableView appear overlay and the text from labels are overlay. What can I do with the tableview to make it dissapear when a new page will be display?
Please help me..I spent a lot of time with this :|
If I get it correctly I think you should keep an ivar to the table you create with the alloc in loadScrollViewWithPage, and when switching page you should removing it from the view by calling :
[mytableview removeFromSuperview];
And most likely your should take care of releasing it as well as I can't see it in your code.
I've successfully embedded a UITextView inside a UITableViewCell, and most of the table is working fine. However, when I enable editing on the UITextView and start editing, the table shifts up too far, obscuring the cursor. Is there a way to control how far the tableview scrolls? Manually scrolling the view to the cell works, but the view still scrolls up before scrolling back down and into view.
Here is an example of what I mean:
editing a UITextField - the field is neatly placed directly above the keyboard.
http://imageshack.us/photo/my-images/13/textfield.png/
editing a UITextView - the field is placed significantly above the keyboard removing the toolbar from the keyboard doesn't affect anything)
http://imageshack.us/photo/my-images/809/textview.png/
Here's all the code that is relevant to the UITextView in the UITableViewController object:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillShow:)
name: UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillHide:)
name: UIKeyboardWillHideNotification object:nil];
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
viewTargetedForEditing = (UIView *)textView;
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[self.navigationController setNavigationBarHidden:YES animated:YES];
// shrink the textView to fit on-screen
originalTextViewFrame = textView.frame;
CGRect keyboardRect = [[keyboardUserinfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardRect.size.height;
CGRect newViewFrame = textView.frame;
CGFloat spaceAboveKeyboard = self.containerView.frame.size.height - keyboardHeight;
newViewFrame.size.height = (spaceAboveKeyboard < textView.frame.size.height) ? spaceAboveKeyboard : textView.frame.size.height;
/* animate the calculations */
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[keyboardUserinfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
textView.frame = newViewFrame;
[UIView commitAnimations];
// recalculate the keyboard height, in case we aren't in portrait mode
CGFloat toolbarHeight;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
toolbarHeight = 44.0;
} else {
toolbarHeight = 32.0;
}
CGRect frame = textView.inputAccessoryView.frame;
frame.size.height = toolbarHeight;
}
- (void)endTextViewEditing
{
[viewTargetedForEditing resignFirstResponder];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
#pragma mark - Keyboard Notifications
- (void)keyboardWillShow:(NSNotification *)notification
{
[keyboardUserinfo release];
keyboardUserinfo = [[notification userInfo] retain];
[self viewDidBeginEditing:viewTargetedForEditing];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[keyboardUserinfo release];
keyboardUserinfo = [[notification userInfo] retain];
[self viewDidEndEditing:viewTargetedForEditing];
}
- (void)viewDidBeginEditing:(id)aView
{
// called 2nd
UITableViewCell *cell = (UITableViewCell *)[aView superview];
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)viewDidEndEditing:(id)aView
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[viewTargetedForEditing superview]];
gallupAppDelegate *appDelegate = (gallupAppDelegate *)[[UIApplication sharedApplication] delegate];
switch (indexPath.section) {
case SectionDescription:
if (![[(UITextField *)aView text] isEqualToString:self.plan.Description]) {
self.plan.Description = [(UITextField *)aView text];
[appDelegate saveManagedContext];
}
break;
case SectionNotes:
if (![[(UITextView *)aView text] isEqualToString:self.plan.Notes]) {
self.plan.Notes = [(UITextView *)aView text];
[appDelegate saveManagedContext];
}
break;
case SectionLocation:
if (![[(UITextField *)aView text] isEqualToString:self.plan.Location]) {
self.plan.Location = [(UITextField *)aView text];
[appDelegate saveManagedContext];
}
break;
}
}
The TextViewCell is a subclass of UITableViewCell, and it is the cell that is giving me the problem with scrolling.Here's the implementation:
#implementation TextViewCell
#synthesize contents=_contents;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_contents = [[UITextView alloc] initWithFrame:CGRectZero];
[self addSubview:_contents];
self.contents.font = [UIFont systemFontOfSize:17];
self.contents.dataDetectorTypes = UIDataDetectorTypeAll;
CGRect frame = CGRectMake(0, 0, self.window.frame.size.width, 44.0);
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(endTextViewEditing)];
UIToolbar *textViewToolbar = [[UIToolbar alloc] initWithFrame:frame];
textViewToolbar.barStyle = UIBarStyleBlackOpaque;
[textViewToolbar setItems:[NSArray arrayWithObjects:spacer, done, nil]];
self.contents.inputAccessoryView = textViewToolbar;
}
return self;
}
- (void)endTextViewEditing
{
[self.contents resignFirstResponder];
}
#define LEFT_MARGIN 15
#define TOP_MARGIN 5
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat width = self.frame.size.width - (LEFT_MARGIN *2);
CGFloat height = self.frame.size.height - (TOP_MARGIN *2);
self.contents.frame = CGRectMake(LEFT_MARGIN, TOP_MARGIN, width, height);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
//[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc
{
[super dealloc];
}
#end
As it turns out, subclassing the UITableView and implementing the following fixed the problem:
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
[super setContentOffset:contentOffset animated:animated];
return;
static int i = 0;
if (0 == i) {
i++;
} else {
i = 0;
[super setContentOffset:contentOffset animated:animated];
}
return;
}
Apparently the -setContentOffset:animated: message was sent 2x, and if the first one is allowed to run the second time round doesn't do it's job properly.
Does anyone have any insite as to why this would fix the problem?