Xcode, Swift 4How do I pass data to another view controller in Swift 4?Below is my code and I am getting an error message.I am getting an error on line 181. It saysCannot assign value of type 'DataToPass' to type 'ViewController'struct DataToPass {
var principal: Double = 0
var balance: Double = 0
var monthlyInterest: Double = 0
var paymentNumber: Int = 0
}
class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
var valueToPass: DataToPass = DataToPass(principal: 0.00, balance: 0.00, monthlyInterest: 0.00, paymentNumber: 0)
// Class-level constant to hold the months per year.
let dblMONTHS_YEAR: Double = 12
// To not allow more than 1 decimal point.
func textField(_ textField: UITextField,shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool
{
let countdots = (textField.text?.components(separatedBy: ".").count)! - 1
if countdots > 0 && string == "."
{
return false
}
return true
}
@IBAction func textFieldCost(_ sender: TextField) {
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
@IBAction func textFieldDownPayment(_ sender: TextField) {
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
@IBAction func textFieldMonths(_ sender: TextField) {
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
@IBAction func textFieldAPR(_ sender: TextField) {
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
@IBOutlet weak var txtViewLabels: UITextView!
@IBOutlet weak var txtViewResults: UITextView!
// Text Field Outlets.
@IBOutlet weak var txtCost: UITextField!
@IBOutlet weak var txtDownPayment: UITextField!
@IBOutlet weak var txtMonths: UITextField!
@IBOutlet weak var txtAPR: UITextField!
// Error Message.
@IBOutlet weak var lblMessage: UILabel!
// Buttons
@IBAction func btnCalculate(_ sender: UIButton) {
var dblAPR: Double = 0 // To hold the Annual Rate.
var dblTotalAmount: Double = 0 // To hold the vehicle total cost.
var dblCost: Double = 0 // To hold vehicle cost.
var dblDownPayment: Double = 0 // To hold down payment.
var intMonths: Int = 0 // To hold number of months for the loan.
var dblLoan: Double = 0 // To hold the amount of the loan.
var dblMonthlyPayment: Double = 0 // To hold the monthly payment.
var dblTotalInterest: Double = 0 // To hold the total interest.
var dblMonthlyRate: Double = 0 // To hold the monthly Rate.
var monthlyInterest: Double = 0
var balance: Double = 0
var principal: Double = 0
var paymentNumber: Int = 0
var data: [String] = []
func passedValue() {
func paymentStructure() {
data = []
balance = dblLoan
for _ in 1...intMonths {
paymentNumber+=1
dblCost = Double(txtCost.text!)!
dblDownPayment = Double(txtDownPayment.text!)!
intMonths = Int(txtMonths.text!)!
dblAPR = Double(txtAPR.text!)!
monthlyInterest = balance * ((dblAPR/100)/12)
principal = dblMonthlyPayment - monthlyInterest
balance = balance - principal
let fPrincipal = NSNumber(value: principal)
let fResultPrincipal = NumberFormatter.localizedString(from: fPrincipal, number: .currency)
let fBalance = NSNumber(value: balance)
let fResultBalance = NumberFormatter.localizedString(from: fBalance, number: .currency)
let fMonthlyInterest = NSNumber(value: monthlyInterest)
let fResultMonthlyInterest = NumberFormatter.localizedString(from: fMonthlyInterest, number: .currency)
data += ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), B: \(fResultBalance)"]
}
valueToPass.paymentNumber = intMonths
valueToPass.monthlyInterest = monthlyInterest
valueToPass.principal = principal
valueToPass.balance = balance
}
}
else if txtCost.text != nil && txtDownPayment.text != nil && txtMonths.text != nil && txtAPR.text != nil {
// Clear the message.
lblMessage.text = ""
dblCost = Double(txtCost.text!)!
dblDownPayment = Double(txtDownPayment.text!)!
intMonths = Int(txtMonths.text!)!
dblAPR = Double(txtAPR.text!)!
// Get the APR rate.
dblAPR = dblAPR / 100
// Get the monthly rate.
dblMonthlyRate = dblAPR / dblMONTHS_YEAR
// Get the monthly payment.
dblMonthlyPayment = (dblCost - dblDownPayment) * (dblMonthlyRate / (1 - pow(1 + dblMonthlyRate, Double(-intMonths))))
// Get the amount of the loan.
dblLoan = dblCost - dblDownPayment
// Get the total interest.
dblTotalInterest = dblMonthlyPayment * Double(intMonths) - dblLoan
// Get the Total Amount.
dblTotalAmount = dblCost + dblTotalInterest
// Get the Vehicle Cost.
dblCost = dblTotalAmount - dblTotalInterest
// Format the results.
let fCost = NSNumber(value: dblCost)
let fResultCost = NumberFormatter.localizedString(from: fCost, number: .currency)
let fDownPayment = NSNumber(value: dblDownPayment)
let fResultDownPayment = NumberFormatter.localizedString(from: fDownPayment, number: .currency)
let fLoan = NSNumber(value: dblLoan)
let fResultLoan = NumberFormatter.localizedString(from: fLoan, number: .currency)
let fMonthlyPayment = NSNumber(value: dblMonthlyPayment)
let fResultMonthkyPayment = NumberFormatter.localizedString(from: fMonthlyPayment, number: .currency)
let fAPR = NSNumber(value: dblAPR)
let fResultAPR = NumberFormatter.localizedString(from: fAPR, number: .percent)
let fTotalInterest = NSNumber(value: dblTotalInterest)
let fResultTotalInterest = NumberFormatter.localizedString(from: fTotalInterest, number: .currency)
let fTotalAmount = NSNumber(value: dblTotalAmount)
let fResultTotalAmount = NumberFormatter.localizedString(from: fTotalAmount, number: .currency)
txtViewLabels.text = " APR:\n Months: \n Cost:\n Down Payment:\n Loan Amount:\n Monthly Payment:\n Total Interest:\n Total Amo
txtViewResults.text = " \(fResultAPR)\n \(intMonths)\n \(fResultCost)\n \(fResultDownPayment)\n \(fResultLoan)\n \(fResultMonthkyPayment)\n \(fResultTotalInterest)\n \(fResultTotalAmount)"
passedValue()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "payout structure" {
if let destVC = segue.destination as? PayoutStructure {
destVC.passedData = valueToPass
}
}
}
}
Post
Replies
Boosts
Views
Activity
I have a function that generates the random color. Every time I call the function, it generates the same color. I put the function in viewDidLoad() but it still generates the same color.
I have a table view and an array of strings. When I swipe a row, I want to add the clicked string to an array of strings. How do I get the value stored in the table view row. I have it set up like this:import UIKit
var myStringArray: [String]?
var someStringArray: [String] = ["Hot Dogs", "Soda", "Chips", "Hamburgers", "Plates", "Dessert", "Napkins", "Fruit",
"Potatoe Salad", "Brats"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return someStringArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
cell.textLabel?.text = someStringArray[indexPath.row]
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
return cell
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let object: String = someStringArray[indexPath.row]
let add = UIContextualAction(style: .normal, title: "Add") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
let alert = UIAlertController(title: "Add ", message: "Are you sure you want to add '\(object)' to your list?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
actionPerformed(false)
}))
alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
self.addObject()
}))
self.present(alert, animated: true)
}
return UISwipeActionsConfiguration(actions: [add, taken])
}
func addObject(index: Int) {
let index = table.indexPathForSelectedRow
let _index = (index?[someStringArray.hashValue])!
if myStringArray!.isEmpty {
myStringArray?.insert(someStringArray[_index], at: 0)
} else {
myStringArray?.append(someStringArray[_index])
}
}
I have two arrays of strings and two table views. In one table view I am using swipe to remove feature. Both arrays hold the same data. When I swipe to remove, I want to remove the same string from the other array also. The strings will have different indexes in the arrays and one array will have a prefix and a suffix. How do I do this?var myArray1: [String] = ["1. Adam, Blazers", "2. Jack, Dare Devils", "3. Steven, Tigers", "4. Donald, Sharks",
"5. Aaron, Cyclones"]
var myArray2: [String] = ["1. Donald, Sharks - QB", "2. Aaron, Cyclones - RB", "3. Adam, Blazers - WR",
"4 Jack, Dare Devils - WR", "5. Steven, Tigers - TE"]I swipe the row in the table that holds "3. Adam, Blazers - WR" from myArray2. I want to remove the string from the myArray1 that holds the string "1. Adam, Blazers". In other words, I swipe the row in myArray2 at index 2 and I want it to remove the string in myArray1 at index 1. How do I do that?
I have an array of strings and I am populating a table view with the array data. I want the table view to display 1 in the first row, 2 in the second row, 3 in the third row. I have done this before but it is not working now. Every time I run the app, it displays the number of elements in the array in every row. What am I doing wrong?func numPick() -> Int {
var num: Int = 0
for _ in myRoster! {
num+=1
}
return num
}
How do I save the view of a table view. I use a strike through text, an accessory type check, and other attributes to the cell at indexPath. How do I save it? I can't even switch to a different view without it not staying.
How do I save the state of a table view after a change to the table view has been made? When I switch to another view and switch back, the table view changes are lost and is back to default. I know there are multiple ways to do this but what is the easiest way? I am thinking core data but how do I do it?
How do I save a global array to a table view so that after I close the app, when I reopen it, the data isn't lost? In my app, I append to an array that is outside of the class. As long as I have the app open, I can switch views and return to the and the table view is still loaded with the array but after I close the app and return to the app the table view is empty.
I used the delegate option using UserDefaults to store and load arrays into a table view and it works good but I am trying to use the singleton database option now.I have everything in my app working right except when I add a player to myRoster or draftOrder it doesn't add the player.My data:import Foundation
import UIKit
class PlayerData: Codable {
var num: Int = 0
var name: String = ""
var team: String = ""
var position: String = ""
var strikeThrough: Bool = false
var color: Bool = false
var accessory: Bool = false
var rosterPosition: Int = -1
var draftPosition: Int = -1
init(num: Int, name: String, team: String, position: String) {
self.num = num
self.name = name
self.team = team
self.position = position
}
}
var objectsArray = [PlayerData]()
var myRoster: [PlayerData] = []
var draftOrder: [PlayerData] = []
class Database {
static let shared = Database()
fileprivate var allPlayers: [PlayerData]
fileprivate func playerDataURL() -> URL {
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
return documentDirectoryURL.appendingPathComponent("playerData.json")
}
fileprivate func playersReadFromDisk() -> [PlayerData]? {
let filePlayerURL = playerDataURL()
guard FileManager.default.fileExists(atPath: filePlayerURL.path) else {
return nil
}
do {
let fileContents = try Data(contentsOf: filePlayerURL)
let list = try JSONDecoder().decode([PlayerData].self, from: fileContents)
return list
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
return nil
}
fileprivate func playersWriteToDisk() {
do {
let data = try JSONEncoder().encode(allPlayers)
try data.write(to: playerDataURL())
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
}
func changeMade() {
playersWriteToDisk()
}
func playerList(position: String) -> [PlayerData] {
return allPlayers.filter({ $0.position == position })
}
func rosterList() -> [PlayerData] {
let rosteredPlayers = allPlayers.filter { ($0.rosterPosition >= 0)}
return rosteredPlayers.sorted(by: { $0.rosterPosition < $1.rosterPosition })
}
func draftList() -> [PlayerData] {
let draftedPlayers = allPlayers.filter({ $0.draftPosition >= 0 })
return draftedPlayers.sorted(by: { $0.draftPosition < $1.draftPosition })
}
func addToRosterList(player: PlayerData) {
let maxRosteredIndex = allPlayers.map({ $0.rosterPosition }).max()!
player.rosterPosition = maxRosteredIndex + 1
}
func addToDraftList(player: PlayerData) {
let maxDraftedIndex = allPlayers.map({ $0.draftPosition }).max()!
player.draftPosition = maxDraftedIndex + 1
}
func removeFromRosterList(player: PlayerData) {
let currentRosterPosition = player.rosterPosition
player.rosterPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
let higherNumberedRosterPlayers = allPlayers.filter({ $0.rosterPosition > currentRosterPosition}) // Their rosterPositions have now gone down by one.
for otherPlayer in higherNumberedRosterPlayers {
otherPlayer.rosterPosition -= 1 // Decrease position by 1.
}
}
init() {
allPlayers = [PlayerData]()
if let playerList = playersReadFromDisk() {
allPlayers = playerList
} else {
allPlayers = [
// Quarterbacks
PlayerData(num: 1, name: "Patrick Mahomes", team: "KC", position: "QB"),
PlayerData(num: 2, name: "Deshaun Watson", team: "HOU", position: "QB"),
PlayerData(num: 3, name: "Aaron Rodgers", team: "GB", position: "QB"),
PlayerData(num: 4, name: "Matt Ryan", team: "ATL", position: "QB"),
PlayerData(num: 5, name: "Baker Mayfield", team: "CLE", position: "QB"),
PlayerData(num: 6, name: "Carson Wentz", team: "PHI", position: "QB"),
PlayerData(num: 7, name: "Jared Goff", team: "LAR", position: "QB"),
PlayerData(num: 8, name: "Cam Newton", team: "CAR", position: "QB"),
PlayerData(num: 9, name: "Andrew Luck", team: "IND", position: "QB"),
PlayerData(num: 10, name: "Drew Brees", team: "NO", position: "QB"),
PlayerData(num: 11, name: "Ben Roethlisberger", team: "PIT", position: "QB"),
PlayerData(num: 12, name: "Dak Prescott", team: "DAL", position: "QB"),
PlayerData(num: 13, name: "Russell Wilson", team: "SEA", position: "QB"),
PlayerData(num: 14, name: "Kyler Murray", team: "ARI", position: "QB"),
PlayerData(num: 15, name: "Tom Brady", team: "NE", position: "QB"),
PlayerData(num: 16, name: "Lamar Jackson", team: "BAL", position: "QB"),
PlayerData(num: 17, name: "Mitchell Trubisky", team: "CHI", position: "QB"),
PlayerData(num: 18, name: "Jameis Winston", team: "TB", position: "QB"),
PlayerData(num: 19, name: "Philip Rivers", team: "LAC", position: "QB"),
PlayerData(num: 20, name: "Kirk Cousins", team: "MIN", position: "QB")
]
}
}
}myRoster view controllerimport UIKit
class MyTeam_2019_2020: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
myRoster = Database.shared.rosterList()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myRoster.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let player = myRoster[indexPath.row]
let str = "\(player.name), \(player.team) - \(player.position)"
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(indexPath.row+1). \([str])"
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
return cell
}
func save() {
let defaults = UserDefaults.standard
defaults.set(myRoster, forKey: "saveMyRoster")
defaults.set(draftOrder, forKey: "saveDraftOrder")
}
@IBOutlet weak var myTeam_20192020: UILabel!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}Top_30_Quartebacks view controllerimport UIKit
@available(iOS 11.0, *)
class Top_30_Quarterbacks: UIViewController, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objectsArray.count
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
objectsArray = Database.shared.playerList(position: "QB")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let num = objectsArray[indexPath.row].num
let name = objectsArray[indexPath.row].name
let team = objectsArray[indexPath.row].team
cell.textLabel?.text = "\(num). \(name), \(team)"
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
if objectsArray[indexPath.row].strikeThrough == false && objectsArray[indexPath.row].accessory == false && objectsArray[indexPath.row].color == false {
cell.textLabel?.text = "\(num). \(name), \(team)"
cell.textLabel?.attributedText = noStrikeThroughText("\(num). \(name), \(team)")
cell.accessoryType = UITableViewCell.AccessoryType.none
cell.backgroundColor = .none
}
else if objectsArray[indexPath.row].strikeThrough == true && objectsArray[indexPath.row].accessory == true && objectsArray[indexPath.row].color == true {
cell.textLabel?.text = "\(num). \(name), \(team)"
cell.textLabel?.attributedText = strikeThroughText("\(num). \(name), \(team)")
cell.accessoryType = UITableViewCell.AccessoryType.checkmark
cell.backgroundColor = .systemGray3
} else {
cell.textLabel?.text = "\(num). \(name), \(team)"
cell.textLabel?.attributedText = strikeThroughText("\(num). \(name), \(team)")
cell.accessoryType = UITableViewCell.AccessoryType.none
cell.backgroundColor = .systemGray2
}
return cell
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let cell = self.top30QuarterbacksTable.cellForRow(at: indexPath)
let str: String = (cell?.textLabel!.text)!
let player = objectsArray[indexPath.row].name
if cell?.textLabel?.attributedText == strikeThroughText(str) {
strikeThroughTextBool = true
} else {
strikeThroughTextBool = false
}
if strikeThroughTextBool == false {
let add = UIContextualAction(style: .normal, title: "Add") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
let alert = UIAlertController(title: "Add Player", message: "Are you sure you want to add '\(player)' to your roster?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
actionPerformed(false)
}))
alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
self.addPlayer(index: indexPath)
let okayAlert = UIAlertController(title: "Player Added!", message: "You added '\(player)' to your roster?", preferredStyle: .alert)
okayAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (alertAction) in
actionPerformed(true)
}))
self.present(okayAlert, animated: true)
}))
self.present(alert, animated: true)
}
add.backgroundColor = .systemGreen
let taken = UIContextualAction(style: .normal, title: "Taken") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
let alert = UIAlertController(title: "Player Taken", message: "Are you sure you want to mark '\(player)' as taken and not available?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
actionPerformed(false)
}))
alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
self.markAsTaken(index: indexPath)
let okayAlert = UIAlertController(title: "Taken Player", message: "You marked '\(player)' as taken and not available!", preferredStyle: .alert)
okayAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (alertAction) in
actionPerformed(true)
}))
self.present(okayAlert, animated: true)
}))
self.present(alert, animated: true)
}
taken.backgroundColor = .systemRed
let config = UISwipeActionsConfiguration(actions: [taken, add])
config.performsFirstActionWithFullSwipe = false
return config
} else {
let undo = UIContextualAction(style: .normal, title: "Undo") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
let alert = UIAlertController(title: "Undo", message: "Are you sure you want to undo the action for '\(player)'?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
actionPerformed(false)
}))
alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
self.removePlayer(index: indexPath)
let okayAlert = UIAlertController(title: "Action Undone", message: "The previous action for '\(player)' has been undone!", preferredStyle: .alert)
okayAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (alertAction) in
actionPerformed(true)
}))
self.present(okayAlert, animated: true)
}))
self.present(alert, animated: true)
}
undo.backgroundColor = .systemBlue
let config = UISwipeActionsConfiguration(actions: [undo])
config.performsFirstActionWithFullSwipe = false
return config
}
}
func addPlayer(index: IndexPath) {
let player = objectsArray[index.row]
player.strikeThrough = true
player.accessory = true
player.color = true
Database.shared.addToRosterList(player: player)
Database.shared.addToDraftList(player: player)
top30QuarterbacksTable.reloadData()
Database.shared.changeMade()
}
func markAsTaken(index: IndexPath) {
let player = objectsArray[index.row]
player.strikeThrough = true
player.color = true
player.accessory = false
top30QuarterbacksTable.reloadData()
Database.shared.changeMade()
}
func removePlayer(index: IndexPath) {
let player = objectsArray[index.row]
player.strikeThrough = false
player.color = false
player.accessory = false
top30QuarterbacksTable.reloadData()
Database.shared.changeMade()
}
@IBOutlet weak var top30QuarterbacksTable: UITableView!
@IBOutlet var view1: UIView!
@IBOutlet weak var view2: UIView!
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Hello,I have a topPlayers view controller with a table, a topRookies view controller with a table, and a view controller with a table for topQuarterbacks, topRunningBacks, etc. When I swipe on a row in topQuarterbacks, it performs an action to strike a line through the text, fill the row background with color, and add an accessory. If this action is performed, I want it to search through topRookies view controller and topPlayers view controller and if a match is found, I want it to do the same action in that table. I also want to be able to swipe in topPlayers view controller and topRookies view controller and search through the rest of my tables in the view controllers for a match and if one is found to perform the same action.
I am trying to hide a bar button item. There is no isHidden method for a button. How do I accomplish this?
I want to be able to reset the properties of a class and then reload the table. I make changes in my app and then it saves the changes of the properties and when I return to the view, it loads the saved changes. I have a row in a table view that will reset the properties in the class back to the default properties. How do I implement this?
How do I create an array of a class?I am managing my data in a singleton database.The structure is the following:Main view - Has a table view to select top quarterbacks, top running backs, etc. When the row is clicked, it segues to another view controller displaying the top quarterbacks, running backs, etc.Top quarterbacks view, runningbacks view, etc.: When the row is swiped, two buttons display - Add, taken -- Add will add that player to my team.- Taken will mark the player as taken and add that player to draft order.After the draft is complete, I have a button called 'add to league'.- Add to league button will segue to another view controller.Add league view: This view has a text field to name the league and then a button to add the league.- Add button adds the league name and segues to another view controller to view the added leagues.My leagues view: This is a table view that has the added league names. If there are more than one added league, then there will be more than one row in the table view. What I want is when a row is tapped to segue to another view controller with a table view and display that added leagues players and at the same time to reset the draft.This is how I get the players on my team:class PlayerData: Codable {
var num: Int = 0
var numPosPick: Int = 0
var numRookie: Int = 0
var name: String = ""
var team: String = ""
var position: String = ""
var rosterPosition: Int = -1
var draftPosition: Int = -1
var isTopPlayer: Bool
var isRookie: Bool
var isRostered: Bool { return rosterPosition >= 0 }
var isDrafted: Bool { return draftPosition >= 0 }
init(num: Int, numPosPick: Int, numRookie: Int, name: String, team: String, position: String, isTopPlayer: Bool, isRookie: Bool) {
self.num = num
self.numPosPick = numPosPick
self.numRookie = numRookie
self.name = name
self.team = team
self.position = position
self.isTopPlayer = isTopPlayer
self.isRookie = isRookie
}
}class Database_2019 {
static let shared = Database_2019()
var myLeagues: [String] = []
var myleaguePlayers: [PlayerData]
var myLeaguePlayersData: [[PlayerData]]
func addPlayersToLeague(league: String) {
myleaguePlayers = rosterList()
if myLeagues == [] {
myLeagues.insert(league, at: 0)
myLeaguePlayersData.insert(myleaguePlayers, at: 0)
} else {
myLeagues.append(league)
myLeaguePlayersData.append(myleaguePlayers)
}
resetDraft()
}
// All players and leagues 2019
fileprivate var allPlayers: [PlayerData]
fileprivate var allPlayersReset: [PlayerData] // To hold the reset properties.
fileprivate func playerDataURL() -> URL {
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
return documentDirectoryURL.appendingPathComponent("playerData_2019.json")
}
fileprivate func leaguesDataURL() -> URL {
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
return documentDirectoryURL.appendingPathComponent("leaguesData_2019.json")
}
fileprivate func leaguePlayersDataURL() -> URL {
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).last!
return documentDirectoryURL.appendingPathComponent("leaguePlayersData_2019.json")
}
// Save players and leagues to disk
fileprivate func playersWriteToDisk() {
do {
let data = try JSONEncoder().encode(allPlayers)
try data.write(to: playerDataURL())
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
}
fileprivate func leaguesWriteToDisk() {
do {
let data = try JSONEncoder().encode(myLeagues)
try data.write(to: leaguesDataURL())
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
}
fileprivate func leaguesPlayersWriteToDisk() {
do {
let data = try JSONEncoder().encode(myLeaguePlayersData)
try data.write(to: leaguePlayersDataURL())
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
}
// Load players and leagues from disk
fileprivate func playersReadFromDisk() -> [PlayerData]? {
let filePlayerURL = playerDataURL()
guard FileManager.default.fileExists(atPath: filePlayerURL.path) else {
return nil
}
do {
let fileContents = try Data(contentsOf: filePlayerURL)
let list = try JSONDecoder().decode([PlayerData].self, from: fileContents)
return list
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
return nil
}
fileprivate func leaguesReadFromDisk() -> [String]? {
let fileLeaguesURL = leaguesDataURL()
guard FileManager.default.fileExists(atPath: fileLeaguesURL.path) else {
return nil
}
do {
let fileContents = try Data(contentsOf: fileLeaguesURL)
let list = try JSONDecoder().decode([String].self, from: fileContents)
return list
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
return nil
}
fileprivate func leaguePlayersReadFromDisk() -> [[PlayerData]]? {
let fileLeaguePlayersURL = leaguePlayersDataURL()
guard FileManager.default.fileExists(atPath: fileLeaguePlayersURL.path) else {
return nil
}
do {
let fileContents = try Data(contentsOf: fileLeaguePlayersURL)
let list = try JSONDecoder().decode([[PlayerData]].self, from: fileContents)
return list
} catch let error as NSError {
NSLog("Error reading file: \(error.localizedDescription)")
}
return nil
}
// Player lists
func playerList(position: String) -> [PlayerData] {
return allPlayers.filter({ $0.position == position })
}
func playerList(topPlayer: Bool) -> [PlayerData] {
return allPlayers.filter({ $0.isTopPlayer == topPlayer })
}
func playerList(rookie: Bool) -> [PlayerData] {
return allPlayers.filter({ $0.isRookie == rookie })
}
// Roster lists/My team lists
func rosterList() -> [PlayerData] {
let rosteredPlayers = allPlayers.filter { ($0.rosterPosition >= 0)}
return rosteredPlayers.sorted(by: { $0.rosterPosition < $1.rosterPosition })
}
func rosterArray() -> [PlayerData] {
let roster = rosterList()
return roster
}
func addToRosterList(player: PlayerData) {
let maxRosteredIndex = allPlayers.map({ $0.rosterPosition }).max()!
player.rosterPosition = maxRosteredIndex + 1
}
fileprivate func removeFromRosterList(player: PlayerData) {
let currentRosterPosition = player.rosterPosition
player.rosterPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
let higherNumberedRosterPlayers = allPlayers.filter({ $0.rosterPosition > currentRosterPosition}) // Their rosterPositions have now gone down by one.
for otherPlayer in higherNumberedRosterPlayers {
otherPlayer.rosterPosition -= 1 // Decrease position by 1.
}
}
// draft List
func draftList() -> [PlayerData] {
let draftedPlayers = allPlayers.filter({ $0.draftPosition >= 0 })
return draftedPlayers.sorted(by: { $0.draftPosition < $1.draftPosition })
}
func addToDraftList(player: PlayerData) {
let maxDraftedIndex = allPlayers.map({ $0.draftPosition }).max()!
player.draftPosition = maxDraftedIndex + 1
}
fileprivate func removeFromDraftList(player: PlayerData) {
let currentDraftPosition = player.draftPosition
player.draftPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
let higherNumberedRosterPlayers = allPlayers.filter({ $0.draftPosition > currentDraftPosition}) // Their rosterPositions have now gone down by one.
for otherPlayer in higherNumberedRosterPlayers {
otherPlayer.draftPosition-=1 // Decrease position by 1.
}
}
func removeFromLists(player: PlayerData) {
removeFromRosterList(player: player)
removeFromDraftList(player: player)
}
fileprivate func removeFromRosterListToBeAdded_2019(player: PlayerData) {
let currentRosterPosition = player.rosterPosition
player.rosterPosition = -1 // No longer on the rosterList. Gets all players on roster at a higher index.
let higherNumberedRosterPlayers = allPlayers.filter({ $0.rosterPosition > currentRosterPosition}) // Their rosterPositions have now gone down by one.
for otherPlayer in higherNumberedRosterPlayers {
otherPlayer.rosterPosition -= 1 // Decrease position by 1.
}
}
// Leagues list to be added to My Leagues
func leaguesList() -> [String] {
return myLeagues
}
func leaguesArray() -> [String] {
let leagues = leaguesList()
return leagues
}
fileprivate func removeFromLeaguesList(player: String) {
let index = IndexPath.Element()
myLeagues.remove(at: index)
}
func removeLeague(league: String) {
removeFromLeaguesList(player: league)
}
// Reset the draft
func resetDraft() {
allPlayers = allPlayersReset
changeMade()
}
// Executed when a change is made
func changeMade() {
playersWriteToDisk()
leaguesWriteToDisk()
}In line 9 of class Database_2019, I created an array of the class PlayerData but it isn't working.This is what class myLeague_2019 looks like:class MyLeague_2019: UIViewController, UITableViewDelegate, UITableViewDataSource {
var players: [[PlayerData]] = [[]]
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
players = Database_2019.shared.myLeaguePlayersData
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
return players.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let players = Database_2019.shared.myLeaguePlayersData[indexPath.section][indexPath.row]
let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(indexPath.row+1). \(players.name), \(players.team) - \(players.position)"
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
return cell
}
@IBOutlet weak var table: UITableView!
}
I am running the following code and it keeps getting an error saying that found nil while unwrapping an optional. What am I doing wrong? I am using a good API.
class Database_2020 {
static let shared = Database_2020()
var leagueNames: [String]
var leagues: [[String]]
let url = " https://www.someURL.com/service/"
private func getData(from url: String) {
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
guard let data = data, error == nil else
print("something went wrong")
return
}
var result: Response?
do {
result = try JSONDecoder().decode(Response.self, from: data)
}
catch {
print("failed to convert \(error.localizedDescription)")
}
guard let json = result else {
return
}
print(json.status)
print(json.results.draftPosition)
print(json.results.name)
}
task.resume()
func printData() {
getData(from: url)
}
}
Is there a way to save data to the iPhone when the app has been deleted so that when the app is reinstalled the app is in the same state it was in before it got deleted? I created an app but when I delete it, it doesn't save and reload the data.