How to insert variables into a tableview? - ios

I'm working on a simple multiplication app for coursework. It has a slider to select a number between 1 and 20. The idea is to create a 'times table' that lists the first 50 items from whatever number is selected from the slider. The error message I'm getting is 'ViewController.Type' does not have a member named 'multiplier'.
Thanks for your help.
import UIKit
class ViewController: UIViewController, UITableViewDelegate {
#IBOutlet weak var sliderValue: UISlider!
#IBAction func sliderMoved(sender: AnyObject) {
println(sliderValue)
}
var multiplier = 1
var cellContent = ["\(multiplier) times 1 is 1", "1 times 2 is 2", "1 times 3 is 3"]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellContent.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
}
Thanks for taking time to answer my question. The suggestions didn't help me. Here is my tutor's method:
import UIKit
class ViewController: UIViewController, UITableViewDelegate {
#IBOutlet weak var table: UITableView!
#IBOutlet weak var sliderValue: UISlider!
#IBAction func sliderMoved(sender: AnyObject) {
table.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
let timesTable = Int(sliderValue.value * 20)
cell.textLabel?.text = String(timesTable * (indexPath.row + 1))
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

TODO
you have to fix your array ;) only the first element is dynamic and uses multiplier. the rest are static strings
you have to save the slider value and reload the table on sliderMoved
AND you need to format the string before giving it to the cell
you need to fix your array again so the result of 'X * Y = Z' (you hardcoded Z)
in your case formatting could be a simple replacing the string
...
#IBAction func sliderMoved(sender: AnyObject) {
multiplier = sliderValue.value; //TODO find right property to save
myTable.reloadData() //reload the table
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
//format it before setting it to the table
//TODO find right method to help you here
var str = cellContent[indexPath.row]
str.stringByReplacingOccurancesOf("(multipler)", NSString("%d", multiple))
str.stringByReplacingOccurancesOf("(result)", NSString("%d", multiple*indexPath.row+1))
cell.textLabel?.text = str
return cell
}
let cellContent = ["(multiplier) times 1 is (result)", "(multiplier) times (result) is 2", "(multiplier) times 3 is (result)"]
...

Make cellContent as:
var cellContent: [String]!
Then initialize it on viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
cellContent = ["\(multiplier) times 1 is 1", "1 times 2 is 2", "1 times 3 is 3"]
}

var multiplier = 1
var cellContent = ["\(multiplier) times 1 is 1", "1 times 2 is 2", "1 times 3 is 3"]
class ViewController: UIViewController, UITableViewDelegate {
#IBOutlet weak var sliderValue: UISlider!
#IBAction func sliderMoved(sender: AnyObject) {
println(sliderValue)
}
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellContent.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
}

Related

How to create controls dynamically and aligned dynamically in swift 4?

I am working on the iOS application with Swift 4. In that project I have requirement like, I have to create controls dynamically along with the proper alignment.
For example, I have a button when I click on that button I am hitting the service from that I am getting json data which contains 4 objects. Based on that I have to create controls dynamically and dynamic alignment also should do. I tried lot of examples and tutorials. I didn’t find any solution.
You can use UITableView for that and here is example:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableview: UITableView!
var nameArr :[String] = []
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func four_btn(_ sender: Any) {
nameArr.removeAll()
let nameData = ["First Name","Middle Name","Last Name","DOB"]
nameArr += nameData
tableview.reloadData()
}
#IBAction func eight_btn(_ sender: Any) {
nameArr.removeAll()
let nameData = ["Salutation","First Name","Middle Name","Last Name","DOB","Gender","Mobile","Email"]
nameArr += nameData
tableview.reloadData()
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nameArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! tableviewCells
cell.nameLabel.text = nameArr[indexPath.row]
return cell
}
}
class tableviewCells : UITableViewCell{
#IBOutlet weak var nameLabel: UILabel!
}
You can use UITableView for the same
Your scenario is like, it may possible that one user having 5 records however another may have 10 or 12 records means you've to work dynamically
if there are 2 buttons which calls 2 different APIs then just manage 2 different array like this
var arr1 = NSArray()
var arr2 = NSArray()
var isAPI1Called = Bool()
save response of both apis in different array
then just manage flag on button tap and in suitable view like this
#IBAction func btn1(_ sender: Any) {
isAPI1Called = true
self.API1Called()
}
#IBAction func btn2(_ sender: Any) {
isAPI1Called = false
self.API1Called()
}
Now use flag in UITableview Delegate like this
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isAPI1Called
{
return arr1.count
}
else
{
return arr2.count
}
}
Load UITableviewCell as per your requirement if UI changed
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isAPI1Called
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as! UITableviewCell
//Do your required stuff here
return cell
}
else
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as! UITableviewCell
//Do your required stuff here
return cell
}
}
Hope it will help you
Comment if not get any point

