UITable on a scrollView, UITable not acting on reloadData call - objective-c

I've got a scroll view, with 2 UITables on it.
Everything about the table work well. Neither of the tables need to scroll themselves.
If I call
[self.tableOne reloadData]; when a button is pressed it works. But when I call it in a delegate method of UITextView it does not action. Is this some threading issue? Or what is causing this bizarre behavior.
I want to increase the size of a TableCell when the user presses on UITextView thats in each cell.
I added a NSLog here to confirm that this method is getting called.
- (void)textViewDidBeginEditing:(UITextView *)textView
{
theTableCellCurrentlyBeingEdited = textView.tag;
[self.tableOne reloadData];
}
Gets touched I note which cell is active, and call reload table so I can adjust the height of this cell in
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath
{
if (theTableCellCurrentlyBeingEdited == indexPath.row)
{
return 120;
}
else
{
return TABLE_CELL_HEIGHT;
}
}
But heightForRowAtIndex never gets called.
I have tableOnes datasource and delegate set to self.
In my .h I have added
<UITextViewDelegate, UITableViewDelegate, UITableViewDataSource>
So the calls are getting here.
Anybody able to give me some advice as to what is going wrong?
Many Thanks,
-Code

First of all. Where do you call the text of the textView?
You are using theTableCellCurrentlyBeingEdited = textView.tag;
And the tag will not give you the text you entered. You are just changing the tag of your cell which won't change a thing to the visuals of the cell.
Second. Why not call:
- (void)textViewDidChange:(UITextView *)textView
or
- (void)textViewDidEndEditing:(UITextView *)textView
So that in the first delegate method your cell gets updated every char you write and in the second you are sure the user is done writing in the textview?

Related

didSelectRowAtIndexPath not being called, i have tried every method on overflow, any other reason can cause this bug?

I have checked out every similar question and every answer,I have implemented with code. I have set
self.tableView.allowsMultipleSelection = NO;
self.tableView.allowsSelection = YES;
self.tableView.userInteractionEnabled = YES;
Check out the method name of what i expect of is didSelectRowAtIndexPath . There is
no UITapGestureRecognizer.UI Hierarchy shows nothing on the cell.
I have not implemented the method: willSelectRowAtIndexPath, shouldHighlightRowAtIndexPath, tableView:didDeselectRowAtIndexPath.
My custom cell is clean without xib.
Tapping the cell doesn't work ,but dragging the cell works and calls didSelectRowAtIndexPath.
Is there anyone know any other reason that can cause this bug?
wired! I have try take this UITableViewController into a demo and show, but in this demo it worked. Maybe some method in my project block didSelectRowAtIndexPath. How can find which method has blocked? How can I catch the tap event ,and find out which method has happened
If you are using UITableViewController inside a UIViewController, please check if you set the delegate & datasource of the UITableViewController or not.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
check return height is correct. You can set cell backgroundColor to check cell frame.

How to trigger complete: method for a NSTextFieldCell, in order to display the autocomplete list?

