Arrays 从结构填充UITableview
我有两个ViewController,一个叫做programlist,它显示平铺列表并填充合适的视图 第二个viewController输入数据。由于Arrays 从结构填充UITableview,arrays,swift,variables,struct,Arrays,Swift,Variables,Struct,我有两个ViewController,一个叫做programlist,它显示平铺列表并填充合适的视图 第二个viewController输入数据。由于prepareForsegue函数中的错误,在实现回调时出现问题。获取错误“实例成员'callback'不能用于'addWorkout'类型” viewController 1又名程序列表: import UIKit struct Item: Codable { var title: String var others: [String] }
prepareForsegue
函数中的错误,在实现回调时出现问题。获取错误“实例成员'callback'不能用于'addWorkout'类型”
viewController 1又名程序列表:
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运动计划:
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!)
}
}
}
主要错误是您试图将
项的数组
保存到用户默认值
,并读取字符串的数组
。这是一个明显的类型不匹配
要能够将自定义结构的数组保存到UserDefaults
中,请采用Codable
将结构保存为JSON
struct Item : Codable {
var title: String
var others: [String]
}
此外,在任何类之外声明数据源数组是一种非常糟糕的做法
这是ProgramList
类,具有调整后的load
和save
方法以及类内的数据源数组。不需要方法viewdide
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
controller为prepareforsgue
中的callback
属性分配一个闭包(或在显示控制器之前)
显示其余代码:完整的
cellForRowAt
、任何UITableCell覆盖、数据源方法……请向我们显示表视图数据源方法。请共享剩余代码。请使用适当的方式提问并尝试学习自己的方法。我已经更新了代码好的,就在最后一节,我将workoutController.callback
更改为addWorkout.callback
,因为这是我添加了训练细节的swift文件的名称。但是,我得到一个错误,即nstance成员“callback”不能用于类型“addWorkout”。我在prepareForSegue
函数中有这个。请编辑您的问题并添加prepareForSegue
。并再次根据命名约定以大写字母开头命名类。这可以避免这些错误,因为您可以立即看到类型和实例。已编辑问题并添加了prepareforsgue
。很抱歉命名约定。我将在实际代码中对此进行修改。请查看更新的答案。不要编辑问题并添加部分解决方案。这将使其他读者感到困惑。
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()
}
}
}