coreData only printing last entity (swift4)

I am trying to call all of my entries of coreData .color. The problem is only 1 entry of coreData is being called to the label. I would like all of the entities of coreData to be printed on the label not just the latest one, which the code is currently doing.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet var label: UILabel!
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
if CDHandler.fetchObject() != nil {
users = CDHandler.fetchObject()!
tableView.reloadData()
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
cell.textLabel?.text = users[indexPath.row].username
for c in users {
label.text = c.color
}
return cell
}
}
Actually your current loop sets the last item of the array to the label text , so Try this to append values together
for c in users {
label.text = "\((label.text)!)+\((c.color)!)"
}

Swift: Customizing TableView to hold multiple columns of data

So I'm customizing a tableview to hold multiple columns. I want 3 columns, and am customizing the TableViewCell, except I'm at a roadblock.
Right now I have a TableView that is in a ViewController, and the TableView accurately holds one column of data. Here I am changing it to three columns and I get an error about unwrapping an optional nil value.
Here's the important parts of viewcontroller with the tableview (FinishTestController.swift):
var bestRank: [String] = ["1", "2", "3", "4", "5"]
var bestScore: [String] = ["-----", "-----", "-----", "-----", "-----"]
var bestTime: [String] = ["-----", "-----", "-----", "-----", "-----"]
override func viewDidLoad() {
super.viewDidLoad()
addhighscore()
loadhighscores()
self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bestRank.count;;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
cell.column1.text = self.bestRank[indexPath.row]//<-- ERROR points here
cell.column2.text = self.bestScore[indexPath.row]
cell.column2.text = self.bestTime[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
func loadhighscores(){
var result = db.query("SELECT * from EASY_MATH5 ORDER BY Score DESC, Time ASC LIMIT 5", parameters: nil)
println("===============================")
for row in result
{
bestScore[i] = row["Score"]!.asString()
print(bestScore[i])
bestTime[i] = row["Time"]!.asString()
println(bestTime[i])
i++
}
}
Here's my cell:
class TableViewCell: UITableViewCell {
#IBOutlet weak var column1: UILabel!
#IBOutlet weak var column2: UILabel!
#IBOutlet weak var column3: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
And here's the error I get:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
and points to the line that says "cell.column1.text = self.bestRank[indexPath.row]" with a line "Thread 1: EXC_BAD_INSTRUCTION".
Any idea on how to resolve?
Remove
self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")
From viewDidLoad(), you don't need to register your UITableViewCell subclass if you're using prototype cells.
Using your code I made minor adjustments which I've noted in the comments with "// nb: " - it works fine now - once those minor points were removed.
Only other change in my code that I did, was the use of "Cell1" instead of "cell" and name of custom cell as "CustomTableViewCell" instead of "TableViewCell", but this is only from personal habit.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var bestRank : [String] = ["1", "2", "3", "4", "5"]
var bestScore: [String] = ["-----", "-----", "-----", "-----", "-----"]
var bestTime: [String] = ["-----", "-----", "-----", "-----", "-----"]
// --------------------------------------
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.bestRank.count // nb: use of "self." and no ";;" at end
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! CustomTableViewCell
cell.column1.text = self.bestRank[indexPath.row]
cell.column2.text = self.bestScore[indexPath.row]
cell.column3.text = self.bestTime[indexPath.row]
return cell
}
// --------------------------------------
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
// --------------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// nb: Not used: "self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")"
// nb: Datasource + delegate already assigned with tableview in storyboard with click-drag-drop into ViewController.
}
CustomCell was done like yours...
class CustomTableViewCell: UITableViewCell {
#IBOutlet var column1: UILabel!
#IBOutlet var column2: UILabel!
#IBOutlet var column3: UILabel!
** Results = No Error **
Simulator showing table as you wanted...
You should most likely be using a UICollectionView for this type of behaviour.
With a collection view you will have more control of the layout of each cell.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/

Cannot show Table View data in a simple Times Table App

I am trying to make a simple Times Table App (for numbers 1-9) in Swift) using a slider and a Table View. I am managing to make the slider work and an array to be created for each number that is selected with the slider and although the array is shown on the console. I cannot get the numbers to appear on the Table View. Can you please help me and tell me what am I missing?
Here is what I have written so far:
class ViewController: UIViewController, UITableViewDelegate {
#IBOutlet var sliderValue: UISlider!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(sliderValue.value)), animated: true)
print(sliderValue)
var cellContent = [String]()
for var i = 1; i <= 10; i += 1 {
cellContent.append(String(i * Int(sliderValue.value)))
}
print(cellContent)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
}
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.
}
}
I'm afraid there's quite a lot in the code you've supplied that doesn't make all that much sense. I've mentioned some of it in my comment above but you've also nested what looks like a tableViewDataSource-function into your sliderMoved function. The whole array thing looks rather flakey as well as the proposed cell-count does not actually consider the size of the array. I think you probably want something like this:
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet var valueSlider: UISlider!
#IBOutlet var tableView: UITableView!
private var cellContent = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(valueSlider.value)), animated: true)
tableView.reloadData()
}
// TableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") // Must exist with the same identifier in your storyboard
cell.textLabel?.text = valueStringForIndex(indexPath.row)
return cell
}
// Private functions
private func valueStringForIndex(index: Int) -> String {
return "\(index * Int(valueSlider.value))"
}
}
Have you tried creating cellContent array as a instance variable and the following code may work. Check it once.
var cellContent = [String]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(sliderValue.value)), animated: true)
print(sliderValue)
for var i = 1; i <= 10; i += 1 {
cellContent.append(String(i * Int(sliderValue.value)))
}
print(cellContent)
self.tableview.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
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.
}
}
Although not directly an answer to your question ->
Depending on how you want the table displayed, a UICollectionView may be a great fit for this application. Very similar to UITableView to implement but with boxes and columns of data, may be simpler to format (and changing the slider could add some fun animation when the collection view updates).
The sample UIViewController below demonstrates using a UICollectionView. In the storyboard, I simply:
Added a UISlider, UICollectionView, and UILabel and created outlets in MultiplicationTableViewController
In the UICollectionView default cell I gave it the reuseIdentifier "numberCell", and added a label (to hold the product)
Made the MultiplicationTableViewController the dataSource and delegate for the UICollectionView
CODE:
import UIKit
class MultiplicationTableViewController: UIViewController {
#IBOutlet var timesTableCollectionView: UICollectionView!
#IBOutlet weak var numberSlider: UISlider!
#IBOutlet weak var label: UILabel!
var products = [Int]() //array to hold the computed value for each cell in the collectionView
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.viewRotated), name: UIDeviceOrientationDidChangeNotification, object: nil) //register for rotation notifications
products = createTableOfValues() //populate products with initial values
label.text = "\(Int(numberSlider.value)) x \(Int(numberSlider.value))"
}
#IBAction func sliderUpdated(sender: UISlider) {
sender.value = Float(Int(sender.value)) //make the slider stop only on whole numbers
label.text = "\(Int(sender.value)) x \(Int(sender.value))"
products = createTableOfValues() //create the new table values
timesTableCollectionView.reloadData() //tell the collectionView to read the new data and refresh itself
}
func createTableOfValues() -> [Int] {
var prod = [Int]() //temp array to hold the generated products
for row in 0...Int(numberSlider.value) { //iterate from row 0 (header) to
var columns = [Int]() //temp array to build column products
for column in 0...Int(numberSlider.value) {//iterate through each column, including column 0 (header)
if column == 0 {
columns.append(row)
} else if row == 0 {
columns.append(column)
} else {
columns.append(column * row)
}
}
prod.appendContentsOf(columns) //add the current row of products to the temp array
}
return prod
}
func viewRotated() {
timesTableCollectionView.reloadData() //called to force collectionView to recalc (basically to get new cell sizes
}
}
extension MultiplicationTableViewController: UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1 //required for UICollectionViewDataSource
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int(numberSlider.value + 1) * Int(numberSlider.value + 1) //tells the UICollectionView how many cells to draw (the number on the slider, plus header rows)
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("numberCell", forIndexPath: indexPath) //get an existing cell if it exists
if cell.frame.origin.y == 0.0 || cell.frame.origin.x == 0.0 { //if the cell is at the top or left of the collectionView
cell.backgroundColor = UIColor.yellowColor()
} else {
cell.backgroundColor = UIColor.clearColor() //If not, reset the color (required because cells are reused
}
cell.layer.borderColor = UIColor.blackColor().CGColor
cell.layer.borderWidth = 1.0
let numberItem = cell.viewWithTag(101) as? UILabel //get a reference to the label in the current cell
numberItem?.text = String(products[indexPath.row]) //get the value generated earlier for this particular cell
return cell
}
}
extension MultiplicationTableViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let columns = CGFloat(numberSlider.value + 1) //get the number of columns - slider value + 1 for header
let width = timesTableCollectionView.bounds.width / columns //divide the width of the collectionView by the number of columns
return CGSizeMake(width, width) //use width value to make the cell a square
}
}
Screenshot:

