Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting data from each UITableView Cells Swift

Tags:

ios

swift

I have searched the internet countless times and have not found a solution to my situation. Things that may be a solution are things I didn't understand and they were in Objective-C. So if this is a duplicate, it isn't. I have failed to get a solution from other posts.

I am making a GPA Calculator specifically for my school where we get different points depending on our subject levels too.

I made a UITableView with a custom cell that will be duplicated specific amount of times each for each subject in the grade.

What I want to know is getting the data from each of these custom cells(the score and the level)

So this is my storyboard:

Storyboard

and this is my app previewed in the simulator:

App Screenshot

I'm going to get the score and the level by getting the text of the labels in each subjects and I have no idea how to get data from specific cells.

Thank you very much.

Here's the code i currently have:

//showStepperValueLabel shows the level and showSliderValueLabel shows the score in the cells.
//customCell is my custom class for my custom cell.
//i have already declared the levels and scores array above in my class

func tableView(tableView: UITableView!, didDeselectRowAtIndexPath indexPath: NSIndexPath!) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as customCell
    var level: String! = cell.showStepperValueLabel.text
    var score: String! = cell.showSliderValueLabel.text
    levels[indexPath.row] = level
    scores[indexPath.row] = score

}


//yadiyadayada 



//and this is the part where the values get received(it's inside the prepareForSegue function)

    var engScore: String = scores[0]
    var engLevel: String = levels[0]
    var mathScore: String = scores[1]
    var mathLevel: String = levels[1]
    var sciScore: String = scores[2]
    var sciLevel: String = levels[2]
    var geoScore: String = scores[3]
    var geoLevel: String = levels[3]
    var hisScore: String = scores[4]
    var hisLevel: String = levels[4]
    var chiScore: String = scores[5]
    var chiLevel: String = levels[5]
    //

But i'm getting an error where the arrays never received the values. can someone help?

EDIT:

i got an error again so i tried giving the strings manually to the arrays while its initialization like

var levels: [String] = ["H", "H", "H", "H", "H", "H"]
var scores: [String] = ["12", "23", "34", "45", "56", "67"]

and the program worked perfectly fine. So that concludes that the problem occurs in the part where the array receives the strings which is

func tableView(tableView: UITableView!, didDeselectRowAtIndexPath indexPath: NSIndexPath!) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as customCell
    var level: String! = cell.showStepperValueLabel.text
    var score: String! = cell.showSliderValueLabel.text
    levels.insert(level, atIndex: indexPath.row)
    scores.insert(level, atIndex: indexPath.row)

}

are you sure the disselect thing is the correct way? everyone else in the internet taught me to use tags however didn't tell me how to use it...

EDIT2:

so i tried using tags. this is what i wrote in the tableView: cellForRowAtIndexPath function

cell.showStepperValueLabel.tag = indexPath.row+10
cell.showSliderValueLabel.tag = indexPath.row

and this is what i wrote in the prepareForSegue

var engScore : UILabel! = self.view.viewWithTag(0) as? UILabel
    var mathScore: UILabel! = self.view.viewWithTag(1) as? UILabel
    var sciScore: UILabel! = self.view.viewWithTag(2) as? UILabel
    var geoScore: UILabel! = self.view.viewWithTag(3) as? UILabel
    var hisScore: UILabel! = self.view.viewWithTag(4) as? UILabel
    var chiScore: UILabel! = self.view.viewWithTag(5) as? UILabel

    var engLevel: UILabel! = self.view.viewWithTag(10) as? UILabel
    var mathLevel: UILabel! = self.view.viewWithTag(11) as? UILabel
    var sciLevel: UILabel! = self.view.viewWithTag(12) as? UILabel
    var geoLevel: UILabel! = self.view.viewWithTag(13) as? UILabel
    var hisLevel: UILabel! = self.view.viewWithTag(14) as? UILabel
    var chiLevel: UILabel! = self.view.viewWithTag(15) as? UILabel

so in the functions of calculating GPA i put

//Get pxcs
    engpxc = engCredits*co.getEnglishPoints(engLevel.text!, engScore: engScore.text!)
    mathpxc = mathCredits*co.getNonLanguagePoints(mathLevel.text!, scoreRecieved: mathScore.text!)
    geopxc = geoCredits*co.getNonLanguagePoints(geoLevel.text!, scoreRecieved: geoScore.text!)
    hispxc = hisCredits*co.getNonLanguagePoints(hisLevel.text!, scoreRecieved: hisScore.text!)
    scipxc = sciCredits*co.getNonLanguagePoints(sciLevel.text!, scoreRecieved: sciScore.text!)
    chipxc = chiCredits*co.getChiPoints(chiLevel.text!, chiScore: chiScore.text!)
    //

and now i'm getting an error that says

fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

can someone help me with this?

EDIT3 - more info:

