First of all, I've looked around to find a solution to my problem, here and on other websites. If I've missed something please show me the link, i didn't intend on bugging you with my problem if there is a solution somewhere else.
My idea was to create an app (just for myself as a practise since I'm fairly new to swift) that would get the NBA schedule from a website, extract the games and results and show them in a table. For that I made a textField where the user could enter from which game day he wanted the results. The Integer he enters changes the url and the url is propperly spilt up and the data I want to display is saved in an array as a string.
Thats were my problem occurs. The items are appended to the array and the array.count displays the right number depending on the day the user entered. The only problem is that the data from the array is not display in the table cell. I've rewrote the code and made sure I didn't mess up the table, but as soon as I add the second part of the app (the information that got from the URL) to the app, the cells don't display anything.
It's kind of weird because both parts are working fine on their own, but as soon as I combine them my problem occurs. Do you know where I might have messed up?
Does anyone have an idea what my mistake may be? I'm not looking for code solutions, just for someone who might tell me where the flaw in my logic is. Maybe i missed something, but i don't get why my cells are not displaying the elements of the array, even though the array is set up properly.
Thanks in advance to anyone answering and have a nice day!
Greetings!
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var gamesArray = [String]()
var gameDay:Int = 0
#IBOutlet var textField: UITextField!
#IBOutlet var gamesTable: UITableView!
#IBAction func enterButton(sender: AnyObject) {
gameDay = Int(textField.text!)!
// webCodeArrayForGames is where i temporarily put the strings I want to add
for var counter = 1; counter<webCodeArrayForGames.count; counter++{
self.gamesArray.append(webCodeArrayForGames[counter])
}
override func viewDidLoad()
{
super.viewDidLoad()
gamesTable.delegate = self
gamesTable.dataSource = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return gamesArray.count
}
func TableView(tableView: UITableView, cellforRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = gamesArray[indexPath.row]
return cell
}
override func viewDidAppear(animated: Bool) {
self.gamesTable.reloadData()
}
}
You can check out this one:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/TableViewAPIOverview/TableViewAPIOverview.html
On the short, you have to provide UITableViewDelegate and UITableViewDataSource.
From the code, I suspect that you didn't provide the dataSource for your table:
"The data source adopts the UITableViewDataSource protocol. UITableViewDataSource has two required methods. The tableView:numberOfRowsInSection: method tells the table view how many rows to display in each section, and the tableView:cellForRowAtIndexPath: method provides the cell to display for each row in the table. "
You could do this way:
Subclass your viewController from UITableViewDelegate and UITableViewDataSource
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { ....
in viewDidLoad() assign the tableview's delegate and dataSource:
override func viewDidLoad() {
super.viewDidLoad()
gamesTable.delegate = self
gamesTable.dataSource = self ....
}
Related
again me with a short question since Swift is confusing me ATM - but I hope I will get used to it soon ;)
Ok so what I was wondering is: When I call a TableView and generate different Cells is there a way to Interrupt after a few and wait for User Input and react to it?
For Example: 2nd Cell is something like "Go to North or West" after that I want a User Input - with Buttons - in whatever direction he likes to go and react to it with following Cells (different Story Parts -> out of other Arrays?).
What is confusing me is that I just load the whole Application in viewDidLoad and i don't know how I can control the "Flow" within this.
I would really appreciate if someone could show me how I can achieve this maybe even with a small description about how I can control the Program Flow within the Method. I really think this knowledge and understanding would lift my understanding for Swift a few Levels higher.
Thanks in advance!
Here is my current Code which is not including any functionality for the named Question since I don't know how to manage this :)
import UIKit
class ViewController: UIViewController {
var storyLines = ["Test Cell 1 and so on first cell of many","second cell Go to North or West","third Cell - Buttons?"]
var actualTables = 1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.dataSource = self
}
#IBOutlet weak var tableView: UITableView!
}
extension ViewController : UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return storyLines.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TxtLine", for: indexPath)
cell.textLabel?.text = storyLines[indexPath.row]
cell.textLabel?.numberOfLines = 0;
cell.textLabel?.lineBreakMode = .byWordWrapping
return cell
}
}
Cocoa is event driven. You are always just waiting for user input. It's a matter of implementing the methods that Cocoa has configured to tell you about it.
So here, for example, if you want to hear about when the user presses a button, you configure the button with an action-and-target to call a method in your view controller when the user presses it. That way, your method can see which button the user pressed and remake the table view's data model (your storyLines array) and reload the table with the new data.
I have the following problem:
I am making a Pokédex-like application that displays a list of all 721 Pokémon on the first tab, and another list on the second tab containing My Favorite Pokémon. Essentially, there are two identical ViewControllers connected to my TabBar.
My storyboard is as follows:
So here is the problem:
The TableView on the first (and initial) tab works fine. However, when I load the TableView on the second tab the Pokémon are loaded, but not displayed. I am able to click the TableViewCell and go to the detail page, but the label in the TableViewCell is not showing anything.
This is the code I use for loading Favorites TableView
class FavoritesViewController: BaseViewController,
UITableViewDataSource, UITableViewDelegate {
#IBOutlet var FavoritesListView: UITableView!
var pokemonList: [String] = ["Nothing Here!"]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FavoriteCell", forIndexPath: indexPath) as! FavoriteCell
var name = pokemonList[indexPath.row]
capitalizeFirstLetter(&name)
cell.nameLabel.text = name
return cell;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pokemonList.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(pokemonList[indexPath.row])
self.performSegueWithIdentifier("ToPokemonDetail", sender: pokemonList[indexPath.row])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "ToPokemonDetail"){
let destination = segue.destinationViewController as! PokemonDetailViewController
let thisPokemon = sender as! String
destination.currentPokemon = thisPokemon
}
}
override func viewWillAppear(animated: Bool) {
FavoritesListView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Fetch the cached list, getNames returns an array of strings
let list = utility.getNames("Favorites")
pokemonList = list
}
The delegate and the dataSource are set via the storyboard.
The above code works, and shows the Favorites list just fine. The class for the complete Pokédex has a similar construction.
I have tried switching Favorites and Pokédex around, so that it shows the complete Pokémon list on startup. All 721 Pokémon are shown correctly, but then the Favorites are not visible.
What else I have tried:
Checking the Reuse Identifiers, over and over
Referencing outlets should be bound correctly
Calling TableView.reloadData() in the viewDidAppear method
Switching around the tab items
Does anyone have any clue what on earth is going on here?
Feel free to ask any more questions
Edit: this is what happens when I swap the two TabBar Buttons around, no code changes
Pokédex Screen
Favorites Screen
GitHub Project Here
Problem is in storyboard cell label frame. Set constraints of view controller for (Any,Any) Size Class. I can commit the code on github if you can give me write rights on your git. Thanks
Perhaps your table's delegate and dataSource are not set.
table.delegate = self
table.dataSource = self
Of course this is after you add the properties to your view controller
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
Your number of rows is always 0 for that controller,
I looked into your code pokemonList count is always 0 its not updating data in it
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pokemonList.count
}
The big issue is your PokemonDetailViewController is not a UITableViewController. It needs to inherent from UITableViewDataSource, UITableViewDelegate and then be connected to the storyboard view to provide data and formatting for a table.
I have been learning swift through the last few days and I have come across an error that I have been stuck on for quite a while now.
I am attempting to get the selected indexPath so that I can then push data according to which item he selected. I have searched through and tried many different solutions I have found on stack overflow as well as different websites but I am not able to get this figured out still.
The code is below:
#IBOutlet var selectGroceryTable: UITableView!
/* Get size of table */
func tableView(tableView: UITableView, numberOfRowsInSection: Int) ->Int
{
return grocery.count;
}
/* Fill the rows with data */
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let myCell:UITableViewCell = selectGroceryTable.dequeueReusableCellWithIdentifier("groceryListRow", forIndexPath:indexPath) as! UITableViewCell
myCell.textLabel?.text = grocery[indexPath.row];
myCell.imageView?.image = UIImage(named: groceryImage[indexPath.row]);
return myCell;
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
print("Row Selected");
NSLog("Row Selected");
}
Nothing ever prints acting like the function is not being called. However, I do not understand why this would not be called?
Any help would be greatly appreciated!
UPDATE:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
selectGroceryTable.data = self;
selectGroceryTable.delegate = self; //gives error states you can not do this
}
There are a couple of things to check in cases like this:
First, what kind of method is didSelectRowAtIndexPath?
Answer: It's a UITableViewDelegate method. Did you set your view controller up as the delegate of the table view? If not, this method won't get called.
Second, have you made absolutely certain that the method signature is a perfect match for the method from the protocol? A single letter out of place, the wrong upper/lower case, a wrong parameter, and it is a different method, and won't be called. it pays to copy the method signature right out of the protocol header file and then fill in the body to avoid minor typos with delegate methods.
It looks to me like your method signature is correct, so my money is on forgetting to set your view controller up as the table view's delegate.
I want to implement a simple tableView in my Viewcontroller but the output is not complete. The content is just visible in one sometimes in two rows.
The classic things:
The class use this:
class MealOfWeekView: UIViewController, UITableViewDelegate, UITableViewDataSource {...}
I set the delegates
override func viewDidLoad() {
super.viewDidLoad()
self.tableViewFood.delegate = self
self.tableViewFood.dataSource = self
self.tableViewFood.reloadData()
}
I use the right identifier:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("foodIdent", forIndexPath: indexPath) as! FoodTableViewCell
cell.dayLabel?.text = "\(day[indexPath.row])"
return cell
}
return 1 section and return 7 rows
=> I use the first time the Tab Bar Controller, in my first tab there is already a tableView. This one works perfect.
The tableView shows as far as I know the days tuesday, saturday or sunday... don't know, whether the info is important :)
EDIT
So with your help I figured out, that my daylabel is nil.
My FoodTableViewCell
class FoodTableViewCell: UITableViewCell {
#IBOutlet weak var dayLbl: UILabel!
}
I add to my viewDidLoad this line:
self.tableViewFood.registerClass(FoodTableViewCell.self, forCellReuseIdentifier: "foodIdent")
But it doesn't work.
If you need more code, give a sign.
Thank you!
Looks like this:
Your issue is with your custom class FoodTableViewCell, but I would verify the following first.
Confirm that the label is being set with the day of the week for the row index. You can do this by setting a breakpoint or printing out statements such as where you create your cells.
print("dayLabel: (cell.dayLabel?.text)")
print("day[indexPath.row]: (day[indexPath.row]")
Confirm you are registering the FoodTableViewCell with the table view.
Confirm that your subclass FoodTableViewCell's dayLabel property is setup correctly. Try changing the background color so you know it is least being displayed in the UI.
Check that your subclass of UITableViewCell is overriding and setting up the dayLabel for reuse correctly.prepareForReuse()
Background information for working with table views
SOLUTION
I found my answer here
When you use Tab Bar Controller you have to use viewDidAppear or viewWillAppear
this lines worked for me:
override func viewWillAppear(animated: Bool) {
self.tableViewFood.delegate = self
self.tableViewFood.dataSource = self
dispatch_async(dispatch_get_main_queue(), {
self.tableViewFood.reloadData()
})
}
I've got an issue where my tableView isn't updating based on the datasource correctly. I'm using a tabbed application structure with Storyboards.
My overall goal here is to have a tableView on the second tab display items that are removed from an array stored in a struct. The items are added to the array from the first tab.
There are 2 ViewControllers (1 for the interface for scrolling through items and selecting to remove them, and 1 to handle the tableView) and 2 Views (1 for the interface for scrolling through items and removing them and 1 for the tableView). The first tab is for providing the interface for removing the items and the second tab is for the tableView.
The remove and add to the array functionality works, just not the displaying it in the tableView.
Currently, if I hard code items in my "removed items" array, they are displayed in the tableView. The problem is that as I add items to the array from my removeItem function in the first ViewController, the tableView does not update, only the hard coded items are shown.
This makes me assume that I have my datasource and delegate setup correctly, since the tableView is getting it's data from the intended datasource. The issue is it's not updating as the user updates the array with new items.
I've tried using self.tableView.reloadData() with no success. I might not be calling in the correct location though.
I'm not sure where the disconnect is.
Here is my second view controller that controls the tableView
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let cellIdentifier = "cellIdentifier"
var removedTopicsFromList = containerForRemovedTopics()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView?.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.cellIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// UITableViewDataSource methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return removedTopicsFromList.removedTopics.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier) as UITableViewCell
cell.textLabel!.text = self.removedTopicsFromList.removedTopics[indexPath.row]
return cell
}
Here is the struct where the removed phrases are stored
struct containerForRemovedTopics {
var removedTopics: [String] = []
}
structure instances are always passed by value. So if your code is something like:
var removedTopicsFromList = secondViewController.removedTopicsFromList
removedTopicsFromList.removedTopics.append("SomeTopic")
secondViewController.reloadData()
then you are changing the different structure.
Maybe you got stuck with this problem I guess.