I was learning storyboards tutorial, which is mainly about the use of Tab Bar Controller,Navigation Controller,and Table View Controller. The Table View Controller is embedded in the Navigation Controller.
However, when I ran this app,the Table View Cell can not be seen.I've double checked my code,but still couldn't find the reason.Here are two mages of storyboard.
Document Outline,click here.
View Controller Scene, here.
Code in ViewController.swift is here.
import UIKit
import Foundation
struct Player
{
var name:String?
var game:String?
var rating:Int
init(name:String?, game:String?,rating:Int)
{
self.name = name
self.game = game
self.rating = rating
}
}
let playersData = [
Player(name: "Bill Evans", game: "TTT", rating: 4),
Player(name: "OD", game: "Spin the Bottle", rating: 5),
Player(name: "DB", game: "Texas Holder", rating: 2)]
class PlayersViewController: UITableViewController {
var players:[Player] = playersData
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
//This method will check to see if there is an existing cell that can be recycled.If not, it will automatically allocate a prototype cell and return it to you.
let cell = tableView.dequeueReusableCellWithIdentifier("PlayerCell", forIndexPath: indexPath)
let player = players[indexPath.row]as Player
cell.textLabel?.text = player.name
cell.detailTextLabel?.text = player.game
return cell
}
}
In your screenshot ("Document Outline"), there is PlayersViewController Scene.
But this should be Players View Controller (with spaces).
This means that you set PlayersViewController as title of ViewController.
You should set this as custom class for this scene (ViewController).
So your scene is handled by UITableViewController which has no data to present, at the moment.
To fix this, select your view controller or scene, go to Identity Inspector and set PlayersViewController in Class property.
//register your cell(nib) in viewdidload
let customCellNib: UINib = UINib(nibName:#"nibName", bundle: nil)
yourTableView.registerNib(customCellNib, forCellReuseIdentifier:#"PlayerCell")
Related
I have a main menu in my app with 15 item and each item has a sub of 20 items which i also added them as images array (15 image array , some thing like a restaurant menu ) so when ever the user clicks on 1 of the main menu items the app will take him to the sub menu , i have created the main menu table view the issue is with the sub menus do i have to create 15 table view for each sub menu !!??
is there is any way to create 1 table view for the sub menus and change its data according to user click
note : i don't want to use the sections in my table view
any ideas will be much appreciated
Need two viewControllers and a navigationController. One for main menu and other for sub menu. Let them be mainMenuViewController and subMenuViewController. Each controllers contains a tableView.
Create an menuArray containing 15 submenu data.Each submenu is an array.
In didSelectRowAtIndexPath of mainMenuViewController, if user selects a row in the tableView, then pass that data in the menuArray corresponding to the selected row.
For example, if user selects third row,
then pass menuArray[3] to subMenuViewController. Here indexPath.row = 3.
Sample Project Code:
MenuViewController.swift:
import UIKit
class MenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var menuTableView: UITableView!
var imagesArray: NSArray = []
var menuArray: NSArray = []
var subMenuDataArray: NSArray = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
menuTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
imagesArray = ["soups.jpg","salads.jpg","starters.jpg","pizzas.jpg","burgers.jpeg"]
menuArray = ["Soups","Salads","Starters","Pizzas","Burgers"]
subMenuDataArray = [["Cream of broccoli","Cream of celery","Cream of tomato","Etrog","Gazpacho"],
["Tuna salad","Urnebes","Waldorf salad"],
["Kakori Kebabs","Stir Fried Chilli Chicken"," Microwave Paneer Tikkas","Aloo and Dal ki Tikki","Cheese Balls","Bhuna Masala Chicken Wings"],
["Cheese Pizzas","Chicken Pizzas","Masala Pizzas","Double Cheese Pizzas","Herbal Pizzas"],
["Luger Burger","Le Pigeon Burger","The Company Burger","Dyer’s Deep-Fried Burger","The Lola Burger","Cheeseburger","Raw Steak Tartare Burger","Buckhorn Burger"]]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return imagesArray.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
return 70
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let menuTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let cellImageView: UIImageView = UIImageView.init()
cellImageView.frame = CGRectMake(10, 10, 50, 50)
cellImageView.image = UIImage(named: imagesArray.objectAtIndex(indexPath.row) as! String)
menuTableViewCell.contentView.addSubview(cellImageView)
let menuLabel: UILabel = UILabel.init(frame: CGRectMake(70, 10, 200, 25))
menuLabel.text = menuArray.objectAtIndex(indexPath.row) as? String
menuTableViewCell.contentView.addSubview(menuLabel)
return menuTableViewCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let subMenuViewController: SubMenuViewController = storyboard!.instantiateViewControllerWithIdentifier("SubMenuViewControllerID") as! SubMenuViewController
subMenuViewController.currentSubMenuArray = subMenuDataArray.objectAtIndex(indexPath.row) as! NSArray
navigationController?.pushViewController(subMenuViewController, animated: true)
}
}
SubMenuViewController.swift:
import UIKit
class SubMenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var subMenuTableView: UITableView!
var currentSubMenuArray: NSArray = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
subMenuTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "subCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return currentSubMenuArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let subMenuTableViewCell = tableView.dequeueReusableCellWithIdentifier("subCell", forIndexPath: indexPath)
let subMenuLabel: UILabel = UILabel.init(frame: CGRectMake(10, 10, 250, 25))
subMenuLabel.text = currentSubMenuArray.objectAtIndex(indexPath.row) as? String
subMenuTableViewCell.contentView.addSubview(subMenuLabel)
return subMenuTableViewCell
}
}
Storyboard:
Output:
To test the sample project, use the following link of my GitHub account:
https://github.com/k-sathireddy/MenuTableViewSample
Declare one array for displaying and change the content of the array according to the selection and screen state like for menu, submenu etc. and reload the table to display the data in the main array. And if you want to display different kind of cell for different selection you can achieve it by taking an enum for whats the current screen state like i said and return required cell initialized in cellForRowAtIndexPath. Its all about how much you can think and implement the logic. Comment below if you need real technical solution with codes you already have used.
I have a normal view controller with a table view inside, so the class is just a normal UIViewController, therefor I am unable to call self.tableView with this.
I have an asynchronous call to create an array of Aircraft objects that is taken from an online database, but that is only completed after the table cells are initially loaded. I am trying to update the table cells after this asynchronous call is completed, but am unsure how to do so.
I do the async call in viewDidLaod(). Here is my current code that only displays the loading tags since the update has not taken place for the aircraft array.
class AircraftViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let log = Logger( id: String(AircraftViewController.self) )
let dvc = DownloadViewController()
var aircraftArr = [Aircraft]()
override func viewDidLoad() {
super.viewDidLoad()
dvc.getMobileSystemOverviewHTML {
dispatch_async(dispatch_get_main_queue()){
self.aircraftArr = self.dvc.aircraft
self.log.debug("\n\n\n\n\n \(self.aircraftArr) \n\n\n\n\n")
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table View Delegate Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("AircraftCell", forIndexPath: indexPath) as! AircraftCell
if indexPath.row < aircraftArr.count{
let singleAircraft = aircraftArr[indexPath.row] as Aircraft
cell.aircraft = singleAircraft
} else {
cell.aircraft = Aircraft(tailID: "Loading", aircraftSN: "Loading", Box_SN: "Loading")
}
return cell
}
You need to create the outlet of tableview like this
#IBOutlet var tableView: UITableView!
After that reload this tableview in your dispatch_async
dvc.getMobileSystemOverviewHTML {
dispatch_async(dispatch_get_main_queue()){
self.aircraftArr = self.dvc.aircraft
self.tableView.reloadData()
self.log.debug("\n\n\n\n\n \(self.aircraftArr) \n\n\n\n\n")
}
}
Hope this will help.
My goal is to make a grouped tableView, but for somehow the data is not added to the table View
Here's the story board picture
I added a table View on top of view controller which is
and the code that I wrote seems like it don't work
import UIKit
import Alamofire
import SwiftyJSON
import KeychainAccess
class SettingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let keychain = Keychain(server: "https://genietesting.herokuapp.com", protocolType: .HTTPS)
var profile: [String]?
let aboutGenie = [
"How it works",
"About",
"Contact"
]
override func viewDidLoad() {
super.viewDidLoad()
let firstName = keychain[string: "first_name"]
profile = [
firstName!
]
tableView.dataSource = self
tableView.delegate = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return profile!.count
} else {
return aboutGenie.count
}
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Profile"
} else {
return "About Genie"
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let tableCell = tableView.dequeueReusableCellWithIdentifier("myCell")
return tableCell!
}
}
and of course, I want to make it clickable so that it would go to its own viewController
After some suggestion, I changed most of my codes above and the result is still the same but this time it shows the header
The result is
airsoftFreak,
There are multiple mistakes I can figure out
There is no IBOutlet for your tableView which is added on top of your ViewController.
So you must be having something like
#IBOutlet var tableView: UITableView!
Your SettingsViewController only confirms to UITableViewDataSource and not to UITableViewDelegate. If you wamt to get didSelectRowAtIndexPath to be triggerred you have to confirm to UITableViewDelegate
class SettingsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
As many have noticed and mentioned in their answer you will have to set your viewController as delegate for both UITableViewDelegate,UITableViewDataSource so
self.tableView.dataSource = self
self.tableView.delegate = self
The way you are instantiating cell is wrong as well :) Yopu should not create tableViewCell everytime for each cell :) Go to your TableView in storyBoard add a prototype cell, decorate it the way you want and the set the reusableIndentifier for it. Lets say reusableIndentifier you set is 'myCell'
your cellForRowAtIndexPath will change to
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//assuming you have different cells for each section
switch indexPath.section {
case 0: let tableCell = tableView.dequeueReusableCellWithIdentifier("myCell")
tableCell.textLabel.text = profile[indexPath.row]
return tableCell
//in swift switch has to be exhaustive so default
default: let secondSectionCell = tableView.dequeueReusableCellWithIdentifier("second_section_cell_identifier")
secondSectionCell.textLabel.text =aboutGenie[indexPath.row]
return secondSectionCell
}
}
Try to drag (ctrl+drag) the tableview to the yellow button at the top of the viewcontroller. You will now see to options: datasource and delegate. Choose one of these to and perform the action again for the other. Now the tableview should be linked to your code.
If the option to make it clickable was a question as well:
With the function didSelectRowAtIndexpath, you can achieve this. There should be a lot of stacks about this issue available.
You probably have not wired the UITableView delegate and dataSource methods to the viewController. You can do this in two ways.
1. programatically
create a tableViewOutlet
override fun viewDidLoad() {
super.viewDidLoad()
yourTableViewOutlet.delegate = self
yourTableViewOutlet.dataSource = self
}
in interfaceBuilder
a) open the document outline in the storyboard.
b) control drag from your tableView to your ViewController.
c) connect delegate and dataSource one by one.
click on the cell will fire the delegate method didSelectRowAtIndexPath
self.tableView.delegate and self.tableView.datasource
override func viewDidLoad() {
super.viewDidLoad()
let firstName = keychain[string: "first_name"]
profile = [
firstName!
]
self.tableView.delegate = self
self.tableView.datasource = self
}
My UITableView data source and delegate are not connected to any file. If this is the problem, would someone tell me how to connect them. If not, here is my code.
My File containing the struct info:
struct PreviousApps {
var name : String
var description : String
var filename : String
}
And this is my code in my TableViewController:
import UIKit
class PreviousProjectsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
var apps = [PreviousApps]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var PreviousApp = PreviousApps(name: "Gecko Catch", description: "DESCRIPTION", filename: "geckocatch.png")
apps.append(PreviousApp)
PreviousApp = PreviousApps(name: "Flappy Timothy", description: "DESCRIPTION", filename: "flappytimothy.png")
apps.append(PreviousApp)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
var currentApp = apps[indexPath.row]
cell.textLabel!.text = currentApp.name
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return apps.count
}
}
I am new to Swift and any help would be appreciated. If i'm not being specific enough, tell me and I will try to provide you with more info.
Thanks,
Beck
Assuming that you are using storyboard to set up your tableviewcontroller:
Set PreviousProjectsVC as the class for the table view controller using identity inspector (at right panel in Xcode)
Click on the "Show document outline" at the bottom-left corner in storyboard
Select the TableView from the outline and control + drag from there to the yellow icon at the top of the table view controller scene in storyboard
Select delegate and datasource from the menu displayed
To set the delegate and datasource from the code, create an outlet for the TableView and set tableView.delegate = self and tableView.dataSource = self
In other words, I'm looking to figure out how to use a 5 tab tab-based view controller, that, when i touch on one tab, I am brought to a table view- static array- that would then have a detail view controller.
So tab- table view- detail view.
I am new at swift so I'm sure how to phrase this properly, but I'm wondering how to manage/add multiple table views to my project using tabs. I've register for an online iOS swift course, but they only touch upon single-view applications. Any help or references would be greatly appreciated.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var taskArray:[TaskModel] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let task1 = TaskModel(task: "Study French", subTask: "Verbs", date: "04/14/2014")
let task2 = TaskModel(task: "Eat Dinner", subTask: "Burgers", date: "01/14/2014")
taskArray = [task1, task2, TaskModel(task: "Gym", subTask: "Leg Day", date: "01/14/2014")]
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showTaskDetail" {
let detailVC: TaskDetailViewController = segue.destinationViewController as TaskDetailViewController
let indexPath = self.tableView.indexPathForSelectedRow()
let thisTask = taskArray[indexPath!.row]
detailVC.detailTaskModel = thisTask
}
}
//UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return taskArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let task = taskArray [indexPath.row]
var cell: TaskCell = tableView.dequeueReusableCellWithIdentifier("myCell") as TaskCell
cell.taskLabel.text = task.task
cell.descriptionLabel.text = task.subTask
cell.dateLabel.text = task.date
return cell
}
//UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("showTaskDetail", sender: self)
}
I think you need to separate the concerns for a start.
A UITabController has viewControllers. Every UIViewController associated in the UITabController can have it's own implementation file and interface. There you can add UITableView and conform to the UITableViewDelegate.
If you want to have multiple UITableView to one UIViewController then it would be good to create custom controls with their corresponding XIB files and implementation files and load into the UIViewController. This way you can abstract and clear code between them. Also check IBDesignable and IBInspectable.
You will probably want to share data between them, either pass them via the UIViewController that include your table view controls, if you need to take action to the specific references, or create a Repository to provide the data.