i added println in the tableView: cellForRowAtIndexPath function in parts where i give the tags and found out that the tags were given successfully and those labels received the tags i assigned in the program however when i checked with println in the prepareForSegue function in where the variables receive their views to see if they received the labels successfully but i got 'nil' there. What in the world is the problem?

like image 718
Chan Woo Avatar asked Feb 10 '15 11:02

Chan Woo


3 Answers

First retrieve your cell where you need it (for instance in didSelectRowAtIndexPath). Cast your UITableViewCell in your custom cell. And then access properties of your cell as you wish.

Since you haven't provided any code, I will provide simply examples of the code:

func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as YourCell
    //cell.value, cell.text, cell.randomValue or whatever you need
}

What about submit button, you want to submit the data right? And you don't have indexPath there...

Well you have several options, one is to go through each cell, check the type and get it. But seems like your each cell is different one. And seems like you have order for these cells. So you know where exactly your result will be. So, in submit you can do the following

@IBAction func submit_pressed(sender: UIButton) {
     var indexs = NSIndexPath.init(index: 10)
     // or which one(s) you need. you extract data from the cell similar to previous function
}

But, why do you have to get entire cell to get one value? How about you create few variables (or even better, array) and extract values there? you can link events to these controls and when they change you get these value and save them. Later on, you can use these values(or array) without accessing cells or retrieving them.

EDIT:

How about tags? I am not sure if you are adding this through code or storyboard, but I will go through both of them.

In cellForRowAtIndexPath, you can simply say cell.tag = indexPath.row, or even better: cell.tag = question.id ( assuming that question is your custom class). That way, you can go through questions and take specific ones.

Here is working code with tags:

    @IBAction func test(sender: AnyObject) {
        var lbl : UILabel = self.tableView.viewWithTag(12) as UILabel!
        var cell : UITableViewCell = self.view.viewWithTag(3) as UITableViewCell!
        return ;
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = indexPath.row == 0 ? tableView.dequeueReusableCellWithIdentifier("firstCell", forIndexPath: indexPath) as UITableViewCell : tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
        if(indexPath.row != 0){
        let item = toDoList[indexPath.row-1]

        cell.textLabel?.text = item.title
        NSLog("%d",indexPath.row)
        var integerncina = (indexPath.row + 10) as NSInteger!
        cell.textLabel?.tag = integerncina
        NSLog("%d", cell.textLabel!.tag)
        cell.tag = indexPath.row
        }
        // Configure the cell...

        return cell
    }
like image 89
Miknash Avatar answered Nov 04 '22 16:11

Miknash


I know this is a very old post but then to if it helps someone I'll be happy so to do this the simple way which I will prefer is made an array of the UI table view cell and called it in the UI View Controller and then this becomes very simple just called the array (Thanks to rohan)

(FOR EXAMPLE)

import UIKit


public class PlanningTableView:UITableViewCell{

    @IBOutlet weak var Sccode: UITextField!
    @IBOutlet weak var NoOfPatients: UITextField!

}

(AND NOW IN VIEW CONTROLLER DO THIS)

import UIKit

class PlanningReport:UIViewController,UITableViewDelegate,UITableViewDataSource{

    var ScCode = [String]()
    var NoOfPatient = [String]()
    var CollectionOfCell = [PlanningTableView]()


 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PlanningTableView
    CollectionOfCell.append(cell)
    return cell
}

//////// Then at sumbmit Button just do this /////////////////

@IBAction func Submit(_ sender: Any) {

     CollectionOfCell.forEach { cell in
           ScCode.append(cell.Sccode.text!)
           NoOfPatient.append(cell.NoOfPatients.text!)
     }
}

For more details I just created a YouTube first ever tutorial - comments good/bad appreciated

like image 4
kunal pal Avatar answered Nov 04 '22 17:11

kunal pal


To collect data from your cells after the user has finished entering the data (score and level), you can use the UITableView delegate method tableView:didDeselectRowAtIndexPath[Deselect]

The code in your instance will go in UITableViewController class and will look something like this.

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as YourCustomCellClass
    var levelArray:[String] = [] //Assuming you want to collect and store your cell data in an Array. You may use a Dictionary as well, whichever is more convenient.
    var scoreArray:[String] = []
    // levelArray.append(cell.levelLabel.text!)
    // scoreArray.append(cell.scoreLabel.text!)
    levelArray.insert(cell.levelLabel.text!, atIndex: indexPath.row)
    scoreArray.insert(cell.scoreLabel.text!, atIndex: indexPath.row)
}

Next, in you submit button's action(Selector) function use the 'levelArray' and 'scoreArray' to pass your collected data. Be sure to declare the array/dictionary variables(ex: levelArray) right under your UITableViewController class declaration, like so

class GpaCalculator: UITableViewController {
    var levelArray:[String] = []
    var scoreArray:[String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    // ...
}

..to be able to use it in other functions like your submit button's action(Selector) function.

like image 3
Lester Avatar answered Nov 04 '22 16:11

Lester