How to have a separate click even for each UITableViewCell - ios

I have a UITableView using the prototype cells that generates a list. They all share the same Prototype cell as the data presented on them is the same, however the function that it should perform is not the same. All of these cells should be under the same section.
Should I use 6 different prototype cells and change which one I'm getting in the cellForRowAtIndexPath function based on the NSINdexPath#row, or is there a simpler way to register custom logic for when a cell becomes selected.
For example, lets say that my table view looks like this:
Show Data - When clicked displays a popup window
Goto Website - When clicked goes to the website
Open application - When clicked opens another application
Open view - When clicked opens another view
How would I handle that logic separately?

You can use didSelectRowAtIndexPath to get a touch event for each cell.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
// Show data
} else if indexPath.row == 1 {
// Go to website
}
/// etc
}
Be sure to have set your tableViews delegate and datasource to your viewController, and have your viewController setup for this like so:
class MyViewController: UITableViewDataSource, UITableViewDelegate {
}

Related

UITableView just for GUI controls, no DataSource

I'm about to write an iOS app in Swift. The main View Controller is a UISplitViewController. The master view of it is a navigation controller whose root view controller is a UITableViewController.
The cells in this TableView should only contain GUI elements (UIButton, UISwitch, UITextField etc.). There are quite a few of them so that I want to make use of the scrolling feature of the TableView and want to design a few custom Prototype Cells.
However, I'm still a learner of Swift, Cocoa Touch and all that. I know that a TableView needs a DataSource (and a Delegate) but because I don't have data to display in my cells ... how would my cellForRowAtIndex function look like? How would I even create a few "constant" cells (of prototype 1, prototype 2, ...) in the TableView? I guess it's not possible at design time in IB but only by code? How so?
Thanks so much in advance!
Setting your tableView delegate in your viewController class is mandatory to override those methods.
You can use numberOfRowsInSection to return a constant value that will be your number of rows.
Inside your cellForRowAt you can verify which row are you in and call appropriated cell.
internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//call cell type 1
}
}
Here you have a reference to create custom cells using xib and call it into your table.
Custom UITableViewCell from nib in Swift

StoryBoard actions cannot be targeted at repeating content [duplicate]

