从结构体中填充UITableview

3

我有两个视图控制器,一个叫做programlist,用于显示瓷砖列表并填充适当的视图。

第二个视图控制器用于输入数据。由于在prepareForsegue函数中出现错误,导致实现回调存在问题。出现错误信息:"Instance member 'callback' cannot be used on type 'addWorkout'"

视图控制器1,也称为Programlist:

import UIKit

struct Item: Codable {
var title: String
var others: [String]
}

class ProgramList: UIViewController, UITableViewDataSource, UITableViewDelegate{

var Programs = [Item]()

@IBOutlet weak var programTableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
    load()
}

//saving current state of programs array
func save() {
    guard let data = try? JSONEncoder().encode(Programs) else { return }
    UserDefaults.standard.set(data, forKey: "notes")
}

//loading saved program array
func load() {
    guard let loadedData = UserDefaults.standard.data(forKey: "notes")  else { return }
    do {
        Programs = try JSONDecoder().decode([Item].self, from: loadedData)
        programTableView.reloadData()
    } catch { print(error) }
}






func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Programs.count
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
              cell.programTitle.text = Programs[indexPath.row].title
    return cell
}

//Removing Item by swipping left & saving this newly established array
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == UITableViewCell.EditingStyle.delete {
        Programs.remove(at: indexPath.row)
        programTableView.reloadData()
        save()
    }


    func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "toAddPage"{
            workoutController.callback = { [weak self] string in
                let entered = Item(title: string, others: ["hi"])
                self?.programs.append(entered)
                let indexPath = IndexPath(row: self?.programs.count - 1, section: 0)
                self?.tableView.insertRows(at: [indexPath], with: .automatic)
                self?.save()
         }
       }
    }    
  }
}

  }

视图控制器 2,也称为 addWorkout:

 import UIKit

 class addWorkout: UIViewController {

@IBOutlet weak var workoutTitle: UITextField!

var callback : ((String) -> Void)?

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func saveWorkoutTitle(_ sender: Any) {

    if !workoutTitle.text!.isEmpty {
        callback?(workoutTitle.text!)
    }   
}
}

展示你的其余代码:完整的cellForRowAt方法,任何UITableCell的重写方法,数据源方法...... - undefined
请展示给我们表视图的数据源方法。 - undefined
分享你剩下的代码。 - undefined
请使用正确的方式提问,并尽量自己学习。https://stackoverflow.com/questions/59383482/struct-not-being-populated - undefined
如果数据源数组不在类的外部,那么我无法从输入数据的视图控制器中填充它。 - undefined
显示剩余6条评论
1个回答

3
主要错误在于你试图保存一个不被支持的 Item 数组到 UserDefaults,并尝试读取一个 String 数组。这是一个明显的类型不匹配。
为了能够将自定义结构体的数组保存到 UserDefaults 中,需要采用 Codable 将结构体保存为 JSON 格式。
struct Item : Codable {
    var title: String
    var others: [String]
}

把数据源数组声明在任何类之外是一个非常不好的实践。

这是具有调整后的loadsave方法以及数据源数组位于类内部的ProgramList类。不需要使用viewDidAppear方法。

class ProgramList: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var programTableView: UITableView!

    var programs = [Item]()

    override func viewDidLoad() {
        super.viewDidLoad()
        load()
    }

    //saving current state of programs array
    func save() {
        guard let data = try? JSONEncoder().encode(programs) else { return }
        UserDefaults.standard.set(data, forKey: "notes")
    }

    //loading saved program array
    func load() {
        guard let loadedData = UserDefaults.standard.data(forKey: "notes")  else { return }
        do {
            programs = try JSONDecoder().decode([Item].self, from: loadedData)
            programTableView.reloadData()
        } catch { print(error) }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return programs.count
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
        cell.programTitle.text = programs[indexPath.row].title
        return cell
    }

    //Removing Item by swipping left & saving this newly established array
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            programs.remove(at: indexPath.row)
            programTableView.deleteRows(at: [indexPath], with: .automatic)
            save()
        }
    }
}

为了在控制器之间共享数据,可以将闭包用作回调函数并传递字符串。

class AddWorkout: UIViewController {

    @IBOutlet weak var workoutTitle: UITextField!

    var callback : ((String) -> Void)?

    @IBAction func saveWorkoutTitle(_ sender: Any) {
        if !workoutTitle.text!.isEmpty {
            callback?(workoutTitle.text!)
        }
    }
}

回到ProgramList控制器,在prepareForSegue(或在呈现控制器之前)将闭包分配给callback属性。
 func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "toAddPage" {
        let workoutController = segue.destination as! AddWorkout
        workoutController.callback = { string in
            let entered = Item(title: string, others: ["hi"])
            self.programs.append(entered)
            let indexPath = IndexPath(row: self.programs.count - 1, section: 0)
            self.tableView.insertRows(at: [indexPath], with: .automatic)
            self.save()
        }
    }
}

好的,就在最后一部分,我将workoutController.callback更改为addWorkout.callback,因为这是我添加了训练详情的Swift文件的名称。然而,我收到一个错误,说实例成员'callback'不能在类型'addWorkout'上使用。我将此代码放在了prepareForSegue函数中。 - undefined
请编辑您的问题并添加prepareForSegue。根据命名约定,再次将类名以大写字母开头命名。这样可以避免错误,因为您可以立即看到是类型还是实例。 - undefined
问题已经编辑过了,并且添加了prepareForSegue。对于命名规范不好的地方,我会在实际代码中进行修改。 - undefined
请查看更新后的答案。不要编辑问题并添加解决方案的部分。这会让其他读者感到困惑。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接