Strange behaviour with UITableViewController and UITextFields - objective-c

I'm observing some strange behaviour when working with a UITableViewController and UITextFields in the cells.
The UITextFields delegate is set to the UITableViewController and when entering editing mode the tableview scrolls to the relevant cell, and does not obscure the input with the keyboard.
However, when I present another view controller using
[self presentViewController:vc animated:TRUE completion:^() {}];
And later dismiss it with
[self dismissViewControllerAnimated:YES completion:^{}];
The table stops scrolling and resizing to fit the keyboard.
It does not seem to matter where I call the presentViewController method (in the cell, in the headers or in a toolbar)
Any ideas?
UPDATE 1:
Delegate for my UITextField is set in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath with cell.textField.delegate = self
I only override viewWillAppear:(BOOL)animated:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[GAI sharedInstance].defaultTracker sendView:#"Some view name"];
}
UPDATE 2
Manually calling
[self dismissViewControllerAnimated:YES completion:^{
[self viewWillAppear:YES];
}];
Fixes it, but i'd still like some input to why this is necessary ?

Somewhere in the view hierarchy I had missed a call to [super viewWillAppear:].

Related

UISearchBar in UIView

I'm having difficulty following directions. I have a UISearchBar in a UIView. The user will enter the search string into the UISearchBar and click the search icon to search. The results will display in a new window (UITableView).
My search has shown me this:
A UISearchDisplayController cannot be added to a UIView because it
doesn't inherit from a UIView. You can add a UISearchBar in Interface
builder with an IBOutlet and then create a UISearchDisplayController
with that UISearchBar programmatically.
Just do it in code e.g. (assuming the view controller is vc): [vc
addSubview:mySearchDisplayController.searchBar]; // Note that
searchBar is the view, and mySearchDisplayController only CONTROLS the
searchBar etc.
and also this:
Just make your view controller implement the UISearchBarDelegate. In
your xib file, all you need to do is to add a UISearchBar to your view
and configure it as necessary, create an outlet for it (optional
really but helps to be explicit), and assign the delegate outlet to
your view controller. Then, to respond to the search bar events,
implement the UISearchBarDelegate protocol methods as necessary. For
example:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self handleSearch:searchBar]; }
(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[self handleSearch:searchBar]; }
(void)handleSearch:(UISearchBar *)searchBar {
NSLog(#"User searched for %#", searchBar.text);
[searchBar resignFirstResponder]; // if you want the keyboard to go away }
(void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
NSLog(#"User canceled search");
[searchBar resignFirstResponder]; // if you want the keyboard to go away }
I'm just not getting it! Should I be adding mySearchController to my UIView? or my UISearchBar? Adding it to my UIView, nothing happens; adding it to my UISearchBar really wigs out the application. I don't even get an error - it just hangs.
Then, there is the second part: The delegate. Should I put the delegate in my UIView? Or in the UISearchDisplayController? Not sure which direction to go in and nothing so far is working. Please help.
All I really want at this point is just to get the handleSearch method to get executed. Thank you very much in advance for any help.
Very confused.
The idea is that you create a Search Bar in Interface Builder as an outlet and then use the following code to create UISearchDisplayController:
self.searchDisplayController2 = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController2.delegate = self;
self.searchDisplayController2.searchResultsDelegate = self;
self.searchDisplayController2.searchResultsDataSource = self;
This code would be implemented in your View Controller, say in viewDidLoad. You will also have to implement at least two delegate functions in the same VC:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

Cannot dismiss the Search view

I have a parent class with tableview and searchbar over it which is a subclass of tableview controller. Delegates for the searchBar and searchdisplaycontroller are set in a seperate class inherited from UISearchdisplaycontroller. The datasource and delegates for tableview and searchbar are handled in this class seperately. The classes are under ARC.
Hence, When a user taps on search, the control transfers from FilesListController (parent)class to this class. Now, When a user taps on cancel button, the searchbar delegate set in this class i.e.
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar
is CALLED but DOESN'T serve the purpose of dismissing the full screen searchtableview and return to the parentviewcontroller. However, if I don't write this delegate in the search class, it works properly. I have set the searchbar delegates in xib and on calling:
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
like this:
self.searchResultsTableView.delegate = self;
self.searchResultsTableView.dataSource = self;
[parentFileViewController.searchDisplayController setDelegate:self];
Where am I going wrong? Thanks in advance.
If you want to dismiss a UISearchBar with a SearchBarController, just use this Code:
[self.searchDisplayController setActive:NO animated:YES];
you should implement resign the responder in the delegate function i.e
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
[searchBar resignFirstResponder];
}
Memory warnings can appear at any time during the application run time, you must assume a memory warning will happen and the view and disposable objects will have to be recreated.
We are handling such situation by setting to nil our arrays:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if([self isViewLoaded] && self.view.window == nil)
{
self.view = nil;
keys = nil;
names = nil;
errorDuringNetworkCall = nil;
}
}
And by dismissing the search bar tableview before performing the segue operation:
[self performSegueWithIdentifier:#"navigateToNextScreen" sender:self];
self.searchBar.text = #"";
[self.searchDisplayController setActive:NO animated:YES];
After a Memory warning is received the viewDidLoad method is called again and the arrays are populated, the search bar will continue to be useful.work without issues

UIWebView on top of UINavigationController stack not shown

I have a UIViewController "PdfViewController" with a view containing an UIScrollView wich is containing an UIWebView, designed by storyboard. I'm using storyboard in Xcode 4.2 with ARC.
If I start PdfViewController as initial ViewController the webview is shown as expected.
I want the PdfViewController to show a PDF from a list of PDF's. So I made a NavigationController containing a TableViewController with the document titles.
If I try to show the PdfViewController by "tableView didSelectRowAtIndexPath" the view stays black and doesn't load the selected document.
There is no errer message from Xcode.
The viewDidLoad and the viewWillAppear from PdfViewController get called.
Here the initialisation of the PdfViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PdfViewController *pdfViewController = [[PdfViewController alloc]init];
[pdfViewController setFileName:#"test"];
[self.navigationController pushViewController:pdfViewController animated:YES];
}
-It seems, the problem is that the PdfViewController does not load the corrsponding nib by itself.
If I make a seque from the TableViewCell, the PdfViewController is loaded correctly.
I changed the code to:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.navigationController.viewControllers.lastObject setFileName:#"test"];
}
The only thing to know here, is that the viewDidLoad und viewWillAppear are called before the execution of tableView didSelectRowAtIndexPath, so the PDF has to be loaded in viewDidAppear.
With Xcode 4.2 or later, you can pass the data between two view controllers via segue.
Please Check:
How to pass prepareForSegue: an object
Your code may look like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([[segue identifier] isEqualToString:#"__YOUR_SEGUE_STRING__"]) {
PdfViewController *pdfViewController =
(PdfViewController*)[segue destinationViewController];
//
// write your code here
//
[pdfViewController setFileName:#"test"];
}
}

Trigger setEditing: animated: without using an edit button

I have a UITableView with some custom cells in it. In these custom cells I defined a UILongPressGestureRecognizer that triggers the edit mode of this table. So when someone presses and holds a cell for like 1.5 sec, the table goes into edit mode.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(startEditMode:)];
Which triggers:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
[table setEditing:YES animated:YES];
}
}
But what I want to do is detect when the table goes into edit mode because I need to show/hide some additional buttons in this case. But for some reason in my viewcontroller this is never executed:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
NSLog(#"SET EDITING");
[super setEditing:editing animated:animated];
}
Any suggestion why? Is this just being called when using a proper Edit Button as provided by default in the UINavigationController?
Or how can I detect when my UITableView goes into Edit Mode?
You're sending the message (setEditing) to the table view, you should be sending it to the view controller (presumably a UITableViewController subclass?). It will then take care of the table view for you.
Ok so in case someone else walks into this thread with the same problem, I will show you how I solved this.
In my custom UITableViewCell I have this method now:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
UITableViewController *control = (UITableViewController *)table.dataSource;
[control setEditing:YES animated:YES];
}
}

How to unselect a UITableViewCell after you have done some action using didSelectRowAtIndexPath?

Currently I do some work inside the didSelectRowAtIndexPath delegate and noticed that my row is still "selected" after I come back to the view controller later.
How can I unselect this row inside the delegate itself?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//do logic and ... it remains selected in the view?
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Typically, you want to deselect the row when the view controller appears again:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
That's what UITableViewController does implicitly, and animating the deselection process after the view controller appears again is a helpful hint to the user as to which cell they selected previously.