Error when trying to save with user defaults - ios

Im having issues saving the table view data to user defaults, im getting the error " Cannot assign value of type '[String]' to type '[ViewController.ItemRow]' " in the load function. It gives the error at the line "items = loadedData". Does anyone know why its giving me this error!I dont know if im even doing it right.
import UIKit
import SafariServices
class ViewController: UIViewController, UIAdaptivePresentationControllerDelegate, UITextFieldDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var OrderNumberLabel: RoundedLabel2!
#IBOutlet weak var CostLabel: RoundedLabel2!
#IBOutlet weak var ProfitLabel: RoundedLabel2!
#IBOutlet weak var TotalLabel: RoundedLabel2!
#IBOutlet weak var itemTextField: UITextField!
#IBOutlet weak var priceTextField: UITextField!
#IBOutlet weak var saleTextField: UITextField!
var items: [ItemRow] = []
struct ItemRow
{
var first: String
var second: String
var third: String
}
override func viewDidLoad() {
super.viewDidLoad()
load()
// tableView.tableFooterView = UIView(frame: CGRect.zero)
}
func save(){
UserDefaults.standard.set(items, forKey: "saved")
}
func load(){
if let loadedData:[String] = UserDefaults.standard.value(forKey: "saved") as? [String]{
items = loadedData
tableView.reloadData()
}
}
#IBAction func addButtonTapped(_ sender: Any) {
insertNewItems()
save()
// profit()
//
}
// func profit(){
// let priceValue = Double(priceTextField.text!)
// let saleValue = Double(saleTextField.text!)
//
// if priceValue != nil && saleValue != nil {
//
// let outputValue = Double (priceValue! - saleValue!)
//
// ProfitLabel.text = "\(outputValue)"
// }
// }
func insertNewItems() {
let newVideoRow = ItemRow(first: itemTextField.text!, second: priceTextField.text!, third: saleTextField.text!)
items.append(newVideoRow)
let indexPath = IndexPath(row: items.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
itemTextField.text = ""
priceTextField.text = ""
saleTextField.text = ""
view.endEditing(true)
}
}
extension ViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let ItemTitle = items[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell") as! ItemCell
cell.itemLabel.text = ItemTitle.first
cell.priceLabel.text = ItemTitle.second
cell.saleLabel.text = ItemTitle.third
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
items.remove(at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
save()
}
}
}

Make your struct conform to the Codable protocol. This is as simple as changing one line to:-
struct ItemRow : Codable
Your save function can be:-
if let data = try? PropertyListEncoder().encode(items) {
UserDefaults.standard.set(data, forKey: "SavedItems")
}
And load can be:
let defaults = UserDefaults.standard
if let data = defaults.data(forKey: "SavedItems") {
items = try! PropertyListDecoder().decode([ItemRow].self, from: data)
tableView.reloadData()
}
A quick look around SO the opinion seems to be that this shouldn't be used for large data sets. So this will get you started, but it may be worth considering a solution a bit more 'database-y' if you need larger amounts of data (e.g. CoreData or Realm).

Related

I m getting 4 times values of same data in tableview cell, so kindly help to pass the data with one value

import UIKit
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource, pass {
var array = [String]()
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var btnPush: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as!TableViewCell
cell.lblName.text = array[indexPath.row]
cell.lblFullName.text = array[indexPath.row]
cell.lblRollno.text = array[indexPath.row]
cell.lblClass.text = array[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
#IBAction func btnPush(_ sender: UIButton) {
let vc = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as!SecondVC
vc.mac = self
self.navigationController?.pushViewController(vc, animated: true)
}
func Datapass(Name: String, FullName Address: String, Rollno: String, Class: String) {
self.array.append(Name)
self.array.append(Address)
self.array.append(Rollno)
self.array.append(Class)
tblView.reloadData()
}
}
import UIKit
protocol pass {
func Datapass(Name:String, FullName:String, Rollno:String, Class:String)
}
class SecondVC: UIViewController {
#IBOutlet weak var textFldName: UITextField!
#IBOutlet weak var txtFldFullName: UITextField!
#IBOutlet weak var txtFldRollno: UITextField!
#IBOutlet weak var txtFldClass: UITextField!
var mac:pass?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnAdd(sender: UIButton) {
mac?.Datapass(Name: textFldName.text!, FullName: txtFldFullName.text!, Rollno: txtFldRollno.text!, Class: txtFldClass.text!)
self.navigationController?.popViewController(animated: true)
}
}
your adding data to your array the wrong way. your adding 4 parameter
and your array will be like this:
array: 0:name|1:Address|2:Rollno|3:Class
and when your reading this from table every time you map this:
cell.lblName.text = array[0]
cell.lblFullName.text = array[0]
cell.lblRollno.text = array[0]
cell.lblClass.text = array[0]
every time table only reads one element of array for 4 times! you are not changing indexpath.row , it will change it's number after loading 1 cell.
the right way to do this is code below:
struct DbModel{
var name:String
var address:String
var rollno:String
var `class`:String
}
var array :[DbModel] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
let model = array[indexPath.row]
cell.lblName.text = model.name
cell.lblFullName.text = model.address
cell.lblRollno.text = model.rollno
cell.lblClass.text = model.class
return cell
}
func Datapass(Name: String, FullName Address: String, Rollno: String, Class: String) {
let model = DbModel(name: Name, address: Address, rollno: Rollno, class: Class)
self.array.append(model)
tblView.reloadData()
}

