I have 5 cells in a tableview that are all custom. Meaning, I've created a xib with a tableviewcell and created a corresponding cellController. The xib has two labels named name and size. The user taps a row, triggering didSelectRowAtIndexPath. From there a timer is started. At some point the timer finishes. Here I need to assign text to the selected cell's name label. How do I get the selected cell reference and keep it for assigning? Or, is there a better way to do it?
The UITableView instance method
-(UITableViewCell*) cellForRowAtIndexPath: (NSIndexPath*)indexPath
will allow you to get a pointer to the cell.
Simply store the row+section info from NSIndexPath argument of the didSelectRowAtIndexPath event. Then, when the timer finishes, build a new NSIndexPath and call cellForRowAtIndexPath. Also be prepared for it to return nil if the cell is no longer in view.
Related
I'm trying to attain a visual interaction between two tables, inside one controller, by dragging and dropping a cell from one table onto another tables cell. When one dragged cell contacts another cell, a segue will be invoked to another controller.
A more detailed description: There are two standard UITableView's inside a UIViewController both that present data in cells utilizing a custom UITableViewCell class (nothing special in terms of what it does) - each cell presents an icon, name & a price. Both tables are placed side-to-side, rather than one on top of the other.
The point of all of this is to have the user tap a cell to create some kind of view object at the tapped location (something that represents the tapped cell) and drag it to the other table view. The dragged object can only be dropped on another cell. This DOESN'T add the dragged object to the other table; the object can only interact with a cell it was dragged & dropped over to invoke a segue to another controller (to do some stuff with the data of the dragged "cell" and the data of the contacted cell).
I've sat on this problem for a while, trying to figure it out. I've tried using touchesBegan & UIGestureRecognizers, but I can't even create some view object upon cell "touchdown" ('didSelectRowAtIndexPath' is useless since it gets called only when the finger is lifted...which null's the ability to drag). Please point me in the right direction or how to solve this problem.
About that touchDouwn event you mentioned, you can achieve that by doing this:
in -(id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
do
//init the cell "foo"
UIButton * bar = [[UIButton alloc] initWithFrame:CGRectMake(0,0,foo.frame.size.width, foo.frame.size.height);
[bar addTarget:self action:#selector(gotATouchDown:) forControlEvents:UIControlEventTouchDown];
bar.tag = indexpath.row; //use this to know where touchDown happend
[foo addSubview:bar];
now the selector function
-(void)gotATouchDown:(UIButton*)sender{
NSLog(#"I just touched row nr %ld ",sender.tag);
}
Not sure what to do next, once I figure it out I'll complete my answer.
I'm working in Objective C. I have a UITableViewController with about 25 cells that push to a UIViewController. When the user hits back, I want to see if the user entered the correct data for the given cell. (I have a working bool , we'll call it isCellComplete for now). If isCellComplete is true, I want to add a checkmark as the accessory to the cell. I've been trying to put the test in cellForRowAtIndexPath but that method does not seem to run and refresh the cells everytime the view appears. Anyone have suggestions?
You should look into the UITableView method reloadRowsAtIndexPaths:withRowAnimation:. This is much more elegant than reloading the whole table view. And if you don't want an animation, you can specify UITableViewRowAnimationNone and it will look just like reloadData but be much more efficient.
You should do the check in tableView:cellForRowAtIndexPath: and if the check passes, set the cell's accessory to UITableViewCellAccessoryCheckmark. Then when you tell the table view to reload the appropriate row(s), it'll automatically call tableView:cellForRowAtIndexPath: on the data source and update that cell.
You could just call
[self.tableView reloadData];
in
-(void) viewWillAppear:(BOOL)animated
And that will make cellForRowAtIndexPath be called again when the view appears
I have dragged an item into my tableview object.
When the dragged item hover over an item in tableview,
the item is redrawn with selection background. The image is as under
The row of the tableview is not selected, when i checked selectedRow method.
My requirement is when an item hover any item i should control its selection
and the background selection thereof.
Thanks,
iSight
To 'control' the selection of a TableViewCell when 'hovering' over such an item you will have to call this method:
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point
It's a method from the UITableView Class and uses the local coordinate system of your tableView. As is mentioned in the Apple Doc: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html
When the method is called you will have a NSIndexPath returned. With it you can select the cell/item at that particular path.
Mind, selecting a path manually doesn't call the didSelectRowAtIndexPath delegate-method so if you want a certain method called from that delegate you will have to do that manually as well!
This method is prolly called from the touchedDidMove method (where you also do the drag&drop) so getting the point needed for the method shouldn't be a problem for you.
You will figure it out :)
Good luck.
I was wondering if it's possible to remove empty cells (empty = cells with no textLabel) after all the cells are created in a UITableView.
Why do you have empty cells? Are you using a consistent technique to control both the number of cells in your table and the content of those cells?
If you're using a UITableViewController, then your controller is automatically declared as the tableview's datasource. If you're using a UIViewController, then you'll declare it as comforming to the UITableViewDataSource protocol (and connect it up in Interface Builder).
Either way, as the tableview's datasource, your controller is required to implement two methods:
– tableView:cellForRowAtIndexPath:
– tableView:numberOfRowsInSection:
Presumably you're providing the data for the tableview with an array or other means inside -tableview:cellForRowAtIndexPath:. Inside this method the cell's label will be set from an entry in your array. And inside tableView:numberOfRowsInSection: you'll be doing something like [myArray count] to return the number of cells. tableview:cellForRowAtIndexPath will be called as many times as you tell it to (dictated by what you provide in tableview:numberOfRowsInSection:). If the datasource array changes, and you'd like to reflect the changes in your tableview, then you can call
[self.tableview reloadData]; //if inside a UITableViewController
[self.myTableViewOutlet reloadData]; //if inside a UIViewController
Note that reloadData reloads the entire tableview, so in some cases this may be computationally expensive. In this case, instead of calling reloadData you can focus on individual rows with the method: deleteRowsAtIndexPaths:withRowAnimation: (see UITableView Class Reference)
As the app delegate, you are responsible for providing cells. It is your responsibility to return every cell, and the number of cells in the table. Therefore as the app delegate you should have a means (be it by NSMutableArray or otherwise) to mutate the data that you return to the table view.
I am wanting to change the text background color on a tableview's cell when it is hovered upon, similar to how AddressBook "highlights" the label of a contact's element when you mouseover the label names. However I cannot figure out how to accomplish...
detecting a mouseover on a particular NSCell and...
After detecting the cell his hovered upon, highlighting the text in that cell (not highlighting the entire row as if the user selected that row)
As NSCell is not a subclass of NSView this seems to be a very difficult task.
Any example of this or explanation on how this might be done would be greatly appreciated.
Thanks!
I actually got it working using another method. I got it from the example posted here... http://www.cocoadev.com/index.pl?NSTableViewRollover
https://web.archive.org/web/20111013060111/http://cocoadev.com/index.pl?NSTableViewRollover
Instead of using NSCell's tracking mechanism, I am tracking mouseEntered/mouseExited and mouseMoved within my subclassed NSTableView.
When the tableview awakeFromNib method is called, I create a trackingRect from the visible portion of the tableview
I have a BOOL ivar that is set to YES when the mouse is within the tracking area(mouseEntered) and NO when it is not (mouseExited)
Within the mouseMoved method, I determine the current row the mouse cursor is on and set it to an NSInteger ivar and then call the tableview's setNeedsDisplayInRect: passing the rect of the row that the mouse is on.
I also override resetCursorRects to remove the old tracking rect and add a new one...this method is called when the tableview is scrolled upon so that it's tracking the latest visible rect.
Finally in my tableview's delegate, I determine the selected row (by retrieving the row index from the NSInteger ivar of the table view and change the cell's text color (or anything you want) if the currently drawn cell matches the row the mouse cursor is on. All this is done in the delegate method: tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
I hope this helps others, as this was a bit tricky. It is also probably important to make sure that tableview is the firstResponder when the view loads, just makes things a bit more streamlined and cleaner.
Btw, is there a way to make a specific control in a view always be the firstResponder with nothing else possible as being the firstResponder? Even a method such as the iPhones... viewWillAppear method will help as I could set the first responder each time the view is visible...but i'm not aware of such a method on the Mac.
Overall, it's not a simple task as you noticed.
To track the mouse in an NSCell, subclass NSCell and override
-[NSCell startTrackingAt:inView:]
and
-[NSCell stopTracking:at:inView:mouseIsUp:]
Once you've detected the mouse is tracking inside a cell, you can find out which cell you are in the table with [tableView rowAtPoint:point] and [tableView columnAtPoint:point], and then find your frame with [tableView frameOfCellAtColumn:column row:row]
Then, you can change the way your cell is drawn by changing some property of the cell or changing the way it's drawn directly by overriding drawInteriorWithFrame:inView:.
Here's documentation on subclassing NSCell:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/ControlCell/Tasks/SubclassingNSCell.html
I achieved something similar by making use of addGlobalMonitorForEventsMatchingMask: handler: of NSEvent within my NSTableView subclass for the NSMouseMovedMask. using this along with columnAtPoint and rowAtPoint of NSTableView I was able to figure out if the position of the mouse was within a given cell.
Using this information I was able to bring up a PopOver when the mouse was over a particular cell.