I have two labels with two seperate tags each one.
I would like to detect which one label was pressed by checking the tag.
Inside the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
i can retrieve one of them by code like this:
cell = [walltable cellForRowAtIndexPath:indexPath];
topLabel= (UILabel *)[cell.contentView.subviews objectAtIndex:0];
but i do not know the one that was pressed.
Is there a way to achieve to find which one label was pressed by the user?
Something important I want to point out: your reference to the label:
topLabel= (UILabel *)[cell.contentView.subviews objectAtIndex:0];
is not the correct, generic way to do this. I would recommend attaching the elements in your cell to an IBOutlet, and get the reference from there.
As for your question about UILabel touch events, I think a good way to achieve this is to add a UITapGestureRecognizer to your label, like so:
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(firstLabelTapped)];
[firstLabel addGestureRecognizer:tgr];
[tgr release];
Do the same with the second label. If you want to pass back information to the TableView's view controller, do this with delegation. Good luck!
You can use touch events and label's tag as suggested in this question and answer.
Handling Touch Event in UILabel and hooking it up to an IBAction
One method, as suggested above, is to assign a tag to each label, then evaluate the tag of the calling UILabel in your callback.
Another approach if you're using a custom cell (i.e., a subclassed UITableViewCell, versus a standard UITableViewCell to which you've added custom content/layout) is to simply define each of the two labels as properties of your subclassed cell. If the labels are assigned as respective properties, you can evaluate those properties against the caller and determine which label was pressed.
Related
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == sessionListTable){
selectedSessionId = [[self.sessionNames objectAtIndex:indexPath.row] objectForKey:#"session_id"];
selectedSessionName = [[self.sessionNames objectAtIndex:indexPath.row] objectForKey:#"session_name"];
NSLog(#"%#",selectedSessionId);
[StudentCommon sharedInstance].mTeacherSessionId = selectedSessionId;
[self remoteSessionButtonClick];
currentIndexPath = indexPath;
previousIndexPath = currentIndexPath;
[sessionListTable reloadData];
[sessionListPopUp removeFromSuperview];
}
TheUILabel` inside table view is not responding to touch, though the touch is working only in Empty space of the cell.
Verified all the connections, constraints and classes.
Check all the properties of inside UI elements in Attribute Inspector,
make sure for all of them are user interaction is “Ticked” ☑️
Check the properties inside User Defined Runtime Attributes and remove which are
not required.
Check the Class name whether it’s the correct “Super Class” / “Relevant Custom
Class” or not.
Check inside Connections Inspector whether the connection is having any warning ⚠️, if warning exists remove connection and connect again.
This is the image showing the User Defined Runtime Attributes, which was causing this error
First you should know that UILabel doesn't respond to TouchUpInside event.
Apart from that, the events those are raised in UITableViewCell, is not catchable in superview (i.e UITableViewController or UIViewController that is hosting respective table).
In order to achieve your goal, you need to change your UILabel to a UIButton. And in order to escalate TouchUpInside event to super view, you have two options:
1- Create a delegate for your cell, and utilise it in your superview.
2- Post a notification from your cell, and observe (catch) it in super view.
Good Luck. :-)
I have UITableView which cells contain one UITextField in it. My UITableViewController is a delegate of all this text fields. Now, when UITableViewController gets deallocated, I want to set delegate of all that text fields to nil. The text field has a tag, so I can get it by it's tag once I have a cell.
The question is how to get all created cells? Asking UITableView for visibleCells returns only visible cells, but it can happen, that there is a row which is not visible, bit it still has my UIViewController as a delegate. So I really need to get all created cells somehow. cellForRowAtIndexPath does the same, so it wouldn't work for me either. The only way I see here is to store all text fields in array, but may be there is a better way?
Here is some code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"reuseId"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"reuseId"];
UITextField *nameTextField = [[UITextField alloc] initWithFrame:nameTextFieldRect];
nameTextField.tag = TEXT_FIELD_TAG;
nameTextField.delegate = self;
[cell.contentView addSubview:nameTextField];
}
return cell;
}
-(void)dealloc
{
// todo: get all text fields and set theirs delegate to nil
}
Well, most answers suggest that I don't need to set delegate to nil, but as I'm paranoid, I suspect that the following scenario is possible:
User taps 'Back' button, so dealloc of my view controller is called. In dealloc my view controller releases it's table view, but the tableView still exists at this point, as well as all the text fields. And if somehow one of text fields would call it's delegate method at this point, the app would crash, because the delegate is not a valid object anymore.
If someone can explain why this scenario is not possible, than it would convince me that I don't need to set delegate to nil.
You do not need to do that. All of the cells will be deallocated as well, so they won't have a reference to the delegate.
By default the delegate is a weak reference, so it will not retain your object.
I am not expecting to have this answer marked as accepted, but this won't fit into a comment window.
So, rather than us trying to convince you, you could start one of the most important tool for an iOS developer, which is the profiler. And see for yourself by playing with the interface that you should get no more than the number of cells necessary to fill the screen are kept allocated, and then when you tap back, all are getting deallocated.
If they are not, they probably have a strong reference to something else, but this can easily detected with the profiler.
I also like to add that when working with cells the act of scrolling UITable, tap back enter again into table, scroll tap back (repeated at least 10 times) it's a mandatory practice to detect memory leak.
Also, I don't know the purpose of assigning a tag to the cell, I maybe wrong but with this:
nameTextField.tag = TEXT_FIELD_TAG;
consider that you have more than one cell with the same tag, therefore you cannot simply recall the desired one. I remember that the rule is the first placed on screen 'win' the TAG (or kind of).
[UPDATE]
Just a guess, I have never proved this, but to stay on the question, if your problem is to have a cell first for having the UITextView, have you tried to loop the main view and just ignore the cell:
UITextView textView = [mainView viewWithTag:TEXT_FIELD_TAG];
while(textView!=nil){ // or whatever loop or criteria you like
// deallo, nil, etc...
textView = [mainView viewWithTag: TEXT_FIELD_TAG];
}
Create a new delegate/protocol for that cell, and implement that delegate in the view controller, like PersonTableViewCellDelegate. Apart from that, your cell implements the UITextField delegate and in that code, call [self.delegate onKeyPressed] or whatever. I recommend you pass also a reference of the cell, so in the view controller you can use indexPathFromCell (or something like that) to know the position of the cell. If you are interested tell me about it and will copy some code.
So far, have read a few posts, such as this and this, but they have not really helped with my situation.
I'm creating a dynamic form for iPad using 'plain' style UITableViews. I have multiple different UITableViews on the page, so I defined a separate object to server as my datasource and delegate. I understand how to change the text of each cell using the datasource; however, I have no clue how to link the UITextFields in my prototype cells to an IBAction. I could figure out how to create a single IBAction for all textfields in my table, such that they all update the same data, but I don't know how to have each UITextField have a one-to-one correspondence with my datasource.
Here is my prototype cell:
and my code thus far:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myPrototypeCell"];
UILabel *buildingNumber = (UILabel *)[cell viewWithTag:100];
buildingNumber.text = [#"Building " stringByAppendingString:self.dataSource[indexPath.row][#"buildingNumber"]];
return cell;
}
self.dataSource is an NSMutableArray of NSMutableDictionaries.
Any help whatsoever is appreciated.
I initially thought you were referring to IBOutlets so my previous answer is somehow wrong but the inherent idea is still the same.
You cannot have IBActions or IBOutlets from a prototype cell unless the cell is subclassed. You can do so if the cells are static though, not that it can help in your case. Subclassing the UITableViewCell is not too hard or too bad, in fact if in the future you want to speed things up on your TableView, that is one of the many ways to start.
This tutorial provides a few different options for dealing with information inside a table view cell:
http://mobile.tutsplus.com/tutorials/iphone/customizing-uitableview-cell/
I almost always use a UITableViewCell subclass to deal with outlets and actions inside the cell. But this should be a decision you make based on your own architecture.
Hope this helps!
you need single for all your textField.So do the following:
Get the text field as your are getting label
UITextField *yourTextField = (UITextField *)[cell viewWithTag:101];
[yourTextField addTarget:self action:#selector(clickTextField:) forControlEvents:UIControlEventEditingChanged];
clickTextField method will get invoke for every Text Field.
Hope this helps.
Edit: Forgot to mention, you can you set delegate of UItextField and get a notification in UITextFieldTextDidChange: delegate method
Is there a way to get or set the textLabel of a standard UITableViewCell inside a custom method? For instance of a pseudo code,
-(void)getTextLabelOfUITableViewCell
{
UILabel *tempLabel = [[UITableViewCell section:0 row:1] textLabel];
}
-(void)setTextLabelOfUITableViewCell:(UILabel *)data
{
[[UITableViewCell section:0 row:1] textLabel] = data;
}
I'm trying to bind this with the PickerView delegate methods so whenever I change values in the datepicker or picker, the selected UITableViewCell will reflect the changes.
Otherwise I'd have to create a custom UITableViewCell. It'd be nice to be able to programmatically use the standard UITableViewCell Styles.
Thanks in advance!
You should keep (or pass) a reference to the "currently selected cell". Then you can easily access its text label by simply writing:
// assuming the selected cell is kept in a property by name selectedTableViewCell
UILabel * tempLabel = self.selectedTableViewCell.textLabel;
In case you're wondering how to keep such a reference, you should implement the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
method, and in it, simply state:
self.selectedTableViewCell = [tableView cellForRowAtIndexPath:indexPath];
This way, when the user taps the cell, it will be set as the "selected cell".
Another way to fly would be by adding the reference to the cell you want to edit the text from in the IBAction as a parameter, like this:
-(IBAction)getTextLabelOfUITableViewCell:(UITableViewCell *)editMe;
And then you could write something like:
UILabel * tempLabel = editMe.textLabel;
You pretty much can do whatever you want with the label from there on.
Hope this helps!
In my app I have a table view with 12 types of custom cells.
I designed each within the storyboard.
In general everything works fine - thanks to your tutorials :)
My problem is, that I have individual styles an additional data in each cell - therefore I don't want them to be reused.
How can I generate a individual custom cell from storyboard to provide it in the -
tableView:cellForRowAtIndexPath:indexPath?
Any suggestions?
Thanks
Dominic
Added:
newCell = [tableView dequeueReusableCellWithIdentifier:cellType];
cell = newCell;
[cell styleWithElement:element andResubItem:resubItem];
my problem is, I need another way to create a custom-styled cell from the storyboard than the quouted above - I have no XIB and the above way is the only way I know to create my cell.
Could it be a solution to create a celltype once the above way and then copy the cell? Is there a way to copy a cell-object?
You can generate a random cell ID each time so it won't be reused.
However, that would not be very good for scroll performance and memory consumption, so consider actually reusing the cells (i.e. come up with a way to replace data in them).
Edit:
you can always just copy the views from one to another, something along these lines:
UITableViewCell* myCell = [UITableViewCell alloc] initWithStyle:YOUR_CELL_STYLE reuseIdentifier:YOUR_RANDOM_ID];
for (UIView *view in newCell.subviews) {
[view removeFromSuperview];
[myCell addSubview: view];
}
You may also need to adjust the frame of myCell to be the same as that of newCell, and if newCell is an action target for any events (e.g. clicking a control element within the cell triggers some action defined in the cell class) you'll need to reassign those to the myCell, too.
Edit2:
To move actions you could do something like this:
NSSet* targets = [control allTargets];
for(id target in targets) {
NSArray* actions = [control actionsForTarget:target forControlEvent:UIControlEventTouchUpInside];
for(NSString* selectorName in actions) {
[newControl addTarget:target action:NSSelectorFromString(selName) forControlEvents:UIControlEventTouchUpInside];
}
}
Substitute your new cell for the target - and make sure it implements all the necessary selectors (or you can put a new selector). The code above will replace targets for UIControlEventTouchUpInside - you can use the ones you need instead (or use allControlEvents to enumerate the ones used by a control).