I've just started my first iOS app (having just finished an OSX app). It's currently got 3 tabs where the first contains a UIView that shows a Google map and the other 2 are UITableViewControllers and I'm trying to set them up.
My storyboard looks like this: https://imgur.com/uNMux7h,ivheZFi
and the UITableViewController class like this: https://imgur.com/uNMux7h,ivheZFi#1
I have connected the class to my delegate and data properties of the UIViewController but I can't connect an outlet, am I off to a poor start here? Does anyone have a tutorial for starting out with the UITableViewController class with Swift?
A standard class for UITableViewController looks something like the following code. Just make sure in interface builder you set the class of the table view controller to SecondViewController and make sure your cell identifier in interface builder matches the cell identifier from your class.
import UIKit
import Foundation
class SecondViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellID", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = "some text"
return cell
}
}
Related
I'm trying to create a swift program with a main ViewController, and a secondary VC that controls a pop up that overlays the screen. In this pop up, you can enter in login credentials, which will display in a tableView in the main ViewController.
So far I'm able to save the entered values in the secondary VC to core data, but I'm not able to reloadData() for the tableView in the first VC, because it just cant see the reloadData() function (must not be a public function? Not really sure, as I'm new to swift).
Could someone help me figure out the best way to go about doing this?
Main ViewController code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var account = [Account]()
#IBAction func onAddAccount(_ sender: Any) {
self.tableView.reloadData()
print("RELOADED")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func onBlank() {
self.tableView.reloadData()
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return account.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
cell.textLabel?.text = account[indexPath.row].email
cell.detailTextLabel?.text = account[indexPath.row].password
return cell
}
}
I am relatively new to swift myself. But I think what you are looking for is a Delegate will tell the main controller that the data has been updated and what it's been updated too. It also seems you might need a datasource? So that you can implement model, view, controller architecture.
I'm creating a slide out menu with xib files using the following tutorial:
https://www.raywenderlich.com/78568/create-slide-out-navigation-panel-swift
Now I'm at the point to make the xib tableview view with the custom tableview cell. Reading several questions on stackoverflow I came to the following code
override func viewDidLoad() {
super.viewDidLoad()
var nib = UINib(nibName: "MenuCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "menucell")
tableView.reloadData()
print("count: \(animals.count)")
}
and the actual cell
extension SidePanelViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animals.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:MenuTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("menucell", forIndexPath: indexPath) as! MenuTableViewCell
cell.configureCell(animals[indexPath.row])
return cell
}
But the tableview is not showing the custom tableview cells with the title. Can anyone help me with this problem?
Probably you have forgot to set this parameters:
tableView.delegate = self
tableView.datasource = self
As explained in comments:
Correct your class declaration like this for example:
class myClass: SidePanelViewController , UITableViewDataSource, UITableViewDelegate { .. }
Try to cross check the following because you have added the xib explicitly in your bundle as your class name and xib name differs
Cross check 1
You have mentioned you custom class MenuTableViewCell in Identity Inspector window
Cross check 2
You have mention the cell identifier in the Attributes Inspector window as
I understand that I need to implement required methods in the controller and establish a relationship between view and controller.. but where do the identifier "tableView" in
func tableView(mintabell: UITableView, numberOfRowsInSection section: Int) -> Int
{
return items.count
}
come from and what if I want several tableviews on same view? How to declare them separately?
These are the protocols that you need to declare for a TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return createCellAndReturnItHere
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfCellsInSection
}
In terms of having more than one tableview in one ViewController.. If you have an outlet for each tableview then you can check which one you need inside the protocol functions:
#IBOutlet weak var tableViewOne: UITableView!
#IBOutlet weak var tableViewTwo: UITableView!
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.tableViewOne {
return createCellForTableViewOneAndReturnItHere
} else {
return createCellForTableViewOneAndReturnItHere
}
}
Think of it like a box. Every tableView that is subscribed to the protocol grabs in that box leaves its fingerprint and takes what it gets. So if you have multiple tableViews in one controller you can distinguish them by checking for equality.
Example:
class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let firstTableView = UITableView()
let secondTableView = UITableView()
viewDidLoad() {
firstTableView.delegate = self
secondTableView.delegate = self
firstTableView.dataSource = self
secondTableView.dataSource = self
}
// ... some othe methods...
func tableView(mintabell: UITableView, numberOfRowsInSection section: Int) -> Int
{
if tableView == firstTableView {
return 10
}
if tableView == secondTableView {
return 20
}
return 0
}
}
Delegates are implemented by the developer and called by iOS not the developer. The tableView is passed by iOS and points to the particular tableview.
If you have several tableviews with the same delegate you can compare the passed tableview parameter to the tableviews you have implemented to determine which one.
Alternatively, create a tableView delegate and datasource per tableView. This will eliminate testing which tableView removing a lot of conditional logic from the code.
First of all, you don't necessarily always have to implement a protocol for every view. Only when you have a view which has delegate that needs implementing, you will have to conform that protocol responsible for that delegate implementation.
So for tableView, first you drag a UITableView in your Controller from the Object Library and then a UITableViewCell under the Table View.
Now go to the ViewController.swift file and add
#IBOutlet var myFirstTableView: UITableView!
right after the line.
class ViewController: UIViewController
P.S: If you have more than one table then you could just declare the extra table's here., like-
#IBOutlet var mySecondTableView: UITableView!
Now, let's assume, you have one table. Now, you need to add the list of protocols. So, just add UITableViewDelegate, UITableViewDataSource with
class ViewController: UIViewController
appended by comma.
Adding this should give you an error but that's okay. This is because you have not added the required method listed under that UITableViewDatasource protocol.
So, just add those required methods and implement it accordingly.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! UITableViewCell
cell.textLabel?.text = "test"
return cell
}
Here, I said, I will have 3 cells whose identifier is "myCell" and the cell's textLabel will have a text, "test".
Now, we forgot a very important step and that is to assign the cell identifier to our TableView Cell. So, go to the storyboard and select the TableView Cell and insert "myCell" as an identifier for your cell.
If you had more than one table, then you would check for which TableView, you are loading your data. So, you could assign a unique tag to each table explicitly(you can do that either from storyboard or from code), and based on that tag, you would implement your methods. Let's say you have 3 tables and the assigned tag is 1,2 and 3. So, you could do something like,
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView.tag == 1{
return 3
}
else if tableView.tag == 2{
return 4
}
else{
return 1
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
if tableView.tag == 1{
cell.textLabel?.text = "test1"
}
else if tableView.tag == 2{
cell.textLabel?.text = "test2"
}
else{
cell.textLabel?.text = "test"
}
return cell
}
I'm trying to setup the Parse PFLoginViewController to appear. Here's my class for one of my viewControllers.
import UIKit
import Parse
import ParseUI
class FirstViewController: PFLogInViewController, UITableViewDataSource, UITableViewDelegate, PFLogInViewControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var textArray:NSMutableArray! = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.textArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.textArray.objectAtIndex(indexPath.row) as? String
return cell
}
}
What I don't understand is, why is the PFLoginViewController appearing when I run the app? I'm not doing the setup code to make it appear, so I'm confused why it's appearing.
My guess is that somehow my viewController is being automatically replaced with the PFLogInViewController somehow because I included it in the top?
My project is a Swift app.
Your FirstViewController is PFLogInViewController (a subclass). If FirstViewController is the rootViewController of your app's window, or if it's the first/root view controller of a container view controller that is itself the window's rootViewController, then you will see the PFLogInViewController when you run your app.
When you define a class in Swift, the first type after the colon is superclass of that class (or, if the first type after the colon is a protocol, your class is a root class that does not inherit from a superclass).
I am trying to learn swift which is also my first programming language. I am trying learn by creating an app with table view in it. I have added a table view and table cell(myCell as identifier). Table cell in turn has labels and text field. Also the background color of the table cell is yellow.
The view controller which encapsulates all this is hooked to class showDetailViewController as show below.
class showDetailViewController:UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: TaskCell = tableView.dequeueReusableCellWithIdentifier("myCell") as TaskCell
return cell
}
//UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
When I run my application I expect to see my cell replicated 5 times (as number of cells in section returns 5) in table view but upon debug I realized that the no tableview delegate class get invoked and hence the issue.
Can anyone please help me with this issue?
Thanks,
Dev
Add the tableView as an IBOutlet.Then you should set tableView's datasource to viewController. self.tableView.dataSource = self. You can also set tableView's dataSource in Interface bulider.