I'm trying to use a plist to fill my tableView. I've currently written this code. I'm not having any errors and I can run the app fine. The problem is the tableview remains empty. My println returns all the value's from my plist tho. If I request them outside my viewDidLoad function nothing comes up tho. Any idea what I'm doing wrong? Sorry for asking an almost similar question as my previous one. It's just that I'm trying to teach myself a new language.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var artists: Array<String> = []
var stages: Array<String> = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let path = NSBundle.mainBundle().pathForResource("TableRowInfo", ofType: "plist")!
let dict = NSDictionary(contentsOfFile:path)!
artists = dict["Artist"] as Array<String>
stages = dict["Stage"] as Array<String>
println(artists)
println(stages)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return artists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("InfoCell", forIndexPath: indexPath) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: .Subtitle, reuseIdentifier: "InfoCell")
cell!.accessoryType = .DisclosureIndicator
}
cell?.textLabel?.text = artists[indexPath.row]
cell?.detailTextLabel?.text = stages[indexPath.row]
return cell!
}
}
Thanks in advance.
Related
I'm implementing a Feed on my App using Parse.com, basically I'm populating a UITableViewController and everything works fine, BUT, I really like the way Instagram does, seems like the Instagram have a UIView inside each cell that works like a header and that view follows the scroll till the end of cell, I tried to search about that and I'm not successful, after some research I've realized that this feature is equally a Section, so I decide to implement Sections in my querys, I've implemented the code below:
import UIKit
class FeedTableViewController: PFQueryTableViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
loadCollectionViewData()
}
func loadCollectionViewData() {
// Build a parse query object
let query = PFQuery(className:"Feed")
// Check to see if there is a search term
// Fetch data from the parse platform
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
// The find succeeded now rocess the found objects into the countries array
if error == nil {
print(objects!.count)
// reload our data into the collection view
} else {
// Log details of the failure
}
}
}
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
// Configure the PFQueryTableView
self.parseClassName = "Feed"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return objects!.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! FeedTableViewCell!
if cell == nil {
cell = FeedTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell.anuncerPhoto.layer.cornerRadius = cell.anuncerPhoto.frame.size.width / 2
cell.anuncerPhoto.clipsToBounds = true
// Extract values from the PFObject to display in the table cell
if let nameEnglish = object?["name"] as? String {
cell?.title?.text = nameEnglish
}
let thumbnail = object?["Photo"] as! PFFile
let initialThumbnail = UIImage(named: "loadingImage")
cell.photoImage.image = initialThumbnail
cell.photoImage.file = thumbnail
cell.photoImage.loadInBackground()
return cell
}
}
Basically I will need to have a section for each cell, Now I'm successfully have sections working for each cell, but the problem is that the querys is repeating on the first post.
In the backend I have 3 different posts, so, in the App the UItableview need to have 3 posts with different content, with the code above I'm successfully counting the number of posts to know how many section I'll need to have and I declare that I want one post per section, but the app shows 3 sections with the same first post.
Any ideas if I'm capture the correct concept of the Instagram feature and why I'm facing this problem in my querys?
Thanks.
Keep the original UITableViewDataSource method and retrieve the current object using the indexPath.section
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! FeedTableViewCell!
if cell == nil {
cell = FeedTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell.anuncerPhoto.layer.cornerRadius = cell.anuncerPhoto.frame.size.width / 2
cell.anuncerPhoto.clipsToBounds = true
let object = objects[indexPath.section]
// Extract values from the PFObject to display in the table cell
if let nameEnglish = object["name"] as? String {
cell?.title?.text = nameEnglish
}
let thumbnail = object["Photo"] as! PFFile
let initialThumbnail = UIImage(named: "loadingImage")
cell.photoImage.image = initialThumbnail
cell.photoImage.file = thumbnail
cell.photoImage.loadInBackground()
return cell
}
i have a UITableView with multiple selection enabled with checkmarks. When i make selection that are all visible in the view, i don't run into any errors. However, if i scroll down further and place a selected item out of view, i get errors and even though the row stays selected, the checkmark goes away.
import Foundation
import Parse
import UIKit
class customerMenuVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var menuTV: UITableView!
var menuItems: [String] = ["Hello"]
var menuPrices: [Double] = [0.0]
var orderSelection: [String] = []
var priceSelection: [Double] = []
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return menuItems.count
}
func tableView(tableView: UITableView, numberOfColumnsInSection section: Int) -> Int
{
return 1;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
cell.textLabel!.text = "\(menuItems[indexPath.row])\t $\(menuPrices[indexPath.row])"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .Checkmark
orderSelection.append(cell!.textLabel!.text!)
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .None
}
override func viewDidLoad() {
super.viewDidLoad()
menuTV.allowsMultipleSelection = true
let resMenu = resUser.sharedInstance
var resName = resMenu.nameStr
var resID = resMenu.idStr
var menuQ = PFQuery(className: "menu")
menuQ.getObjectInBackgroundWithId(resID){
(menus: PFObject?, error: NSError?) -> Void in
if error == nil && menus != nil {
let items: [String] = menus?.objectForKey("menuItems") as! Array
let prices: [Double] = menus?.objectForKey("menuPrices") as! Array
self.menuItems = items
self.menuPrices = prices
self.menuTV.reloadData()
}
}
}
#IBAction func continueButton(sender: AnyObject) {
let selections = menuTV.indexPathsForSelectedRows() as! [NSIndexPath]
var indexCount = selections.count
println(indexCount)
var x = 0
while x < indexCount
{
println(x)
let currentCell = menuTV.cellForRowAtIndexPath(selections[x]) as? UITableViewCell?;
println(x)
println(selections[x].row.description)
orderSelection.append(currentCell!!.textLabel!.text!)
println(orderSelection[x])
x++
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
This is how table views work.
When a cells scrolls off-screen, it gets tossed into the recycle queue and then used again to display data for a different indexPath in your data.
Any time the user makes any changes to the data for a cell you should save it to your data model (usually an array of information, or maybe an array of arrays if you're using a sectioned table view.) Then you should tell the table view to redisplay the changed cell. The cellForRowAtIndexPath method picks up the changed data and shows the changes to the cell. If the cell scrolls off-screen and then scrolls back on-screen, it gets displayed with the correct settings.
This applies to keeping track of which cells are selected as well.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let path = NSBundle.mainBundle().pathForResource("TableRowInfo", ofType: "plist")!
let dict = NSDictionary(contentsOfFile:path)!
var artists: AnyObject = dict.objectForKey("Artist")!
var stages: AnyObject = dict.objectForKey("Stage")!
println(artists)
println(stages)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return artists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("InfoCell", forIndexPath: indexPath) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: .Subtitle, reuseIdentifier: "InfoCell")
cell!.accessoryType = .DisclosureIndicator
}
return cell!
}
}
Hey all,
I'm new to swift so just experimenting with some things. What I'm trying to do is filling my table with content from a plist file. I know this isn't the best way! I already loaded the list successfully. My println(artists) returns what I want as well does the stages. The only problem is if I call artists or stages outside my viewDidLoad function it doesn't work. Why is that and how do I solve it?
Thanks in advance.
Greets,
Wouter
The variables "artists" and "stages" do not exists outside of the viewDidLoad-Function scope. You have to define them as properties to access them outside of the viewDidLoad-function. Like this
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var artists: AnyObject?
var stages: AnyObject?
override func viewDidLoad() {
...
artists: AnyObject = dict.objectForKey("Artist")
...
}
I'm trying to make a view controller that has one text field that populates the tableview below, ideally the user will be able to continue to add to the tableview without jumping between two views.
I previously had it working with the text field on one view that populates a UITableView and used prepareForSegue to push the data to the table, but I haven't been able to get it to work with just one view.
Can anyone please point out where I'm going wrong or push me to a tutorial / documentation to help?
Edit: Clarity
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
#IBOutlet var tableView: UITableView!
#IBOutlet weak var textField: UITextField!
var items: [String] = ["Pls", "work", "pls", "work", "pls"]
var foodGroup: FoodGroup = FoodGroup(itemName:"")
//var foodGroup: [FoodGroup] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel.text = self.items[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("Selected cell #\(indexPath)")
}
func addFood(sender: AnyObject!) {
if (countElements(self.textField.text) > 0) {
self.foodGroup = FoodGroup(itemName: self.textField.text)
}
}
#IBAction func addFoodToList() {
let source = FoodGroup
let foodGroup:FoodGroup = source.foodGroup
if foodGroup.itemName != "" {
self.foodGroup.append(foodGroup)
self.tableView.reloadData()
}
}
}
It seems like your intention here is to have your dataSource be an array of FoodGroup objects. If this is indeed the case you can get rid of your foodGroup instance variable and update your items definition to be like so:
var items = [FoodGroup]()
then in addFoodToList:
if self.textField.text != "" {
let foodGroup = FoodGroup(itemName: self.textField.text)
self.items.append(foodGroup)
self.tableView.reloadData()
}
and finally in cellForRowAtIndexPath:
var cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
let foodGroup = self.items[indexPath.row] as FoodGroup
cell.textLabel.text = foodGroup.itemName
return cell
Also I don't quite see the intention of your the addFood(sender: AnyObject!) function. Looks like cruft. I would get rid of it. Good luck!
I need to load a custom cell in a UITableView. I created a custom subclass of UITableViewCell named "CustomTableViewCell". I have added a UITabelViewCell to the tableview (using drag and drop) as shown in figure. Then in file inspector I set the class of that UITabelViewCell to be "CustomTableViewCell". Here is my code:
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet var tableView : UITableView
var items = String[]()
override func viewDidLoad() {
super.viewDidLoad()
items = ["Hi","Hello","How"]
self.tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "CusTomCell")
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int{
return items.count
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!{
var cell:CustomTableViewCell? = self.tableView.dequeueReusableCellWithIdentifier("CusTomCell") as? CustomTableViewCell
if !cell
{
cell = CustomTableViewCell(style: UITableViewCellStyle.Subtitle,
reuseIdentifier: "CusTomCell")
}
println("cell \(cell)")
// cell.?.labelTitle.text = items[indexPath.row]
cell!.labelTitle.text = "some text"
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
When I run my code, I get the following error: "fatal error: Can't unwrap Optional.None" as seen in the image.
Hi Finally i found solution for my question..please check my code..it works for me..
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet var tableView : UITableView
var items = String[]()
override func viewDidLoad() {
super.viewDidLoad()
items = ["Hi","Hello","How"]
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int{
return items.count
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!{
var cell:CustomTableViewCell? = self.tableView.dequeueReusableCellWithIdentifier("CusTomCell", forIndexPath: indexPath) as? CustomTableViewCell
cell!.labelTitle.text = "some text"
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Step 1 : Register nib in viewDidLoad() like below
var xib : UINib = UINib (nibName: "WeatherTableViewCell", bundle: nil)
self.tableView.registerNib(xib, forCellReuseIdentifier: "Cell")
Step 2 : Add the following in cellForRowIndexPath
var cell:WeatherTableViewCell? = self.tableView.dequeueReusableCellWithIdentifier("Cell") as? WeatherTableViewCell
cell!.weatherName.text = "weather"
return cell
self.tableView.dequeueReusableCellWithIdentifier will only return a cell if there is one created earlier. You have to do a nil check and create a new cell if it's nil. In you case it will go wrong on the cell.labelTitle.text = because cell could be nil there.