Use UITableViewCell as Button - objective-c

I read some similar questions about this on Stack Overflow, but none of them had a satisfying answer.
What I am trying to achieve is a "Facebook Sign In Button" from the Settings screen.
I want to achieve this using Static Cells.
But I soon discovered that I could not connect a "Action" to the UITableViewCell using Xcode.
I then tried to achieve the same result using a Custom UITableViewCell with a UIButton inside, but it resulted it a lot of extra styling trouble to make it look exactly like a real UITableViewCell.
Now I managed to make the UITableViewCell to behave like a Button using the following solution:
I changed the Identifier of the "Login Button" UITableViewCell to "loginButton". And I added the following code to the Table View Controller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([[selectedCell reuseIdentifier] isEqualToString:#"loginButton"]) {
NSLog(#"Clicked");
// Execute function to run code for Login button
}
}
Instead of executing a IBAction (which would have been the case if I could just link it like a button in Xcode) I am now going to execute a Function.
This is working like expected. But the reason I created this question is: I want to know if this is the right way to go. Is this ok? Is this bad? Why is this ok or bad? Is there a better solution? Thanks!

Thats a reasonable way to go.
A similar solution using indexpaths would be:
Create an outlet for the Table View Cell from IB.
#property (strong, nonatomic) IBOutlet UITableViewCell *loginButtonCell;
Then implement the didSelectRowAtIndexPath: method.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath isEqual:[tableView indexPathForCell:self.loginButtonCell]])
{
// This will get called when you cell button is tapped
}
}
You can then re-order and without having to modify your code

Related

Static table view inside UIViewController [Xcode 5]

I'm aware of the problem that one is not able to have static table view content in a UIViewController in
I don't get a warning/error but he also doesn't compile. Is there a trick to it or do I have to use the old ways around it?
Thanks in advance.
UPDATE: With the latest update (Xcode 5.1) it seems that it's no longer possible to put static cells inside regular UIViewController. My answer still applies for UITableViewController though.
Yes, you can have static table view content in UIViewController.
All you need to do is:
-Create the table's static cells in interface builder and design them the way you like.
-Make the UIViewController implement table view's data source and delegate:
#interface MyViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
-Connect the table view's delegate and dataSource to the view controller in interface builder
-Implement -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section to return the number of your cells. (e.g. return 10, yes simple as that)
-Connect your cells to your code as IBOutlets in Interface Builder. IMPORTANT: Make sure they are strong, weak won't work. e.g. #property (strong, nonatomic) IBOutlet UITableViewCell *myFirstCell;
-Implement -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to return the correct cell at index path. e.g:
int num = indexPath.row;
UITableViewCell *cell;
switch (num) {
case 0:
cell = self.myFirstCell;
break;
case 1:
cell = self.mySecondCell;
break;
}
return cell;
If you apply all these steps, you should have working static cells that works for tables with not many cells. Perfect for tables that you have a few (probably no more than 10-20 would be enough) content. I've ran the same issue a few days ago and I confirm that it works. More info on my answer here: Best approach to add Static-TableView-Cells to a UIViewcontroller?
There's a way to improve Can's answer.
Connect your cells to code not as IBOutlet but as IBOutletCollection. If you name it as e.g. cells your code will look like this, which makes it slightly cleaner:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.cells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return self.cells[indexPath.row];
}
The order in which you connect cells to outlet collection will be the order you see when run the app.
I can think of supporting several sections by linking their cells to several outlet collections.
This is my try:
I have created container view and Table View Controller. Then I opened source code of Storyboard and changed destination identifier of container view to table view container identifier. Now make table view controller static...
UPDATE:
Just Ctrl+Drag from ContainerView to UITableViewController!
UPDATE 2:
Set embedded view controller class to smith like MYStaticTableViewController, witch should only have this method to provide -prepareForSegue calling to parent view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([self.parentViewController respondsToSelector:#selector(prepareForSegue:sender:)])
[self.parentViewController prepareForSegue:segue sender:sender];
}
UPDATE 3:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([self.parentViewController respondsToSelector:#selector(shouldPerformSegueWithIdentifier:sender:)])
return [self.parentViewController shouldPerformSegueWithIdentifier:identifier sender:sender];
return YES;
}
Can's solution does break in XCode 5.1 :(
I found a workaround which builds off the same basic idea, but unfortunately requires a little more involvement: http://www.codebestowed.com/ios-static-tableview-in-uiviewcontroller/
To summarize, you can add TableViewCells directly to views (and create IBOutlets from them, etc), but in order for them to get "moved" to the TableView properly, you need to remove them from the view in code, and you also need to set Auto-Layout constraints in IB.
As Dannie P mentioned above, using an IBOutletConnection is the way to go. To clarify on this a bit further:
Take the first cell from your static table view and ctrl+drag it into your UITableViewController. On the connection property window, select Outlet Collection on the Connection pull down menu.
Your should end up with code similar to this:
#property (strong, nonatomic) IBOutletCollection(UITableViewCell) NSArray *cells;
Next, ctrl+drag over all the rest of your cells (one at a time) onto the property you created above in the order you want them to appear in your static table view.

UITableViewCell as Header or Footer View

I know about UITableView reusable header and footer view
but in my case, i have UITableView Cells, which i need to place also in section headers and also in normal rows
if i use
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
MyCell * cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
// ...
return cell;
}
How does it work out with the reusing? (is the message to be available for reuse even than passed), or does this disable the cell reuse
The cells get dealloc'ed when they go off-screen. So they don't get reused. An easy way to verify this is to subclass UITableViewCell with the following
- (void)dealloc
{
NSLog(#"I got dealloc'ed");
}
and observe the console output as you scroll.
These has always worked fine. You first should create a prototype with that name, or register a custom nib with your custom section identifier. HOWEVER , I noticed this breaks in iOS 7 when you add new sections to the table dynamically. Reverting to a plain non-reusing UIView works. Really a shame!

Buttons on a UICollectionViewCell

One of the new ios6 classes is uicollectionview which allows one to display items in a grid format similar to the Homescreen / iBooks / Pages layout.
Is there was a way to receive a touch event on a button that is on the UICollectionViewCell? Currently, my cell is created through an XIB file and added to the UICollectionView programatically. I'm looking for something similar to the Detail Diclosure Indicator on a UITableView.
After looking through Apple's documentation here, I don't see any methods that allow for something like that, but I am positive there's a way to do it.
How can one add a button to a UICollectionViewCell and get the indexPath of the cell when the button is tapped?
Are there any tutorials or links out there that could be helpful? iOS 6 is fairly new so I haven't found much. Thanks in advance.
One way is to add an NSIndexPath property to your cell and set it when the cell is dequeued. Then, your cell's action handler would have access to the current index.
Snippet for your UICollectionViewCell:
#interface MyCustomCell : UICollectionViewCell
#property (weak, nonatomic) NSIndexPath *indexPath;
- (IBAction)testClicked:(id)sender; // TODO: wire up your button to this handler
#end
Snippet for your view controller implementing UICollectionViewDataSource:
-(UICollectionViewCell*) collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:#"myCustomCell"
forIndexPath:indexPath];
cell.indexPath = indexPath;
// TODO: other initialization for the cell
return cell;
}

