Home > Blockchain >  Anyone know how to make username appear on shop?
Anyone know how to make username appear on shop?

Time:11-30

Making a shopping cart app and come to a problem. I have a login page where if logged in it will store in core data and login but I want to make the username appear on the table view on another view controller LoginVC:

import UIKit
import CoreData
class LoginVC: UIViewController {
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!

var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view
    fetchData()
}

@IBAction func login(_ sender: Any) {
    for acc in userList {
        if username.text == acc.username && password.text == acc.password {
                currentUser = username.text!
            try! context.save()
            performSegue(withIdentifier: "DisplayShop1", sender: nil)
        }
        /*else if username.text == "" || password.text == "" || username.text != acc.username || password.text != acc.username {
        let alert = UIAlertController(title: "Alert", message: "Please enter the right credentials", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
        
        present(alert, animated: true, completion: nil)
        }*/
     }
     }
   func fetchData(){
   userList = try! context.fetch(User.fetchRequest())
     }   
     }

ListingShopVC

import UIKit
import CoreData
class ListingShopVC: UIViewController, UITableViewDelegate,        UITableViewDataSource{   
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var usernameloggedin: UILabel!
@IBOutlet weak var creditsdisplay: UILabel!

var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var myUser:[User] = []
var mySecond:[Product] = []
var mySecondF:[Product] = []

var id:String = ""
var name:String = ""
var price:Double = 0.0
var image:String = ""
var details:String = ""

@IBOutlet weak var searchBar: UISearchBar!


override func viewDidLoad() {
    super.viewDidLoad()
    
    fetch()
    tableView.delegate = self
    tableView.dataSource = self
    extracted()
    usernameloggedin.text = "Welcome \(userList)"
    creditsdisplay.text = "You have \(userList)"
    
}
// MARK: - Table view data source

func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return mySecond.count
    
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "hello", for: indexPath) as! TableCellData

    // Configure the cell...

    cell.shopTitle.text = mySecond[indexPath.row].name
    cell.shopPrice.text = "$"   String(mySecond[indexPath.row].price)   "0"
    cell.shopDesc.text = mySecond[indexPath.row].description
    
    if let imageURL = URL(string: mySecond[indexPath.row].image) {
        DispatchQueue.global().async {
            let data = try? Data(contentsOf: imageURL)
            if let data = data {
                let image = UIImage(data: data)
                DispatchQueue.main.async {
                    cell.shopImageView.image = image
                }
            }
        }
    }
    
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    id = mySecond[indexPath.row].id
    name = mySecond[indexPath.row].name
    price = mySecond[indexPath.row].price
    image = mySecond[indexPath.row].image
    //print("At table \(image)")
    details = mySecond[indexPath.row].description
    performSegue(withIdentifier: "toDetails", sender: self)
}

override func prepare(for segue:  UIStoryboardSegue, sender:Any?){
    if segue.identifier == "toDetails"{
        let vc = segue.destination as! ProductDetail
        
        vc.productID = id
        vc.productName = name
        vc.productPrice = price
        vc.productPicture = image
        vc.productDetails = details
        print(vc.productDetails)
    }
}


func extracted(){
    guard let url = URL(string: "http://rajeshrmohan.com/sport.json")
    else {return}
    
    let task = URLSession.shared.dataTask(with: url){
        (data,response,error) in
        guard let dataResponse = data,
              error == nil else {
            print(error?.localizedDescription ?? "Response Error")
            return
        }
        
        do {
            let decoder = JSONDecoder()
            let model:[Product] = try decoder.decode([Product].self, from: dataResponse)
            //print(model)
            
            for i in 0..<model.count{
                self.mySecond.append(model[i])
            }
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
        catch let parsingError {
            print("Error", parsingError)
        }
    }
    task.resume()
}

@IBAction func logOut(_ sender: Any) {
    }

func fetch(){
    userList = try! context.fetch(User.fetchRequest())
    
    tableView.reloadData()
}
}

The top part https://i.stack.imgur.com/9RahD.jpg

I just want to make it appear on on top also it seems my login page and codes doesn't work well If I put a if empty so if any probable suggestions will be appreciated

CodePudding user response:

As far as I understand you can't pass data between pages. Add this to the page you got the userList from.

@IBAction func okAction(_ sender: Any) {
    let controller = storyboard?.instantiateViewController(withIdentifier: "DisplayShop1") as! ListingShopVC

    controller.userList = userList


    controller.modalPresentationStyle = .fullScreen
    present(controller, animated: true, completion: nil)
    
}

If you add this to the page you want to transfer the userList of later, you can call the userList.

var userList: String = ""

CodePudding user response:

You almost have it. Instead of passing the username into the string, you're passing the entire list of Core Data objects which get formatted as a string, but not in the way you want. You should get the username for the user, then pass that into the string:

let username = userList.first?.username ?? ""
usernameloggedin.text = "Welcome \(username)"
creditsdisplay.text = "You have \(username)"

That said, here's a couple critiques to make this work even more reliably.

  1. I would move this part of the code to your function to load from the database. That way if you ever reload the data from the database, it will get the correct user, and the name will be updated appropriately.
  2. You should pick one user that is doing the shopping, and only one user. Currently you are getting a list of users and keeping the list of users. There's also no sorting to determine which user is used, so it could change mid-shop. To fix that, I suggest you create a new property to store the current user that is of type User, rather than [User], and only load one user from the database. The fetch request will return an array, so you need to get and keep only the first one. Additionally, to make this even more reliable, you might consider having your first view check if there is a user logged in, get that user from the database (which you are already doing), and pass that user into the shop view using dependency injection. There's plenty of tutorials out there for how to handle that, but basically you get a reference to the second view in the prepareForSegue call and set the user property on that second view to the desired user, thereby 'injecting your dependency'.
  • Related