Here i am creating Global array and appending values to it, which i need to save in two different viewcontrollers tableview
Global array and appending values and sending to two view controllers code:
var addressArray = [String]()
class NewZoomAddressViewController: UIViewController {
weak var delegate: DataEnteredDelegate? = nil
//var addressArray = [String]()
var zipName: String?
var localityName: String?
var sublocalityName: String?
var streetNumber: String?
var streetName: String?
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var addressLabel: UILabel!
var viewController: UIViewController?
#IBAction func confirmBtn(_ sender: Any) {
for controller in navigationController?.viewControllers ?? [] {
if let listController = controller as? ProfileViewController {
let string = "\(streetNumber ?? "") \(streetName ?? "") \(sublocalityName ?? "") \(zipName ?? "") \(localityName ?? "")"
saveaddAddressService()
listController.addressArray.append(string)
navigationController?.popToViewController(controller, animated: true)
return
}
else if let listController = controller as? Add_EditAddressViewController {
let string = "\(sublocalityName ?? "") \(zipName ?? "") \(localityName ?? "")"
listController.addressArray.append(string)
saveaddAddressService()
navigationController?.popToViewController(controller, animated: true)
return
}
}
}
func saveaddAddressService(){
let parameters: [String: Any] = [
"pincode": zipName,
"city": localityName,
"streetName": sublocalityName,
"colony": "",
]
//some JSON code.....
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String: Any]
self.addAddrsID = jsonObject["addressId"] as! String
UserDefaults.standard.set(self.addAddrsID, forKey: "addAddress")
} catch { print(error.localizedDescription) }
}
})
dataTask.resume()
}
Saving array in first view controller view controllers: here i am getting each time with new address the model address also coming, i dont know why?
class ProfileViewController: UIViewController {
var userModel : ProfileModel?
var addressArray = [String]()
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden=true
getUserProfile()
}
func getUserProfile() {
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String :AnyObject]
self.userModel = ProfileModel.init(fromDictionary: jsonObject)
if (self.userModel?.userId) != nil {
DispatchQueue.main.async {
self.updateUserDetails()
self.addressTableview.reloadData()
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if userModel?.userAddresses != nil{
return userModel?.userAddresses.count ?? 0
}
else{
return addressArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: AddresCell = tableView.dequeueReusableCell(withIdentifier: "AddresCell") as! AddresCell
let addr = userModel?.userAddresses![indexPath.row]
if addr?.addressId != nil{
let street = addr?.streetName
let colony = addr?.colony
let city = addr?.city
let pincode = addr?.pincode
cell.address.text = street! + "," + colony! + "," + city! + "," + pincode!
}
else{
cell.address.text = addressArray[indexPath.row]
print("added address in profilr \(cell.address.text)")
}
return cell
}
saving global array in second view controller: here array values are coming, but if i go from this view controller to other view controller the array values gone(not coming.. showing empty.. not saving)
class Add_EditAddressViewController: UIViewController,DataEnteredDelegate {
#IBOutlet weak var addeditTableview: UITableView!
var addressArray = [String]()
override func viewWillAppear(_ animated: Bool) {
addeditTableview.reloadData()
}
}
extension Add_EditAddressViewController : UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return addressArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EditAddressTableViewCell", for: indexPath) as! EditAddressTableViewCell
cell.editButton.addTarget(self, action: #selector(editbuttonClicked(sender:)), for: .touchUpInside)
cell.nameHeader.text = "Other"
cell.addressLabel.text = addressArray[indexPath.row]//"\(city) \(pincode) \(locality)"
}
return cell
}
you can create a singleton class to manage your global array like below GlobalArrayManager class:
import Foundation
class GlobalArrayManager{
static let shared = GlobalArrayManager()
var globalArray : [Int] = []
private init(){}
func getArray()->[Int]{
return globalArray
}
func addDataInArray(data : Int){
globalArray.append(data)
}
}
In first ViewController add data and print:
GlobalArrayManager.shared.addDataInArray(data: 100)
print("array values : ",GlobalArrayManager.shared.getArray())
Output In first ViewController:
array values : [100]
In second ViewController add data and print:
GlobalArrayManager.shared.addDataInArray(data: 200)
print("array values : ",GlobalArrayManager.shared.getArray())
Output In Second ViewController:
array values : [100, 200]
you can add more functionalities in your manager class
Related
my Data Model :
class KeyModell {
var UserID : String?
var key : Array<Any>?
init(UserIDString : String , keyString : Array<Any>? ) {
UserID = UserIDString
key = keyString
}
}
My ViewContoller :
class ViewController: UIViewController {
var userID = ""
var keyContiner = [KeyModell]()
#IBOutlet weak var tableViewOutLet: UITableView!
#IBOutlet weak var textFeildOUtLet: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
FetchUsers(userID: userID) { (user) in
// print("userID His Profile \(user.id)")
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
fetchKey()
tableViewOutLet.reloadData()
}
#objc func fetchKey () {
Database.database().reference().child("AdminKeys").observeSingleEvent(of: .value) { (snapshot) in
// print(snapshot.value)
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let dict = child.value as? [String : Any] {
// print(dict)
let userID = dict["UserID"] as! String
if let keyID = dict["key"] as! Array<Any>? {
let key = KeyModell.init(UserIDString: userID, keyString: keyID)
self.keyContiner.append(key)
self.tableViewOutLet.reloadData()
}
self.tableViewOutLet.reloadData()
}
}
}
func FetchUsers (userID : String , Compation : #escaping (UserModel)->Void) {
Database.database().reference().child("Users").child(userID).observe(.childAdded) { (snapshot) in
if let dic = snapshot.value as? [String : Any] {
let user = UserModel.TransferUserModel(dic: dic, key: snapshot.key)
Compation(user)
}
}
}
#IBAction func saveKeybtn(_ sender: Any) {
let keyString : String = textFeildOUtLet.text!
let keys = keyString.components(separatedBy: ",")
let ref : DatabaseReference!
ref = Database.database().reference()
let AdminKeysREF = ref.child("AdminKeys")
let newKeysPostID = AdminKeysREF.childByAutoId()
guard let userID = Auth.auth().currentUser else {return}
let userKeyId = userID.uid
newKeysPostID.setValue(["UserID": userKeyId , "key" : keys] )
}
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return keyContiner.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! KeyCell
return cell
}
My Cell :
class KeyCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBOutlet weak var keyOUtLet: UILabel!
var key : KeyModell?{
didSet {
upDatekey()
}
}
func upDatekey() {
keyOUtLet.text = key?.key
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
My database :
when i print(cell.key) it give me result :
the problem was when i try to set lable to key mode like this :
func upDatekey() {
keyOUtLet.text = key?.key
}
it give me error "Cannot assign value of type '[Any]?' to type 'String?'"
as my database key value are Array so i set it like this :
var key : Array<Any>?
i think the problem from here i can't figuer it out
I solve the issue ,
my firebase database node is an Int array , so i have to cast my object as [String] than i loop thrught the arrya to extract the kyes
if let key = dict["key"] as? [String] {
for keys in key {
print(keys)
}
than i load it to table view . it work fine .
I have tableview with label, i need to display different array count in tableview for different category. for that i have taken different arrays for different category but i am unable to check condition, all the time the condition goes to outer return count in numberOfRowsInSection and i am getting all category values in tableview.
I have to compare homeVC typeName with AllMakePaymentViewController category name and display accordingly in tableview.
HomeVC code for saving and selecting type for displaying category values in AllMakePaymentViewController tableview:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if itemsArray[indexPath.item].typeName == "WATER"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else if itemsArray[indexPath.item].typeName == "ELECTRICITY"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else if itemsArray[indexPath.item].typeName == "CASH POINT"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else{
AlertFun.ShowAlert(title: "", message: "will update soon..", in: self)
}
}
//MARK:- Service-call
func homeServiceCall(){
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the home json is \(jsonObj)")
let financerArray = jsonObj["financer"] as! [[String: Any]]
for financer in financerArray {
let id = financer["id"] as? String
let pic = financer["icon"] as? String
self.typeName = financer["tpe"] as! String
KeychainWrapper.standard.set(self.typeName!, forKey: "typeName")
var saveTypenameKey = KeychainWrapper.standard.string(forKey: "typeName")
print("keychain typename \(KeychainWrapper.standard.set(self.typeName!, forKey: "typeName"))")
self.itemsArray.append(JsonData(icon: pic ?? "", tpe: self.typeName ?? "", id: id ?? ""))
}
}
catch {
print("catch error")
}
}).resume()
}
AllMakePaymentViewController code:
import UIKit
class PaymentTableViewCell: UITableViewCell{
#IBOutlet weak var pamntTypeLabel: UILabel!
}
class AllMakePaymentViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var electricityArray = [String]()
var waterArray = [String]()
var iteamsArray = [String]()
var categoryName: String?
override func viewDidLoad() {
super.viewDidLoad()
allPaymentService()
}
func allPaymentService(){
let urlStr = "https://dev.com/webservices/api.php?rquest=billermdm"
let url = URL(string: urlStr)
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let respData = data else {
return
}
guard error == nil else {
print("error")
return
}
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the all make payment json is \(jsonObj)")
let billerdetailsArray = jsonObj["billerdetails"] as! [[String: Any]]
for billerdetail in billerdetailsArray {
self.categoryName = billerdetail["bcategoryname"] as? String
if self.categoryName == "Water"{
let bName = billerdetail["bname"] as? String
self.waterArray.append(bName ?? "")
}
if self.categoryName == "cashpoint"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
}
if self.categoryName == "Electricity"{
let bName = billerdetail["bname"] as? String
self.electricityArray.append(bName ?? "")
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch {
print("catch error")
}
}).resume()
}
}
extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if categoryName == "Water"{
return waterArray.count
}
if categoryName == "cashpoint"{
return iteamsArray.count
}
if categoryName == "Electricity"{
return electricityArray.count
}
return iteamsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell
if categoryName == "Electricity"{
cell.pamntTypeLabel.text = electricityArray[indexPath.row]
}
if categoryName == "Water"{
cell.pamntTypeLabel.text = waterArray[indexPath.row]
}
if categoryName == "cashpoint"{
cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
else
{
cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
self.tableView.separatorStyle = .none
return cell
}
}
How to compare homeVC typeName select from didselectItematIndex with AllMakePaymentViewController categoryname and show only selected item categoryName values in tableview label. please help me in the above code. I got stuck here from long time.
You need top inject the category into the nextViewControllers so it knows what data to display. To minimise the use of string literals, I'm converting them into an enum, and have changed the code to use this instead.
enum Category: String {
case water = "WATER"
case electricity = "ELECTRICITY"
case cashpoint = "CASHPOINT"
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
switch Category(rawValue: [indexPath.item].typeName) {
case .water: nextViewcontroller.category = .water
case .electricity: nextViewcontroller.category = .electricity
case .cashpoint: nextViewcontroller.category = .cashpoint
default: AlertFun.ShowAlert(title: "", message: "will update soon..", in: self)
}
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
class AllMakePaymentViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var electricityArray = [String]()
var waterArray = [String]()
var iteamsArray = [String]()
var category: Category?
//load data etc
}
extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let category = category else {return 0}
switch category {
case .electricity: return electricityArray.count
case .water: return waterArray.count
case .cashpoint: return iteamsArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell
guard let category = category else {return 0}
switch category {
case .electricity: cell.pamntTypeLabel.text = electricityArray[indexPath.row]
case .water: cell.pamntTypeLabel.text = waterArray[indexPath.row]
case .cashpoint: cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
self.tableView.separatorStyle = .none
return cell
}
}
Note: not been able to compile this so might be small typos, but it should give you the basis for what you need. Ask if XCode throws up any syntax errors.
I want to show data in UICollectionView. Which is coming from UITableView cell. My main concern is this. I am passing a key catgID from cellForRowAt in another API and getting data from it. But data is not coming proper way.
I am passing catgID from cellForRowAt and getting in another API which will show the list of data for UICollectionViewCells. Now data is coming but not in proper way.
This is my UITableView class for tableview index.
import UIKit
import Reachability
import Alamofire
var arrayMenuProducts = [structMenuProducts]()
struct structMenuProducts {
var id:Int
var product_name:String
var category:String
var product_image:String
var price:String
var unit_price:Double
var addons:NSArray
}
class MenuVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var reachability = Reachability()!
#IBOutlet weak var tableview: UITableView!
var arrayMenuCat = [structMenuCat]()
struct structMenuCat{
var id:Int
var category_name:String
}
override func viewDidLoad() {
super.viewDidLoad()
menuVegAPI()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayMenuCat.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
catgID = arrayMenuCat[indexPath.row].id
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1") as! MenuTableCell
cell.lblCategoryTitle.text = arrayMenuCat[indexPath.row].category_name
cell.collectionviewOne.reloadData()
// let catid = arrayMenuCat[indexPath.row].id
// print(catid)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 216
}
func menuVegAPI()
{
if (reachability.connection == .wifi) || (reachability.connection == .cellular)
{
arrayMenuCat.removeAll()
SwiftLoader.show(animated: true)
let url = BaseUrl + ViewController.sharedInstance.menuCategory
print(url)
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default).responseJSON { response in
SwiftLoader.hide()
switch response.result {
case .success:
let json = response.result.value
print(json)
let code = (json as AnyObject).object(forKey: "code") as! Int
print(code)
if code == 200
{
let data = (json as AnyObject).object(forKey: "data") as? NSArray
for alldata in data!
{
let id = (alldata as AnyObject).object(forKey: "id") as! Int
let category_name = (alldata as AnyObject).object(forKey: "category_name") as! String
let arr = structMenuCat(id: id, category_name: category_name)
self.arrayMenuCat.append(arr)
// self.menuProductsAPI(categoryid: id)
}
self.tableview.reloadData()
}
else
{
}
case .failure:
print("error")
}
}
}
else
{
alert(title: "", message: "Please Check Your Internet Connection")
}
}
}
This is my TableViewCell type class. In this class I am show data on CollectionView. Its code is here
import UIKit
import Alamofire
import Reachability
var catgID : Int!
var collectionreload : UICollectionView?
class MenuTableCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
var reachability = Reachability()!
#IBOutlet weak var lblCategoryTitle: UILabel!
#IBOutlet weak var collectionviewOne: UICollectionView!
var arrayMenuProducts = [structMenuProducts]()
struct structMenuProducts {
var id:Int
var product_name:String
var category:String
var product_image:String
var price:String
var unit_price:Double
var addons:NSArray
}
override func awakeFromNib() {
super.awakeFromNib()
collectionreload = self.collectionviewOne
print(arrayMenuProducts)
print(catgID ?? 0)
menuProductsAPI(categoryid: catgID!)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayMenuProducts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellRID", for: indexPath) as! MenuCollectionViewCell
let abc = arrayMenuProducts[indexPath.row].product_name
print(abc)
// if catgID == Int(arrayMenuProducts[indexPath.row].category)
// {
cell.lblTitleForVeg.text = arrayMenuProducts[indexPath.row].product_name
cell.lblForPriceVeg.text = "$\(arrayMenuProducts[indexPath.row].unit_price)"
}
func menuProductsAPI(categoryid:Int)
{
if (reachability.connection == .wifi) || (reachability.connection == .cellular)
{
SwiftLoader.show(animated: true)
arrayMenuProducts.removeAll()
let url = BaseUrl + ViewController.sharedInstance.menuProducts + "categoryid=\(categoryid)"
print(url)
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { response in
switch response.result {
case .success:
let json = response.result.value
print(json)
// self.tableview.reloadData()
let code = (json as AnyObject).object(forKey: "code") as! Int
print(code)
if code == 200
{
let data = (json as AnyObject).object(forKey: "data") as? NSArray
DispatchQueue.main.async {
for alldata in data!
{
let id = (alldata as AnyObject).object(forKey: "id") as! Int
let product_name = (alldata as AnyObject).object(forKey: "product_name") as! String
let category = (alldata as AnyObject).object(forKey: "category") as! String
let product_image = (alldata as AnyObject).object(forKey: "product_image") as! String
let price = (alldata as AnyObject).object(forKey: "price") as! String
let unit_price = (alldata as AnyObject).object(forKey: "unit_price") as! Double
let addons = (alldata as AnyObject).object(forKey: "addons") as? NSArray
let arr = structMenuProducts(id: id, product_name: product_name, category: category, product_image: product_image, price: price, unit_price: unit_price, addons: addons!)
self.arrayMenuProducts.append(arr)
}
self.collectionviewOne.reloadData()
SwiftLoader.hide()
}
}
else
{
}
case .failure:
print("error")
}
}
}
else
{
// alert(title: "", message: "Please Check Your Internet Connection")
}
}
}
I want to show data coming in CollectionView in a proper formate. If Tableview index == 0 and Category id is coming 10 then. Category id 10 will first then one by one in a sequence I want to pass category id. In my case Category id is not coming in a queue.
Update the tableview datasource method as
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1") as! MenuTableCell
cell.lblCategoryTitle.text = arrayMenuCat[indexPath.row].category_name
cell.menuProductsAPI(categoryid: arrayMenuCat[indexPath.row].id)
return cell
}
And remove menuProductsAPI(categoryid: catgID!) from awakeFromNib method
I've read a lot of related questions here, but am still struggling with populating my tableview. I get the result from the print(firstname) and print(lastname) in the console. But nothing appears in the tableview.
The Table view has a Prototype cell with identifier BasicCell.
Any idea why the table is not populating?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var listTableView: UITableView!
let URL_GET_PERSONAGE = "http://somesite.net/somescript.php"
var firstnames: [String] = []
var lastnames: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: URL_GET_PERSONAGE)
do{
let allContactsData = try Data(contentsOf: url!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = allContacts["teams"] as? NSArray{
for index in 0..<arrJSON.count{
let aObject = arrJSON[index] as? [String : AnyObject]
firstnames.append(aObject?["fname"] as! String)
lastnames.append(aObject?["lname"] as! String)
}
print(firstnames)
print(lastnames)
listTableView.reloadData()
}
}
catch {
}
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return self.firstnames.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell: UITableViewCell! = self.listTableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath as IndexPath) as UITableViewCell!
cell.textLabel?.text = self.firstnames[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I'm attempting to store an array in UserDefaults yet have had no luck in finding a solution. I have a struct and func set up that work to store "name" and "description" in an array. The code is as follows...
struct task {
var name = "Untitled"
var description = "No description available"
}
var tasks = [task]()
func addTask(name: String, description: String) {
tasks.append(task(name: name, description: description))
}
What's the best way to store the data in UserDefaults and add the information to cell.textLabel?.text and cell.detailTextLabel?.text after a relaunch?
It is Swift convention to name your structs starting with an uppercase letter. You need to make a class, make it NSCoding compliant and use KeyedArchiever to save the object data
class Task: NSObject, NSCoding {
let name: String
let desc: String
required init(name: String, desc: String) {
self.name = name
self.desc = desc
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(desc, forKey: "desc")
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.desc = decoder.decodeObject(forKey: "desc") as? String ?? ""
}
}
Testing
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var descField: UITextField!
#IBOutlet weak var tableView: UITableView!
var tasks: [Task] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
if let data = UserDefaults.standard.data(forKey: "tasks") {
tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] ?? []
tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addTask(_ sender: UIButton) {
guard let name = nameField.text, let desc = descField.text else { return }
tasks.append(Task(name: name, desc: desc))
UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: tasks) , forKey: "tasks")
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID")!
cell.textLabel?.text = tasks[indexPath.row].name + " - " + tasks[indexPath.row].desc
return cell
}
}