Home > database >  How to get value from the first 3 rows in TableView using swift?
How to get value from the first 3 rows in TableView using swift?

Time:08-30

I retrieve data from MySql via PHP file to get users information and scores to load them in a table. I need to get the value of the first 3 users and put them in a Label outside the Table, it is like game leaders list. I attached an image to explain the idea.

enter image description here

Here is the structure code:

 import Foundation

protocol HomeModelProtocol: AnyObject {
    func itemsDownloaded(items: NSArray)
}


class HomeModel: NSObject, URLSessionDataDelegate {


weak var delegate: HomeModelProtocol!
let urlPath = "https://mywebsite.com/folder/callUserList.php" //this will be changed to the path where service.php lives

func downloadItems() {
    
    let url: URL = URL(string: urlPath)!
    let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
    
    let task = defaultSession.dataTask(with: url) { (data, response, error) in
        
        if error != nil {
            print("Failed to download data")
        }else {
            print("Data downloaded")
            self.parseJSON(data!)
        }
    }
    
    task.resume()
}


func parseJSON(_ data:Data) {
    var jsonResult = NSArray()
    do{
        jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
        
    } catch let error as NSError {
        print(error)
        
    }
    var jsonElement = NSDictionary()
    let users = NSMutableArray()
    
    for i in 0 ..< jsonResult.count
    {
        
        jsonElement = jsonResult[i] as! NSDictionary
        
        let user = UsersModel()
        //the following insures none of the JsonElement values are nil through optional binding
        if let name = jsonElement["name"] as? String,
            let email = jsonElement["email"] as? String,
            let phoneNumber = jsonElement["phone"] as? String,
            let userImage = jsonElement["image"] as? String
        {
            
            user.name = name
            user.email = email
            user.phoneNumber = phoneNumber
            user.userImage = userImage
        }
        
        users.add(user)
    }
    
    DispatchQueue.main.async(execute: { () -> Void in
        
        self.delegate.itemsDownloaded(items: users)
        
    })
}

}

Here is the model:

import Foundation

class UsersModel: NSObject {
    
    //properties

var name: String?
var email: String?
var phoneNumber: String?
var userImage: String?


//empty constructor

override init()
{
    
}

//construct with @name, @address, @latitude, and @longitude parameters

init(name: String, email: String, phoneNumber: String, userImage: String) {
    
    self.name = name
    self.email = email
    self.phoneNumber = phoneNumber
    self.userImage = userImage
    
}


//prints object's current state

override var description: String {
    return "Name: \(String(describing: name)), Email: \(String(describing: email)), Phone Number: \(String(describing: phoneNumber)), User Image: \(String(describing: userImage))"
    
   
    
}

}

Here is the code in the TableView controller:

var feedItems: NSArray = NSArray()

override func viewDidLoad() {
        super.viewDidLoad()

 let homeModel = HomeModel()
        homeModel.delegate = self
        homeModel.downloadItems()

}



func itemsDownloaded(items: NSArray) {
    
    feedItems = items
    self.listTableView.reloadData()
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of feed items
    return feedItems.count
    
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    // Retrieve cell
    let cellIdentifier: String = "BasicCell"
    let myCell: WinnerTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! WinnerTableCell
    // Get the location to be shown
    let item: UsersModel = feedItems[indexPath.row] as! UsersModel
    // Get references to labels of cell
    myCell.lbTextName!.text = item.name
    
   
    
    return myCell
}

The data shows in the Table but I have no idea how to fill the 3 label with the 3 first users from the Table.

How can I get these values from the table and pass it to a label in the same ViewController?

Thanks

When adding this code:

if feedItems.count >= 3 {
        
        lblFirstWinner.text = feedItems[0].name       // 1st winner
        lblSecondWinner.text  = feedItems[1].name     // 2nd winner
        lblThirdWinner.text  = feedItems[2].name      // 3rd winner  
    }

it shows error: Value of type 'Any' has no member 'name'

CodePudding user response:

Change itemsDownloaded method as

   func itemsDownloaded(items: NSArray) {
        feedItems = items
        self.listTableView.reloadData()
        for (index, user) in items.enumerated() {
            let user = user as! UserModel
            switch index {
            case 0: // 1st winner
                lblFirstWinner.text = user.name       
            case 1: // 2nd winner
                lblSecondWinner.text = user.name
            case 2: // 3rd winner
                lblThirdWinner.text = user.name
            }
        }
   }

OR

Change your HomeModelProtocol method and feedItems type to [UsersModel]

protocol HomeModelProtocol: AnyObject {
    func itemsDownloaded(items: [UsersModel]) // Changed
}

var feedItems =[UsersModel]() // Changed

override func viewDidLoad() {
        super.viewDidLoad()

 let homeModel = HomeModel()
        homeModel.delegate = self
        homeModel.downloadItems()

}



func itemsDownloaded(items: [UsersModel]) {
    
    feedItems = items
    self.listTableView.reloadData()

    if feedItems.count >= 3 {

        lblFirstWinner.text = feedItems[0].name       // 1st winner
        lblSecondWinner.text  = feedItems[1].name     // 2nd winner
        lblThirdWinner.text  = feedItems[2].name      // 3rd winner  
    }
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of feed items
    return feedItems.count
    
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    // Retrieve cell
    let cellIdentifier: String = "BasicCell"
    let myCell: WinnerTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! WinnerTableCell
    
    // Get references to labels of cell
    myCell.lbTextName!.text = feedItems[indexPath.row].name // Changed
      
    return myCell
}

CodePudding user response:

Just you need to add a few lines in the below function and your solution will be done.

func itemsDownloaded(items: NSArray) {
    feedItems = items
    self.listTableView.reloadData()
    
    if feedItems.count >= 3 {
        
        lblFirstWinner.text = feedItems[0].name       // 1st winner
        lblSecondWinner.text  = feedItems[1].name     // 2nd winner
        lblThirdWinner.text  = feedItems[2].name      // 3rd winner  
    }
}

Let me know... is it working for you? and please also refer to @vadian comment on your question.

  • Related