Swift TableView segue to new ViewController with wrong index path (penultimate selection)

I have a weird problem.
I have two TableViews one for showing Projects and one for showing all Team Members. With both TableViews I have the same bug.
When a user clicks on a Project/ Team Member I want to show the Details for it.
The weird thing is, when running the app and I select a Project/ Team Member for the first time, nothing is happening. When I then select another one, it shows me the details of the previous selected one.
I hope someone can help me with that.
Also a weird thing is, the entry "Sarra Fezzani" was deleted from the Firebase Database and the app was clean build, but it still shows it several times...
Since both codes are pretty similiar I will only post the Code for the ProjetTableViewController without the other files.
//
// TeamViewController.swift
// ProLabArtv2
//
import UIKit
class TeamViewController: UIViewController {
// MARK: - Properties
#IBOutlet weak var memberTableView: UITableView!
#IBOutlet weak var addTeamMember: UIButton!
var members = [TeamMember]()
var textToBeSent: String = ""
override func viewDidLoad() {
super.viewDidLoad()
setUpElements()
UserService.members(for: User.current) { (members) in
self.members = members
self.memberTableView.reloadData()
}
}
// MARK: - Element Style
func setUpElements() {
// Mark: Style the elements
Utilities.addShadowtoButton(addTeamMember)
}
func configureTableView() {
// remove separators for empty cells
memberTableView.tableFooterView = UIView()
// remove separators from cells
memberTableView.separatorStyle = .none
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toMemberDetails" {
let destVC = segue.destination as! TeamMemberDetailsViewController
destVC.member = sender as? TeamMember
}
}
}
// MARK: - UITableViewDataSource
extension TeamViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let member = members[indexPath.row]
let cell = memberTableView.cellForRow(at: indexPath)
print(members)
performSegue(withIdentifier: "toMemberDetails", sender: member)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return members.count
}
// func numberOfSections(in tableView: UITableView) -> Int {
// return members.count
// }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let member = members[indexPath.row]
let cell = memberTableView.dequeueReusableCell(withIdentifier: "TeamMemberCell") as! TeamMemberCell
cell.jobLabel.text = members[indexPath.row].memberJob
cell.nameLabel.text = members[indexPath.row].memberName
return cell
}
}
// MARK: - UITableViewDelegate
extension TeamViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
}
import UIKit
class TeamMemberCell: UITableViewCell {
// MARK: - Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var jobLabel: UILabel!
static let height: CGFloat = 78
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
import Foundation
import UIKit
import FirebaseDatabase.FIRDataSnapshot
class TeamMember {
// Next let's add properties to store all the additional information we need. Add the following to your post class.
var key: String?
let memberName: String
let memberJob: String
let memberLanguage: String
let memberPrice: String
let memberSpecification: String
// You'll get some compiler errors for not having any initializers or default values for certain properties. Let's go ahead and fix that:
init(memberName: String, memberJob: String, memberLanguage: String, memberPrice: String, memberSpecification: String) {
self.memberName = memberName
self.memberJob = memberJob
self.memberLanguage = memberLanguage
self.memberPrice = memberPrice
self.memberSpecification = memberSpecification
}
var dictValue: [String : Any] {
return ["memberName" : memberName,
"memberJob" : memberJob,
"memberLanguage" : memberLanguage,
"memberPrice" : memberPrice,
"memberSpecification" : memberSpecification]
}
init?(snapshot: DataSnapshot) {
guard let dict = snapshot.value as? [String : Any],
let memberName = dict["memberName"] as? String,
let memberJob = dict["memberJob"] as? String,
let memberLanguage = dict["memberLanguage"] as? String,
let memberPrice = dict["memberPrice"] as? String,
let memberSpecification = dict["memberSpecification"] as? String
else { return nil }
self.key = snapshot.key
self.memberName = memberName
self.memberJob = memberJob
self.memberLanguage = memberLanguage
self.memberPrice = memberPrice
self.memberSpecification = memberSpecification
}
}
import Foundation
import FirebaseAuth.FIRUser
import FirebaseDatabase
import FirebaseUI
import FirebaseAuth
struct UserService {
static func members(for user: User, completion: #escaping ([TeamMember]) -> Void) {
let ref = Database.database().reference().child("team").child(user.uid)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let snapshot = snapshot.children.allObjects as? [DataSnapshot] else {
return completion([])
}
let members = snapshot.reversed().compactMap(TeamMember.init)
completion(members)
})
}
}
//
// TeamMemberDetailsViewController.swift
// ProLabArtv2
//
// Created by Manu on 09.06.20.
// Copyright © 2020 Manuel Knott. All rights reserved.
//
import UIKit
import FirebaseDatabase
import FirebaseAuth
import FirebaseStorage
class TeamMemberDetailsViewController: UIViewController {
// MARK: - Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var jobLabel: UILabel!
#IBOutlet weak var specificationLabel: UILabel!
#IBOutlet weak var languageLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var newScoreButton: UIButton!
#IBOutlet weak var projectsPartButton: UIButton!
var member: TeamMember?
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
func setUI() {
nameLabel.text = member?.memberName
jobLabel.text = member?.memberJob
specificationLabel.text = member?.memberSpecification
languageLabel.text = member?.memberLanguage
priceLabel.text = member?.memberPrice
// scoreLabel.text = member?.
}
}
And that's the one for the ProjectViewController, where I am using a switch statement...
// HomeViewController.swift
// ProLabArtv2
//
//
import UIKit
import Kingfisher
import Foundation
import FirebaseStorage
import FirebaseDatabase
class HomeViewController: UIViewController {
// MARK: - Properties
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var addProject: UIButton!
var posts = [Post]()
var textToBeSent: String = ""
override func viewDidLoad() {
super.viewDidLoad()
UserService.posts(for: User.current) { (posts) in
self.posts = posts
self.tableView.reloadData()
}
Utilities.addShadowtoButton(addProject)
}
func configureTableView() {
// remove separators for empty cells
tableView.tableFooterView = UIView()
// remove separators from cells
tableView.separatorStyle = .none
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toDetails" {
let destVC = segue.destination as! ShowProjectDetailsViewController
destVC.post = sender as? Post
}
}
}
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let post = posts[indexPath.row]
performSegue(withIdentifier: "toDetails", sender: post)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func numberOfSections(in tableView: UITableView) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.section]
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "PostImageCell") as! PostImageCell
let imageURL = URL(string: post.imageURL)
cell.postImageView.kf.setImage(with: imageURL)
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "PostSubCell") as! PostSubCell
cell.projectName.text = post.projectTitle
return cell
default:
fatalError("Error: unexpected indexPath.")
}
}
}
// MARK: - UITableViewDelegate
extension HomeViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.row {
case 0:
let post = posts[indexPath.section]
return post.imageHeight
case 1:
return PostSubCell.height
default:
fatalError()
}
}
}
Hopefully someone can help me :)
This is one of those errors we've all made at some point, usually by not reading the autocomplete carefully.
Your code is
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)
You've used the didDeselectRowAt rathert than didSelectRowAt method. Which means that it runs it when that row loses focus (which will be when you click on another row).
You need
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
...
You are using the wrong delegate method. Perform the segue on selecting rather than deselecting a cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let post = posts[indexPath.row]
performSegue(withIdentifier: "toDetails", sender: post)
}

