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.
- 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.
- 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 theprepareForSegue
call and set the user property on that second view to the desired user, thereby 'injecting your dependency'.