When I use NSTextView is easy to trigger the autocomplete popup with the list of suggestions, with the method complete: or by pressing F5.
I'm trying to have the same with a NSTextFieldCell. F5 works very well, but I don't have the method complete: and therefore I can't open such menu programmatically. How to solve it ?
This is what I've tried:
implement the NSTextField delegate method textShouldBeginEditing: but such method is only invoked after a key is pressed and not when the cell gets focus
override becomeFirstResponder in a subclass of NSTextFieldCell but such method is never invoked. And in any case, even if it was, I wouldn't know how to implement it, since, as I said before, the complete: method is not part of the cell APIs.
implement
- (BOOL)tableView:(NSTableView *)tableView shouldTrackCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
but such method is invoked before the cell enters in edit mode, and again, I wouldn't know what to do as in point 2.
thanks
Solution:
Subclass the NSTextFieldCell and override this method to customize its NSTextView
- (NSTextView *)fieldEditorForView:(NSView *)aControlView
{
return [[[CBAutocompleteTextField alloc] init] autorelease];
}
Subclass the NSTextView (CBAutocompleteTextField in my case) and add this to trigger the autocomplete when it gets focus:
-(BOOL)becomeFirstResponder
{
[self performSelector:#selector(complete:) withObject:nil afterDelay:0.01];
return YES;
}

How to get textFields in custom UITableView

Very beginner obj-c question.
I have plain UITableView with two sections, but I am interested only in first section now. This section have four custom cells (inherited from standard UITableViewCell), and they have a UITextField's as a property.
I need to improve custom Input Accessory View with buttons "Next", "Previous"(for switch between textFields in tableview) and "Done" (dismissimg of keyboard). http://uaimage.com/image/62f08045
In -textFieldShouldReturn i set tags for textFields from 0 to 3. My next plan is to add textFields into NSMutableArray in -viewDidLoad and then just set and resign first responder for the textFields. Approximate code listing for "Next" button:
- (void) inputAccessoryViewDidSelectNext:(FDInputAccessoryView *)view {
for (UITextField *textField in [self textFieldsArray]) {
if ([textField isFirstResponder]) {
[textField resignFirstResponder];
UITextField *field = [[self textFieldsArray] objectAtIndex:textField.tag + 1];
[field becomeFirstResponder];
}
}
}
Questions:
Is this a right way or maybe there is a better approach to solve problem?
Do I need to tag textfields or use indexPath of cells in what they are built in? (or what is the best to track textFields?)
And the main question: what is the syntax to "get" textField from cell?
Sorry for the dumb questions, I am a very beginner.
Thanks,
Alex.
I think you have the right idea, but a few things come to mind:
Just to be safe, don't start with tag number 0. Every view has a tag number defaulted to 0, so you may get something unexpected.
Don't set the text view's tags inside of the textFieldShouldReturn, set the tags in cellForRowAtIndexPath or viewDidLoad, wherever you init the textFields.
Add the textFields to the cell's contentView, not the cell itself.
You don't have to resign first responder from the first text field, you can just becomeFirstResponder on the new one.
Make sure you're handling the last text view edge case: You could loop around to the first text field or simply dismiss the keyboard at the end.
If you want to get the textField in the cell:
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:
[NSIndexPath indexPathForRow:ROW_NUMBER inSection:1]];
UITextField *textField = (UITextField *)[cell.contentView viewWithTag:TEXT_FIELD_TAG];

Why does an empty tableView check the number of sections but a non-empty one does not?