I cant get my calculations print in the label

I am trying to get the values to calculate the profit and print out the calculated numbers in a label, but it isn't printing it out in the label. When I hover over "outputValue" after the app crashed it has the calculated value stored in it, but for some reason it doesn't print out in the label and gives me the error
Cannot assign value of type 'Double' to type 'String?'
at line ProfitLabel.text = (outputValue) in insertNewItems(). Is there any way to fix this?
import UIKit
import SafariServices
class ViewController: UIViewController, UIAdaptivePresentationControllerDelegate, UITextFieldDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var OrderNumberLabel: RoundedLabel2!
#IBOutlet weak var CostLabel: RoundedLabel2!
#IBOutlet weak var ProfitLabel: RoundedLabel2!
#IBOutlet weak var TotalLabel: RoundedLabel2!
#IBOutlet weak var itemTextField: UITextField!
#IBOutlet weak var priceTextField: UITextField!
#IBOutlet weak var saleTextField: UITextField!
var items: [ItemRow] = []
struct ItemRow: Codable
{
var first: String
var second: String
var third: String
}
override func viewDidLoad() {
super.viewDidLoad()
load()
// tableView.tableFooterView = UIView(frame: CGRect.zero)
}
func save(){
if let data = try? PropertyListEncoder().encode(items) {
UserDefaults.standard.set(data, forKey: "SavedItems")
}
}
func load(){
let defaults = UserDefaults.standard
if let data = defaults.data(forKey: "SavedItems") {
items = try! PropertyListDecoder().decode([ItemRow].self, from: data)
}
}
#IBAction func addButtonTapped(_ sender: Any) {
insertNewItems()
save()
}
func insertNewItems() {
let newVideoRow = ItemRow(first: itemTextField.text!, second: priceTextField.text!, third: saleTextField.text!)
items.append(newVideoRow)
let indexPath = IndexPath(row: items.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
let priceValue = Double(priceTextField.text!)
let saleValue = Double(saleTextField.text!)
if priceValue != nil && saleValue != nil {
let outputValue = Double (saleValue! - priceValue!)
ProfitLabel.text = (outputValue)
}
itemTextField.text = ""
priceTextField.text = ""
saleTextField.text = ""
view.endEditing(true)
}
}
extension ViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let ItemTitle = items[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell") as! ItemCell
cell.itemLabel.text = ItemTitle.first
cell.priceLabel.text = ItemTitle.second
cell.saleLabel.text = ItemTitle.third
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
items.remove(at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
save()
}
}
}
Simply disconnect you ProfitLabel and reconnect the outlet.
Also try convert output value to string like this:
ProfitLabel.text = "\(output)"
The error is clear: You are going to assign a Double to a text property which is impossible.
There is an easy solution
ProfitLabel.text = String(outputValue)
However your code is cumbersome and objective-c-ish, the recommended Swift syntax is
if let priceValue = Double(priceTextField.text!),
let saleValue = Double(saleTextField.text!) {
ProfitLabel.text = String(saleValue - priceValue)
}
If the code still crashes then the text field ProfitLabel is not connected in Interface Builder.
Side notes:
Please name variables according to the naming convention with starting lowercase letter.
Delete beginUpdates/endUpdates. Both lines have no effect.
ProfitLabel.text = NSString(format: "%.2f", outputValue) as String
it will round off up to 2 decimal places convert double into the string
You are force unwrapping the values. Replace following code
let priceValue = Double(priceTextField.text!)
let saleValue = Double(salesTextField.text!)
if priceValue != nil && saleValue != nil {
let outputValue = Double (saleValue! - priceValue!)
ProfitLabel.text = (outputValue)
}
With
if let price = Double(priceTextField.text ?? ""), let sale = Double(salesTextField.text ?? "") {
let outputValue = price - sale
ProfitLabel.text = String(outputValue)
} else {
print("Getting nil for \(priceTextField.text) or \(salesTextField.text)")
}
if priceValue != nil && saleValue != nil {
let profit = Double(saleValue)! - Double(priceValue)!
ProfitLabel.text = profit
}