I have just created an app and have started hooking up #IBOutlet's to the storyboard. I am connecting some of them to labels in a UITableViewCell Prototype Cell with a Basic Style. When I connect it though I get this error in the Storyboard:
The detailText Outlet from the TableViewController to the UILabel is invalid. Outlets cannot be connected to repeating content.
Can someone help me out? I have set it up the way I always do successfully but this time it has chucked me this error.
Create a table view cell subclass and set it as the class of the prototype. Add the outlets to that class and connect them. Now when you configure the cell you can access the outlets.
There are two types of table views cells provided to you through the storyboard, they are Dynamic Prototypes and Static Cells
1. Dynamic Prototypes
From the name, this type of cell is generated dynamically. They are controlled through your code, not the storyboard. With help of table view's delegate and data source, you can specify the number of cells, heights of cells, prototype of cells programmatically.
When you drag a cell to your table view, you are declaring a prototype of cells. You can then create any amount of cells base on this prototype and add them to the table view through cellForRow method, programmatically. The advantage of this is that you only need to define 1 prototype instead of creating each and every cell with all views added to them by yourself (See static cell).
So in this case, you cannot connect UI elements on cell prototype to your view controller. You will have only one view controller object initiated, but you may have many cell objects initiated and added to your table view. It doesn't make sense to connect cell prototype to view controller because you cannot control multiple cells with one view controller connection. And you will get an error if you do so.
To fix this problem, you need to connect your prototype label to a UITableViewCell object. A UITableViewCell is also a prototype of cells and you can initiate as many cell objects as you want, each of them is then connected to a view that is generated from your storyboard table cell prototype.
Finally, in your cellForRow method, create the custom cell from the UITableViewCell class, and do fun stuff with the label
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCellIdentifier") as! YourCell
cell.label.text = "it works!"
return cell
}
2. Static Cells
On the other hand, static cells are indeed configured though storyboard. You have to drag UI elements to each and every cell to create them. You will be controlling cell numbers, heights, etc from the storyboard. In this case, you will see a table view that is exactly the same from your phone compared with what you created from the storyboard. Static cells are more often used for setting page, which the cells do not change a lot.
To control UI elements for a static cell, you will indeed need to connect them directly to your view controller, and set them up.
If you're using a table view to display Settings and other options (like the built-in Settings app does), then you can set your Table View Content to Static Cells under the Attributes Inspector. Also, to do this, you must embedded your Table View in a UITableViewController instance.
Or you don't have to use IBOutlet to refer to the object in the view. You can give the Label in the tableViewCell a Tag value, for example set the Tag to 123 (this can be done by the attributes inspector). Then you can access the label by
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "someID", for: indexPath)
let label = cell.viewWithTag(123) as! UILabel //refer the label by Tag
switch indexPath.row {
case 0:
label.text = "Hello World!"
default:
label.text = "Default"
}
return cell
}
With me I have a UIViewcontroller, and into it I have a tableview with a custom cell on it. I map my outlet of UILabel into UItableviewcell to the UIViewController then got the error.
As most people have pointed out that subclassing UITableViewCell solves this issue.
But the reason this not allowed because the prototype cell(UITableViewCell) is defined by Apple and you cannot add any of your own outlets to it.
Sometimes Xcode could not control over correctly cell outlet connection.
Somehow my current cell’s label/button has connected another cell
I just remove those and error goes away.
For collectionView :
solution:
From viewcontroller, kindly remove the IBoutlet of colllectionviewcell
. the issue mentions the invalid of your IBOutlet. so remove all subclass which has multi-outlet(invalids) and reconnect it.
The answer is already mentioned in another question for collectionviewcell
Click on simulator ,
Navigate to Window and enable Device Bezels

Configuring UICollectionView to keep the same cell view

I have a collection view delegate
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)
-> UICollectionViewCell {
}
I wanted the property of the cell to persist between each call to this method.
let cell = levelView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,
forIndexPath: indexPath)
But retrieving cell using dequeueReusableCellWithReuseIdentifier seems to create a new cell view element that is different from the initial one.
cell.accessibilityIncrement()
So the cell accessibility value cannot persist after tapping on the cell.
I need to do this because I wanted to do UI testing by tapping on the cell.
Any help is appreciated!
Reusable cells in iOS are handled with a queue. This helps the tableViews and collectionViews move smoothly and remain efficient with a large amount of data. I don't think you would want to change the way that is designed to work in your application. This way, the device only needs to load as many cells into memory as can be displayed on a single screen. As cells move off the screen, they can be reused as another cell as cellForItemAtIndexPath will be called to load the required data into the reused cell.
If the goal is to have a value persisted between cell reloads, consider using a map or some other similar variable that could be managed by the collectionView's dataSource delegate.
For example, in your viewController that contains your dataSource delegate, you could have a Dictionary defined like so:
let numberOfTapsByIndexPath = [NSIndexPath: Int]()
Then every time a cell is tapped, you would increment the value in the map for the cell tapped. That code might look something like this:
let previousTaps = numberOfTapsByIndexPath[indexPath]
numberOfTapsByIndexPath[indexPath] = previousTaps + 1
I'm not 100% sure that was the goal you explained above, but regardless, you'll want to move any persistent information out of the cell and into a variable that the dataSource delegate or some other singleton can manage.
Hope this helps!

How to properly add UITextField to UITableViewCell