show textfields text in a UITableView using swift

I'm very new in swift programming .
I'm just trying some features of textfield .
just want to show textfields value in a UItableView.
stuck in this code
please check this out ....
and give solution
import UIKit
class langViewController: UIViewController {
var txt = ""
let simpleTableIdentifier = "TableViewCell";
#IBOutlet weak var txtlang: UITextField!
#IBOutlet weak var langTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addButtonTapped(sender: AnyObject)
{
txt = txtlang.text
self.langTableView.reloadData()
langData.append(txt)
print(langData)
txtlang.resignFirstResponder()
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier(simpleTableIdentifier) as UITableViewCell
cell.textLabel?.text = txt
return cell;
}
To update your table view cells you have to call reloadData(). So you have to do something like this:
1. Declare the txt variable right where your class definition starts:
var txt = ""
2. In your button handler call reloadData() to update your cells.
#IBAction func addButtonTapped(sender: AnyObject) {
txt = txtlang.text
self.tableView.reloadData()
}
3. Set the text to your cell's label:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier(simpleTableIdentifier) as! UITableViewCell
cell.textLabel?.text = txt
return cell;
}
thanks #flashadvanced
i was using a textfield and a tableview
i trying to get text in tableView from textfield. after suggestion of #flashadvanced i did it.
my code is :
class langViewController: UIViewController,UITableViewDelegate, UITableViewDataSource{
var txt = ""
let simpleTableIdentifier = "TableViewCell";
#IBOutlet weak var txtlang: UITextField!
#IBOutlet weak var langTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.langTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.langTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return langData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.langTableView
.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = langData[indexPath.row]
return cell
}
#IBAction func addButtonTapped(sender: AnyObject)
{
txt = txtlang.text
langData.append(txt)
print(langData)
txtlang.resignFirstResponder()
self.langTableView.reloadData()
}

Resources