Deleting a UITableView cell in a specific section

There is a task. Each cell contains a button by clicking which you want to delete this cell. The problem is that sections are used to delineate the entire list by category. The data I take from Realm DB. removal must occur under two conditions because the name is repeated, so you need to consider the name from the label and the name of the section. I will be very grateful for the sample code with comments.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
override func viewDidLoad() {
super.viewDidLoad()
purchesTableView.delegate = self
purchesTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
purchesTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return manage.loadPurchases().0.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return manage.loadPurchases().0[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return manage.loadPurchases().1[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
// cell.boughtButton.addTarget(self, action: #selector(removeProduct), for: .touchUpInside)
return cell
}
}
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton!
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
#IBAction func removePurches(_ sender: Any) {
print("remove")
}
}
method for get data
func loadPurchases() -> ([String], Array<Array<String>>, Array<Array<String>>, Array<Array<String>>) {
var sections: [String] = []
var product = Array<Array<String>>()
var weight = Array<Array<String>>()
var nameWeight = Array<Array<String>>()
let realm = try! Realm()
let data = realm.objects(Purches.self)
for item in data {
if sections.contains(item.nameDish) == false {
sections.append(item.nameDish)
}
}
for a in sections {
var productArr = Array<String>()
var weightArr = Array<String>()
var nameWeightArr = Array<String>()
for prod in data {
if a == prod.nameDish {
productArr.append(prod.product)
weightArr.append(prod.weight)
nameWeightArr.append(prod.nameWeigh)
}
}
product.append(productArr)
weight.append(weightArr)
nameWeight.append(nameWeightArr)
}
return (sections, product, weight, nameWeight)
}
Index path you will get in cell class
Index path have two property section and row for table view
Now you can create on more method in Controller class and assign to a variable to every cell or you can use editAction provided by table view for delete
in order to get number section and row you need create IBOutlet in custom cell and on ViewController class is created addTarget for your button.
Example code at the bottom.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
//... more code ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
cell.boughtButton.addTarget(self, action: #selector(removePurches(_:)), for: .touchUpInside)
return cell
}
#objc func removePurches(_ sender: UIButton) {
let position: CGPoint = sender.convert(CGPoint.zero, to: purchesTableView)
let indexPath: IndexPath! = self.purchesTableView.indexPathForRow(at: position)
print("indexPath.row is = \(indexPath.row) && indexPath.section is = \(indexPath.section)")
purchesTableView.deleteRows(at: [indexPath], with: .fade)
}
}
and custom class CustomPurchesTableViewCell for cell
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton! // you button for press
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
}

