Making a tableviewcell scroll up on displaying keyboard - iphone

I have a UITableViewCell with UITextField. In the edit mode, when the keyboard comes up, the row I am trying to edit gets overlapped by the keyboard. Ideally the row should scroll up so that I can edit the cell.
I have searched stackoverflow throughly and found several different solutions. Most of them has to do with calculations to move or scroll the view up. Now there is a sample code from apple called TaggedLocations. They have the exact same behavior. And there is no code doing any complex calculations to move the view up.
I also thoroughly checked the IB interface and could not find any fancy thing going on either. If you download and run the code, it beautifully pushes up the row to a perfect position for the edit.
Does anybody know what trick is there in the TaggedLocations project which does this so elegantly? Location of the project:
http://developer.apple.com/library/ios/#samplecode/TaggedLocations/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40008914
For the complex calculations I was referring, look at the following thread for example:
How to make a UITextField move up when keyboard is present?
thanks

This line in RootViewController.m is what causes the scroll:
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Put that in your cellForRowAtIndexPath: method and it should work.

I figured out the problem.
Initially I had
TabBarController
- UIViewController
-- UINavigationController
--- UITableViewController
- UIViewController
- -UINavigationController
--- UITableViewController
With this kind of a hierarchy the table cells do not roll up when keyboard is displayed. But if I change the hierarchy to the following the rolling up happens just fine without any additional code!
TabBarController
- UINavigationController
-- UITableViewController
- UINavigationController
-- UITableViewController
When I duplicated the Apple code, I somehow messed up the hierarchy. Now on switching to the new hierarchy, it works fine.
No additional code or calculation necessary.

or call viewWillAppear if you have your own hierarchy of controllers... then table views will automatically scroll cells to be visible when keyboard appears.

I had a similar confusion with Apple's sample code TaggedLocations, although in my case I realized that my table view was being managed by a UIViewController subclass as opposed to a UITableViewController subclass, and UITableViewController apparently manages the scrolling for you. It works quite well, so a lot of these complex calculations are unnecessary. I wish I didn't spend so much time trying to figure them out.
I don't see why the hierarchy you describe would matter. As long as the UITableViewController is managing the text fields, it should automatically take care of the scrolling to avoid the keyboard.

Related

Custom UIScrollView with NSNotification

I have a situation here which I am trying to resolve, but it seams I am missing something.
My architecture of the application is as following:
AppDelegate (TabBarController)
Navigation Controller
Viewcontroller one
Viewcontroller two
Viewcontroller three
Viewcontroller
Since I have lot of text validations and scrolling enabled, I am using a custom uiscrollview for viewcontroller one, two and three. In the custom uiscollview I am utilizing the code from Apple which causes scrollview to scroll if the textfield is being hidden behind the keyboard. The problem which I am occuring at this point is that I have the viewcontroller one working fine, but when it comes to viewcontroller two and three, it does see's that custom view controller after debugging, and reaches the point of "setContentOffSet" but not animating the scrollview, but just displaying the keyboard.
If anyone had this issue before, I would like to see what might I be missing here?

Separate UITableView Controller/Delegate Reference Quandary

I've been following the guide in the following (StackOverflow question), which has been very helpful, and by completing the steps I've managed to successfully have a UITableView with a separate controller and delegate/datasource.
However, even though everything is working, I'm unable to reference or change anything instance of the UITableview.
For example: let's say the UIViewController for the table is TableViewController and the separate delegate/datasource class is TableDelegate. I have everything hooked up in interface builder as in the previous SO question. In TableDelegate.m, within viewDidLoad, I put the following:
self.navigationItem.leftBarButtonItem = self.editButtonItem;
And nothing changes in the UITableView as it should. This includes pushing UIViewControllers, which also has no effect as if the code wasn't even there, although when I NSLog(), it appears it is being run.
The odd part, however, is that even though that doesn't work, if I set the table's alpha property to 0, it works.
Thanks for any help in advance, let me know if you need any more information to solve the problem.
From your comments, it looks like both TableViewController and TableDelegate are subclasses of UIViewController. If this is the case, make sure both are being added to the navigation stack by pushing them onto a UINavigationController or adding them to a UITabBarController: otherwise, viewDidLoad may not be called.
As an aside, I don't think it's a good idea to have your UITableViewDataSource be a UIViewController subclass when you've already got a UITableViewController to handle that table view.

NIB File Doesn't Display at Runtime