What I'm trying to do should be pretty straight forward from my understanding, yet I seem to be having some trouble with this.
I'm trying to add UITextField to a UITableViewCell in my Storyboard, however it only lets me place the text field as the child of a UIView, with the latter placed in the table view cell.
ie:
UITableViewCell
|__UIView
|__UITextView
I create my IBOutlet in my Swift ViewController and add the following function to have the keyboard appear on touch
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.nameTextField.becomeFirstResponder()
}
When I run this though, the cell responds to touch however it's as if the text view is always hidden and never gets enabled or becomeFirstResponder. I'm presuming it has to do with the UIView in the way, however I've been unsuccessful in placing the text view directly inside the table view cell.
If anyone has an idea on what I'm doing wrong, I'd greatly appreciate the help,
Thank you!
Create a custom UITableView cell as a xib and make a corresponding .swift file for this. Add a textField to the cell and create an IBOutlet for the textField in the custom .swift class. Make sure your constraints are set in this xib.
In your ViewController .swift class, make the func tableView(cellForRowAtIndexPath) return your custom cell.
You do not have to set the firstResponder because the keyboard will come up by default. Unless of your cell is basically just a textField, it doesn't seem wise to have the didSelectRowAtIndexPath to always bring up the keyboard. If, for some reason that the cell always takes the touch action, then use didSelectRowAtIndexPath, but use
tableView.cellForRowAtIndexPath(indexPath).textField.becomeFirstResponder()
Set textField delegate to the custom cell and add this in the CustomTableViewCell.swift to dismiss the keyboard upon press of return key:
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
Side note: The keyboard will not show in the simulator unless you deselected the option to use the hardware keyboard.
Here is a sample project with what I think you are trying to achieve:
https://mega.nz/#!B1ASDIQT!8-diyv_Fd2H66nb08gs3ObzlQqVHKUUIs4U_BbI6s4s

how to implement UITableViewController with multiple prototype cell programmatically in swift

I have just started learning swift and i created a settings page as show in attached image using the StoryBoard. The reference link used is http://shrikar.com/xcode-6-tutorial-grouped-uitableview/
Same thing i want to do it programmatically i.e. i want to implement cellForRowAtIndexPath function which has different prototype cell as shown in below image.
If possible please give example with reference to given example UI.
Thanks
A great start for you would be this project created by Apple. It includes a variety of things and is a demo app by itself. This will give all the general info you need to start working with UITableView and UITableViewCell.
1.Create a view (XIB) files for each of the custom cells you wish to see in your tableView. Although you can layout design in code, I would advise you to start out with visual approach and see how goes, since you must be able operate freely with such things as Auto Layout, Constraints, Size Classes, etc.
2.Create a UIViewController with a single table view in it.
3.Create a Cocoa Touch Class file (.swift) for each of the cells (XIBs) you created in step 1. In these files you should reference the stuff you incluled in the cell (UILabels, UIImageViews, etc.). Don`t forget that the cells should have these same classes (open XIB files, third icon on the right panel)
4.Create a Cocoa Touch Class file (.swift) for the UIViewController you created in the storyboard. Reference (mouse drag) the tableView in this Cocoa Touch Class. Make sure that the UIViewController in the storyboard has this class set (Custom class field, same as for cells in step 3)
5.Refister nib for the cell in your ViewDidLoad method
tableView.registerNib(UINib(nibName: "topCell", bundle: nil), forCellReuseIdentifier: "topCell")
tableView.registerNib(UINib(nibName: "contentCell", bundle: nil), forCellReuseIdentifier: "contentCell")
tableView.rowHeight = UITableViewAutomaticDimension; //<--Calculates rows height
tableView.estimatedRowHeight = 44.0; // automatically (iOS 8+)
6.On your UIViewController with tableView, click the last button on the right panel and drag "data source" along with "data delegate" to the same view controller (yellow circular symbol).
7.Make sure that your Cocoa Touch class (created in step 4) conforms to the protocols UITableViewDataSource, UITableViewDelegate (by implementing the necessary methods)
class FeedVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
} // <-- your class for the UIViewController with tableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
If your are not completly sure how to implement these required methods, you can look them up in the project I referenced in the beginning of my post.
Please look more into dequeuereusablecellwithidentifier. If you are using Storyboard, add UITableViewCells with reusableIdentifier.

Resources