How do I delete Realm ? I can not be deleted

import UIKit
import RealmSwift
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var text1: UITextField!
#IBOutlet weak var text2: UITextField!
#IBOutlet weak var ttableview: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array1.count
}
func ttableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array1.count
}
/////
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ttableview.dequeueReusableCell(withIdentifier: "cell") as! Cell
cell.lable1.text = array1[indexPath.row]
cell.lable2.text = array2[indexPath.row]
return cell
}
/////
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//this delet Realm
let cat1 = array1[indexPath.row]
let cat2 = array2[indexPath.row]
let realm = try! Realm()
try realm.write {
realm.delete(cat1)
realm.delete(cat2)
}
//this delete table view row and array
array1.remove(at: indexPath.row)
array2.remove(at: indexPath.row)
ttableview.deleteRows(at: [indexPath], with: .fade)
}
}
var array1 = [String]()
var array2 = [String]()
///////////////////
//add 2 text filed in tableview
#IBAction func Add(_ sender: Any) {
addCat()
array1.insert(text1.text!, at: 0)
array2.insert(text2.text!, at: 0)
self.ttableview.reloadData()
}
/////////////
func addCat(){
let realm = try! Realm()
let mike = CCat()
mike.name = (text1.text!)
mike.job = (text2.text!)
try! realm.write {
realm.add(mike)
//print(" \(mike.name) and \(mike.job)")
}
}
////////////////
func queryPeople(){
let realm = try! Realm()
let allPeople = realm.objects(CCat.self)
// var byname = allPeople.sorted(byProperty: "name", ascending: false)
for person in allPeople {
array1.insert(person.name, at: 0)
array2.insert(person.job, at: 0)
print("\(person.name) to \(person.job)")
ttableview.reloadData()
}
}
///////////////////
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
ttableview.delegate = self
ttableview.dataSource = self
// addCat()
queryPeople()
}
The objects you store in Realm are from CCat class (which hopefully inherits from Object), hence you can write (add) them to Realm database.
But as the Xcode says, you are trying to delete a String from realm. Which is not possible.

Resources