Adding Text Field Data to Table Cell

How I can store text field data in a view controller into a tableView cell in a TableViewController With Xcode using data source?
That means when the user taps "+" it will show another view that has the text field. When the user enters the text and presses save, the entered data will be stored as a table cell.
First make sure you understand data sources. Then you have to implement
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.data.count;
}
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSTableCellView * result = [tableView makeViewWithIdentifier:#"identifier" owner:self];
result.textField = #"Your special string";
return result;
}
After having setup it in IB like this and having connected the outlet of the Table View data source to your custom objects class (the class the above code is in) it should look like this
Please notice I used the same identifier as in the code so that I can get the created table cell view back easily.
self.data could be an array for example in which you store all your underlying objects (for the cell creation).
Of course you could also add any kind of UI elements to the cell view as well. In this case I use a custom subclass for the cell view. You would have to do something like this then (and set your class as the class of the cell view within IB of course. This is the part in the screenshot that has an NSTableCellView currently in it. It had to be MyGreatCellView from now on):
#interface MyGreatCellView : NSTableCellView {
IBOutlet NSTextField *files;
}
#property (assign) NSTextField *files;
Then you could also refer to result.files in the tableView:vieForTableColumn:row for example.
If something is unclear, just ask.
Getting the UITextField data onto a TableView Cell.
Here is a query for some one for the same issue.I think it will help you.

Getting name of cell from indexPath / Swip Gesture

The Situation
I'd like to be able to get information about the title of a cell within a UITableView when the user swipes the cell (to display the "delete" button).
The Code
When the user swipes a cell in the UITableView, this method is fired:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath
The Problem
I need to be able to get the name of the cell the user "swiped" so that my iOS (Obj-C) app can do various operations, etc.
Everything Else
I know that the indexPath has something, but I can't get an NSString from it (which is what I need).
I was also thinking that a workaround such as using a gesture recognizer instead of the above method might be able to provide me with more information about the cell.
Any ideas as to how I can get the name of the cell when the user "swipes to edit / delete"?
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *text = cell.textLabel.text;
// do something with text
}
Please, how does your table work in the first place - you don't seem to understand the basic principles of it. You back your table up with a data model. YOU provide and construct the cells for each indexPath, so you should know how to access the data in your model using that swiped indexPath, no?
Of course you could also ask the tableView delegate (yourself) for the swiped cell by calling tableView:cellForRowAtIndexPath: and then check the labels on that cell.
Have a look at the implementation of your tabkeView:cellForRowAtIndexPath: method all your info of how to get the data should be there...
All in all it's pretty easy, if you provide some code you sure will get more hints.