【问题标题】:Populating an UITableview from a struct从结构填充 UITableview
【发布时间】:2019-12-18 00:02:16
【问题描述】:

我有两个视图控制器,一个称为程序列表,它显示图块列表并填充合适的视图。

第二个 viewController 输入数据。由于prepareForsegue 函数中的错误而导致实现回调的问题。收到错误“实例成员 'callback' 不能用于类型 'addWorkout'”

viewController 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()
         }
       }
    }    
  }
}

  }

viewController 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 覆盖、数据源方法......
  • 请向我们展示表格视图数据源方法。
  • 分享你的剩余代码。
  • 请用正确的方式提问,并尝试自己学习。 stackoverflow.com/questions/59383482/struct-not-being-populated
  • 我已经更新了代码

标签: arrays swift variables struct


【解决方案1】:

主要错误是您试图将 Item 数组(无论如何都不支持)保存到 UserDefaults 并读取 String 数组>。这是一个明显的类型不匹配。

为了能够将自定义结构的数组保存到UserDefaults,采用Codable将结构保存为JSON。

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

此外,在任何类之外声明数据源数组是一种非常糟糕的做法。

这是 ProgramList 类,调整了 loadsave 方法以及类内的数据源数组。不需要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,因为这是我添加了锻炼细节的快速文件的名称。但是我收到错误说 nstance 成员 'callback' 不能用于类型 'addWorkout'。我在 prepareForSegue 函数中有这个。
  • 请编辑您的问题并添加prepareForSegue。并再次根据命名约定以大写字母命名类。这可以避免这些错误,因为您可以立即看到什么是类型和什么是实例。
  • 已编辑问题并添加了prepareForSegue。抱歉命名约定。我将在实际代码中对此进行修改。
  • 请查看更新后的答案。并且不要编辑问题并添加部分解决方案。这会让其他读者感到困惑。
猜你喜欢
  • 2018-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
相关资源
最近更新 更多