Swift Playgrounds 中的一个简单的笔记应用程序
A simple notes app in Swift Playgrounds
我正在尝试在 Swift Playgrounds 中创建一个简单的笔记应用程序,但我被卡住了。
如何在没有 prepareForSegue
的情况下将数据从主视图(即 UITableView
)发送到详细视图(即 UITextView
),反之亦然,因为没有故事板?
我错过了什么或做错了什么?
我一直在拼命寻找解决方案,因此非常感谢您的帮助。
这是我的游乐场:
import UIKit
import PlaygroundSupport
class MasterViewController: UITableViewController {
var noteData: [String] = []
var selectedRow: Int = -1
var newRowLabel: String = ""
override func viewDidLoad() {
configureNavigationBar()
loadNote()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if selectedRow == -1 {
return
}
noteData[selectedRow] = newRowLabel
if newRowLabel == "" {
noteData.remove(at: selectedRow)
}
tableView.reloadData()
saveNote()
}
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
navigationController?.pushViewController(DetailViewController(), animated: true)
}
func configureNavigationBar() {
title = "Notes"
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(newNote))
navigationItem.rightBarButtonItem = addButton
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return noteData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
}
cell?.textLabel?.text = noteData[indexPath.row]
return cell!
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
noteData.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
saveNote()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let detailView: DetailViewController = segue.destination as! DetailViewController
selectedRow = tableView.indexPathForSelectedRow!.row
detailView.masterView = self
detailView.setText(noteText: noteData[selectedRow])
}
func saveNote() {
UserDefaults.standard.set(noteData, forKey: "Notes")
UserDefaults.standard.synchronize()
}
func loadNote() {
if let loadedNote = UserDefaults.standard.value(forKey: "notes") as? [String] {
noteData = loadedNote
tableView.reloadData()
}
}
}
class DetailViewController: UIViewController {
let textView = UITextView()
var noteText: String = ""
var masterView: MasterViewController!
override func loadView() {
configureDetailView()
}
override func viewDidLoad() {
configureTextView()
}
func configureDetailView() {
view = textView
}
func configureTextView() {
textView.text = noteText
}
func setText(noteText: String) {
if isViewLoaded {
textView.text = noteText
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
masterView?.newRowLabel = noteText
}
}
let masterViewController = MasterViewController()
let navigationController = UINavigationController(rootViewController: masterViewController)
PlaygroundPage.current.liveView = navigationController
而不是
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
您可以像这样创建 DetailViewController 并分配 noteText
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detailViewController = DetailViewController()
detailViewController.noteText = noteData[indexPath.row]
detailViewController.masterView = self
navigationController?.pushViewController(detailViewController, animated: true)
}
函数prepare
可以删掉,因为你没有用storyboards所以不用
别忘了适应 newNote()
:
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
let detailViewController = DetailViewController()
detailViewController.masterView = self
navigationController?.pushViewController(detailViewController, animated: true)
}
在您的 didSelectRow
方法中:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
你正在创建你的 DetailViewController()
但当你的视图控制器有变量来接受数据时没有向它传递任何数据,所以为了做到这一点而不是做:
navigationController?.pushViewController(DetailViewController(), animated: true)
你可以做到:
let detailVC = DetailViewController()
detailVC.noteText = noteData[indexPath.row]
navigationController?.pushViewController(detailVC, animated: true)
编辑: 我正在从这里更新我的答案,因为您的解决方案需要进行大量更改才能实现,就像我上面解释的如何传递数据的方式一样,您有在不同的地方以及您创建新笔记的地方执行此操作
首先,为了让您的新内容保存并让 table 视图单元格自行更新,您需要调整您的 newNote()
功能:
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
selectedRow = indexPath.row
let detailVC = DetailViewController()
detailVC.masterView = self
navigationController?.pushViewController(detailVC, animated: true)
}
您将 selectedRow
变量设置为插入的 indexPath
并将 masterView
传递给 DetailsViewController()
其次,您还需要更改 didSelectRow
,使用我发布的相同解决方案,但同样也将您的 masterView
和 selectedRow
也传递到那里,所以它应该看起来像这样:
let detailVC = DetailViewController()
detailVC.noteText = noteData[indexPath.row]
detailVC.masterView = self
selectedRow = indexPath.row
navigationController?.pushViewController(detailVC, animated: true)
第三,您的 DetailViewController 缺少一件事,无论何时在您的文本视图中输入文本,它都不会更新 noteText
而您的 viewWillDisappear
方法依赖于此,您需要设置文本视图的委托自己听文本变化,但是为了更简单的解决方案,将您的 viewWillDisappear
更改为直接访问 textView
,如下所示:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
masterView?.newRowLabel = textView.text
}
第四,当你从这个屏幕返回时,你的 MasterViewController 需要将它保存在你的 viewWillAppear
方法中,那里也需要一些改变,实际上并不多,你只需要重置你的 selectedRow
保存注释后变量,因此在您调用后:
saveNote()
在下一行还添加:
selectedRow = -1
我正在尝试在 Swift Playgrounds 中创建一个简单的笔记应用程序,但我被卡住了。
如何在没有 prepareForSegue
的情况下将数据从主视图(即 UITableView
)发送到详细视图(即 UITextView
),反之亦然,因为没有故事板?
我错过了什么或做错了什么?
我一直在拼命寻找解决方案,因此非常感谢您的帮助。
这是我的游乐场:
import UIKit
import PlaygroundSupport
class MasterViewController: UITableViewController {
var noteData: [String] = []
var selectedRow: Int = -1
var newRowLabel: String = ""
override func viewDidLoad() {
configureNavigationBar()
loadNote()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if selectedRow == -1 {
return
}
noteData[selectedRow] = newRowLabel
if newRowLabel == "" {
noteData.remove(at: selectedRow)
}
tableView.reloadData()
saveNote()
}
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
navigationController?.pushViewController(DetailViewController(), animated: true)
}
func configureNavigationBar() {
title = "Notes"
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(newNote))
navigationItem.rightBarButtonItem = addButton
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return noteData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
}
cell?.textLabel?.text = noteData[indexPath.row]
return cell!
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
noteData.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
saveNote()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let detailView: DetailViewController = segue.destination as! DetailViewController
selectedRow = tableView.indexPathForSelectedRow!.row
detailView.masterView = self
detailView.setText(noteText: noteData[selectedRow])
}
func saveNote() {
UserDefaults.standard.set(noteData, forKey: "Notes")
UserDefaults.standard.synchronize()
}
func loadNote() {
if let loadedNote = UserDefaults.standard.value(forKey: "notes") as? [String] {
noteData = loadedNote
tableView.reloadData()
}
}
}
class DetailViewController: UIViewController {
let textView = UITextView()
var noteText: String = ""
var masterView: MasterViewController!
override func loadView() {
configureDetailView()
}
override func viewDidLoad() {
configureTextView()
}
func configureDetailView() {
view = textView
}
func configureTextView() {
textView.text = noteText
}
func setText(noteText: String) {
if isViewLoaded {
textView.text = noteText
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
masterView?.newRowLabel = noteText
}
}
let masterViewController = MasterViewController()
let navigationController = UINavigationController(rootViewController: masterViewController)
PlaygroundPage.current.liveView = navigationController
而不是
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
您可以像这样创建 DetailViewController 并分配 noteText
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detailViewController = DetailViewController()
detailViewController.noteText = noteData[indexPath.row]
detailViewController.masterView = self
navigationController?.pushViewController(detailViewController, animated: true)
}
函数prepare
可以删掉,因为你没有用storyboards所以不用
别忘了适应 newNote()
:
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
let detailViewController = DetailViewController()
detailViewController.masterView = self
navigationController?.pushViewController(detailViewController, animated: true)
}
在您的 didSelectRow
方法中:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(DetailViewController(), animated: true)
}
你正在创建你的 DetailViewController()
但当你的视图控制器有变量来接受数据时没有向它传递任何数据,所以为了做到这一点而不是做:
navigationController?.pushViewController(DetailViewController(), animated: true)
你可以做到:
let detailVC = DetailViewController()
detailVC.noteText = noteData[indexPath.row]
navigationController?.pushViewController(detailVC, animated: true)
编辑: 我正在从这里更新我的答案,因为您的解决方案需要进行大量更改才能实现,就像我上面解释的如何传递数据的方式一样,您有在不同的地方以及您创建新笔记的地方执行此操作
首先,为了让您的新内容保存并让 table 视图单元格自行更新,您需要调整您的 newNote()
功能:
@objc func newNote() {
let noteTitle: String = ""
noteData.insert(noteTitle, at: 0)
let indexPath: IndexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
selectedRow = indexPath.row
let detailVC = DetailViewController()
detailVC.masterView = self
navigationController?.pushViewController(detailVC, animated: true)
}
您将 selectedRow
变量设置为插入的 indexPath
并将 masterView
传递给 DetailsViewController()
其次,您还需要更改 didSelectRow
,使用我发布的相同解决方案,但同样也将您的 masterView
和 selectedRow
也传递到那里,所以它应该看起来像这样:
let detailVC = DetailViewController()
detailVC.noteText = noteData[indexPath.row]
detailVC.masterView = self
selectedRow = indexPath.row
navigationController?.pushViewController(detailVC, animated: true)
第三,您的 DetailViewController 缺少一件事,无论何时在您的文本视图中输入文本,它都不会更新 noteText
而您的 viewWillDisappear
方法依赖于此,您需要设置文本视图的委托自己听文本变化,但是为了更简单的解决方案,将您的 viewWillDisappear
更改为直接访问 textView
,如下所示:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
masterView?.newRowLabel = textView.text
}
第四,当你从这个屏幕返回时,你的 MasterViewController 需要将它保存在你的 viewWillAppear
方法中,那里也需要一些改变,实际上并不多,你只需要重置你的 selectedRow
保存注释后变量,因此在您调用后:
saveNote()
在下一行还添加:
selectedRow = -1