I am pulling my hair out on this one. I have a NavigationController with two levels of TableViews. Each TableView is in its own NIB file. The first level simply displays a list. Upon selecting a cell, it takes the user to a second level TableView with a more detailed list. It is on this second level TableView that I want to display a search bar (actually I am using a SearchDisplayController as well). I have added it to the TableView because I want the SearchBar to scroll with the table.
Below, I am displaying two screenshots. The first is the second level tableview in InterfaceBuidler. The second is the second level tableview at runtime. For some reason, the SearchBar doesn't display at runtime.
I have tried creating a completely new project from scratch and the same things happens. I don't understand why the SearchBar doesn't display on a NIB pushed on the NavigationController.
Before you ask, if I put the SearchBar on the first level TableView, it shows up just fine. Yes, I am adding it to the TableView itself, so it is a part of the view that should be displayed.
Help! What am I doing wrong?
This is what actually displays after the XIB is pushed...
Okay, I'm going to have to answer my own question. I thought about deleting it, but perhaps this could help someone else. I really pulled my hair out on this one. It wasn't because of anything I was doing wrong so much as a fundamental misunderstanding of how iPhone development works.
In a nutshell, the problem was with this line of code, which instantiated the TableViewController:
self.downloadDetailViewController = [[DownloadDetailTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
When you use XCode to create a new class, you can use the following:
"Add -> New File -> Cocoa Touch Class -> UIViewController subclass -> UITableViewController
subclass AND With XIB for user interface"
The problem is that the NIB has absolutely nothing to do with the UITableViewController until you tell your code to use it. To me, this seems like a bug in XCode or at the very least something that is counterintuitive. When the development environment creates all three files together, it would only make sense that they would work together, but they don't.
Instead, the solution is to modify the line of code as follows:
self.downloadDetailViewController = [[DownloadDetailTableViewController alloc] initWithNibName:#"SecondaryView" bundle:[NSBundle mainBundle]];
Hopefully this can help someone else...
You could also set Nib Name property on your Download View Controller under the Tab Bar Controller, in fact that and coupled with setting the class with your class name will automatically create the view for you and you don't have to manually create it.
I think the problem is that you are adding the searchbar to the tableView, so it is not displaying.
Try to add that searchBar with out adding to the table view, that means move the table view some what down and add the search bar to the view(not the tableview).

hidesBottomBarWhenPushed and a pushy UISearchBar on short UITableViews

I'm working on an application that has a view hierarchy that is very similar to Apple's Music or iPod aps. It has a UITabBarController containing UINavigationControllers presenting UITableViews that eventually lead to a UIViewController that sets hidesBottomBarWhenPushed to YES in its designated initializer (to hide the UITabBar). The previous UITableViews all have a UISearchBar in their tableHeaderView that I move out of sight in viewWillAppear:.
The UISearch normally remains hidden until pulled down except when backing out of the UIView to a short UITableView. It remains hidden through the UITableView's viewWillAppear: and viewDidAppear: methods and the UIView's viewWillDisappear: and viewDidDisappear: methods and then finally pops down of its own accord. If I comment out self.hidesBottomBarWhenPushed = YES; in the UIView the UISearchBar stays hidden when backing out of that view.
What is causing the UITableView to reveal the UISearchBar after I have hidden it? Is there a delegate method higher up in the view hierarchy that I can use to prevent it from happening?
Update I've created a simple project with the minimum amount of code needed to reproduce the problem. Download PushySearchBar.zip. (Sorry, I had a mod_rewrite rule preventing downloads from third-party domains. I've added Stack Overflow to the whitelist. Download should work now.)
Does the UISearchBar have text in it when backing out of the UIViewController? Seems plausible that this might cause it to be displayed by default.
EDIT: (adding below comment to body of answer for easier scanning / finding, plus adding some explanation.)
Duplicate your viewWillAppear: method body in viewDidAppear: in SearchableTableViewController. This fixes the issue in my testing.
Basically, all this does is ensure that the offset is set correctly on either side of the navigation animation.
Shaun - I'm still learning Objective-C too so I might be off on this, but I think the issue is that ViewWillAppear: fires once when you get to the SearchableTableView 3 view, and then when you try to go backwards from Terminal to SearchableTableView 3 it's not firing again. I duplicated the code in ViewWillAppear: and put it in ViewDidAppear: and the search bar appears to be hiding properly.
UPDATE: This post seems to verify the above and offer cleaner solutions: iPhone viewWillAppear not firing

UIToolbar above a Keyboard - iPhone SDK

I have seen this question posted several times with no useful answers. I am trying to place a toolbar above my UIKeyboard in my iPhone app, but am having difficulty. I found this example which works GREAT, except that my view is a UITableView instead of the standard [self.view addsubview:...]. Can anyone figure out how to apply this to a UITableView?
In short, I have several UITextFields in my table cells, so I want the toolbar to appear above the keyboard for those cells.
Many thanks,
Brett
Just don't use the table view directly as a view.
Use a view that will have a table view inside it.
This way you will be able to use the tutorial as is...
In my opinion this way is much better - I don't have view controller with a single table view in any of my applications. There is always something additional on the screen...
In addition, I don't think that using parentViewController is good solution.
Not always you have one.
Actually, I don't even understand how it works for you...
A work around for this would be to create a hidden textfield in a viewcontroller and present it modally with it begin the first responder. The view can be completely transparent and the toolbar can be configured using the interface builder.