I have set up a demo application with a simple UITableViewController with no contents, but an 'Add' button in the toolbar. This launches a modal view controller which is again empty other than a 'cancel' button. The cancel button just tells its delegate (the UITableViewController) to dismiss the modal.
I then added an NSLog statement in the UITableViewController's numberOfSectionsInTableView method.
Ordinarily, when the table view controller loads I see two calls to numberOfSectionsInTableView. When I open and dismiss the modal (which returns to the UITableViewController) I see no further calls to numberOfSectionsInTableView.
However, if I return 0 from numberOfSectionsInTableView, in addition to the two calls on display, I also see an additional numberOfSections call when the modal is dismissed.
This only happens when numberOfSectionsInTableView returns 0, and I have added no additional code to my project besides that mentioned. This is easily verifiable by setting up a couple of controllers as I've described and modifying the result from numberOfSectionsInTableView.
My questions:
Why is the UITableView calling numberOfSectionsInTableView on return from a modal view?
Why is it only doing this if numberOfSectionsInTableView returns 0?
In addition to numberOfSectionsInTableView, the UITableViewController is also calling cellForRowAtIndex: when the modal is dismissed. In fact, it is attempting to display the new contents of its dataSource. How am I meant to manually animate a row insertion if the first row added is going to already be updated automatically? Shouldn't it be left to me to make sure that my UITableView is consistent with its dataSource?
What property is the UITableViewController checking to know that there is one or more sections (and therefore ask my delegate how many sections)? It can't be numberOfSectionsInTableView itself, since I would see it called whenever I return from the modal, not only when numberOfSections = 0.
From UITableViewController docs:
When the table view is about to appear the first time it’s loaded, the
table-view controller reloads the table view’s data... The
UITableViewController class implements this in the superclass method
viewWillAppear:
If you watch in the debugger, the second call upon app launch is from UITableViewController's viewWillAppear: implementation - specifically the part referred to above, where tableView is sent the reloadData message.
Now, the first call to numberOfSectionsInTableView: on launch is also from UITableViewController's implementation of viewWillAppear: but not directly from that implementation's call to -[UITableView reloadData]. I'm not sure what the first call is all about.
But, to your question, the call to numberOfSectionsInTableView: that happens when dismissing the modal has exactly the same call stack as the second call from applicationDidFinishLaunching:withOptions:. My hypothesis then is that UITableView interprets having zero sections as being in a state where it has not loaded at all. That does make some sense actually. I'd consider an "empty" table view to be one without any rows, but one without any sections seems almost "uninitialized" to me. Furthermore the UITableViewDataSource documentation implies UITableView has by default one section. Returning zero from this method would be inconsistent with that assumption of the docs as well.
Now, to your concern about animation - if you give the table an empty section to work with, you will be able to have full control over inserting the first row with whatever animation you'd like, and not be locked in to when you need to reload.
I think the moral of the story is, don't return zero sections unless you really, really need to for some reason. The title of your post refers to this table view being "empty" as well but I think it's clear the framework finds zero sections to not be empty but unloaded.
Hope this helps! And thanks for posting the sample project for me to play around with.
Perhaps the delegate just couldn't believe its eyes. But seriously, since a table view has to have at least one section, passing 0 doesn't make any sense. Why do it? You pass it an invalid argument and it gives you back a weird response. As to why it doesn't ask for number of sections when you pass 1, I think it's because it doesn't need to know at that point (coming back from the modal view controller) -- the table view has already been populated (if there were some data) and you haven't changed anything in the model, so it doesn't need to update.
I added a few lines to your example project to slide in a row each time you return from the modal view controller, which is what I think you're trying to do. I added an int property num for the return value of numberOfRowsInSection, added an array to populate the table, and a call to insertRowsAtIndexPaths from the modal view controller dismissal method.
- (void)viewDidLoad
{
_num = 0;
self.theData = #[#"one",#"two",#"three"];
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(addRecipe)];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"# sections requested");
//when 0, this fires on return from the modal. When 1, it does not.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"in numberOfRows in section");
return _num;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"in cellForRowAtIndexPath");
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
cell.textLabel.text = [self.theData objectAtIndex:indexPath.row];
return cell;
}
- (void)addRecipe
{
//create the modal and suscribe for delegate notifications
AddRecipeViewController *addRecipeController = [[AddRecipeViewController alloc]initWithStyle:UITableViewStyleGrouped];
addRecipeController.delegate = self;
//display the modal in a navigation controller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addRecipeController];
[self.navigationController presentModalViewController:navController animated:YES];
}
- (void)addRecipeVC:(AddRecipeViewController *)addRecipeVC didAddRecipe:(NSString *)recipe
{
[self dismissModalViewControllerAnimated:YES];
_num += 1;
[self performSelector:#selector(addRow) withObject:nil afterDelay:.5];
}
-(void)addRow {
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:_num-1 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
}
The tableview checks number of sections when it's populating the table view with data!
Since the table can be divided into sections, it has to know specifically how many sections to divide it into.
When you reload the data, the number of sections is also checked.
Because every time the table view has to take action in accessing either the data of the table, like what row you tapped, and in what section, or populating the data table, the number of sections has to be known!
Hope this helped!

UITableView reloadData causes UITextField to resignFirstResponder

I have a textField that is set to change the tableView's dataSource with each letter that's entered (and call reloadData).
But for some reason, every time a letter is entered, the keyboard is dismissed.
Anyone know why?
Your text field is resigning because reloaded cells are sent a -resignFirstResponder message due to the fact that their survival is not guaranteed after a reload. See this related question for more.
Use this method textFieldShouldReturn: and add UITextFieldDelegate delegate in yourClass.h file. set delegate to yourTextfield and write following code in viewDidLoad method.
yourTextfield.delegate = self;
and also implement the textFieldShouldReturn: as following as
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[theTextField resignFirstResponder];
return YES;
}
I think it will be helpful to you.