Swift:关闭 ViewController 时更新 ViewController 的布局和内容
Swift: Update Layout and Content of ViewController when dismissing presented ViewController
我有一个 UIView,它显示一些信息,例如用户名等,包括所有从我的数据库中提取的对象列表。这很好用。
但是,我现在有一个 ViewController 显示在当前 ViewController 之上。在此呈现的 ViewController 中,我将数据添加到我的数据库中。关闭该视图时,我希望原始 ViewController 更新其所有内容以保持最新。
现在,我所有的视图都在 ViewDidLoad 中进行布局,这意味着它们只真正加载一次,以后不会重新加载。我已经通过调用 self.view.layoutIfNeeded()
设法更新布局,但如果我理解正确,这只会更新约束。当然,我可以调用我原来的视图控制器的新初始化。这会使它重新加载,但我想避免这种情况。
我的另一个想法是在 ViewWillAppear 中设置我的所有内容,然后在我的视图控制器即将可见时更新它。但是,我不知道该怎么做。我可以将所有设置代码移动到 viewWillAppear 吗?这有什么缺点吗?
TLDR:有没有一种方法可以使用新元素更新堆栈视图,而无需通过 ViewWillAppear 重新加载完整 ViewController?
UITableView 元素处理数据库数据非常顺畅。如果您在第一个视图控制器中从 viewDidLoad 中的数据库中获取数据,并将其存储在一个数组中,则 UITableView(如果您正确设置了它的数据源)将自动使用第二个视图控制器中的新值填充 table视图控制器。有了这个方法,就完全不用ViewWillAppear了
听起来您现在正在使用视图(在 VStack 中)?显示数据库中的单个对象。如果您想保留视图中使用的任何自定义 style/layout,可以通过定义 UITableViewCell 的自定义子类并选择“同时创建 XIB 文件”选项来实现。 XIB 文件可让您自定义 UITableView 中单元格的外观。
这里是一个简单的例子,显示第一个视图控制器中的数据库值自动更新。我没有包括自定义 XIB 文件(这些都是默认的 UITableViewCells),以保持其精简。
第一视图控制器
import UIKit
import CoreData
class ViewController: UIViewController {
@IBOutlet weak var dataTable: UITableView!
var tableRows: [DataItem] = []
func loadData() {
let request: NSFetchRequest<DataItem> = DataItem.fetchRequest()
do {
tableRows = try Global_Context.fetch(request)
} catch {
print("Error loading data: \(error)")
}
}
override func viewDidLoad() {
super.viewDidLoad()
dataTable.dataSource = self
loadData()
}
@IBAction func goForward(_ sender: UIButton) {
self.performSegue(withIdentifier: "toSecond", sender: self)
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableRows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dataTableCell", for: indexPath)
cell.textLabel?.text = tableRows[indexPath.row].name
return cell
}
}
let Global_Context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func saveContext () {
if Global_Context.hasChanges {
do {
try Global_Context.save()
} catch {
let nserror = error as NSError
print("Error saving database context: \(nserror), \(nserror.userInfo)")
}
}
}
第二个视图控制器:
import UIKit
import CoreData
class AddViewController: UIViewController {
@IBOutlet weak var itemEntry: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
itemEntry.delegate = self
}
@IBAction func addNewItem(_ sender: UIButton) {
let newDataItem = DataItem(context: Global_Context)
newDataItem.name = itemEntry.text
saveContext()
}
@IBAction func goBack(_ sender: UIButton) {
self.performSegue(withIdentifier: "toFirst", sender: self)
}
}
extension AddViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.endEditing(true)
return true
}
}
Main.storyboard:
一旦您将视图控制器设置为 UITableViewDataSource(如示例代码中所示),table 视图应该会消除任何手动管理单个视图的需要,从而使事情变得更简单。
这是您正在寻找的功能吗? (注意示例:它是在 Xcode 中设置的,启用了“使用核心数据”。)
这是官方文档的link:
https://developer.apple.com/documentation/uikit/uitableview
我有一个 UIView,它显示一些信息,例如用户名等,包括所有从我的数据库中提取的对象列表。这很好用。
但是,我现在有一个 ViewController 显示在当前 ViewController 之上。在此呈现的 ViewController 中,我将数据添加到我的数据库中。关闭该视图时,我希望原始 ViewController 更新其所有内容以保持最新。
现在,我所有的视图都在 ViewDidLoad 中进行布局,这意味着它们只真正加载一次,以后不会重新加载。我已经通过调用 self.view.layoutIfNeeded()
设法更新布局,但如果我理解正确,这只会更新约束。当然,我可以调用我原来的视图控制器的新初始化。这会使它重新加载,但我想避免这种情况。
我的另一个想法是在 ViewWillAppear 中设置我的所有内容,然后在我的视图控制器即将可见时更新它。但是,我不知道该怎么做。我可以将所有设置代码移动到 viewWillAppear 吗?这有什么缺点吗?
TLDR:有没有一种方法可以使用新元素更新堆栈视图,而无需通过 ViewWillAppear 重新加载完整 ViewController?
UITableView 元素处理数据库数据非常顺畅。如果您在第一个视图控制器中从 viewDidLoad 中的数据库中获取数据,并将其存储在一个数组中,则 UITableView(如果您正确设置了它的数据源)将自动使用第二个视图控制器中的新值填充 table视图控制器。有了这个方法,就完全不用ViewWillAppear了
听起来您现在正在使用视图(在 VStack 中)?显示数据库中的单个对象。如果您想保留视图中使用的任何自定义 style/layout,可以通过定义 UITableViewCell 的自定义子类并选择“同时创建 XIB 文件”选项来实现。 XIB 文件可让您自定义 UITableView 中单元格的外观。
这里是一个简单的例子,显示第一个视图控制器中的数据库值自动更新。我没有包括自定义 XIB 文件(这些都是默认的 UITableViewCells),以保持其精简。
第一视图控制器
import UIKit
import CoreData
class ViewController: UIViewController {
@IBOutlet weak var dataTable: UITableView!
var tableRows: [DataItem] = []
func loadData() {
let request: NSFetchRequest<DataItem> = DataItem.fetchRequest()
do {
tableRows = try Global_Context.fetch(request)
} catch {
print("Error loading data: \(error)")
}
}
override func viewDidLoad() {
super.viewDidLoad()
dataTable.dataSource = self
loadData()
}
@IBAction func goForward(_ sender: UIButton) {
self.performSegue(withIdentifier: "toSecond", sender: self)
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableRows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dataTableCell", for: indexPath)
cell.textLabel?.text = tableRows[indexPath.row].name
return cell
}
}
let Global_Context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func saveContext () {
if Global_Context.hasChanges {
do {
try Global_Context.save()
} catch {
let nserror = error as NSError
print("Error saving database context: \(nserror), \(nserror.userInfo)")
}
}
}
第二个视图控制器:
import UIKit
import CoreData
class AddViewController: UIViewController {
@IBOutlet weak var itemEntry: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
itemEntry.delegate = self
}
@IBAction func addNewItem(_ sender: UIButton) {
let newDataItem = DataItem(context: Global_Context)
newDataItem.name = itemEntry.text
saveContext()
}
@IBAction func goBack(_ sender: UIButton) {
self.performSegue(withIdentifier: "toFirst", sender: self)
}
}
extension AddViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.endEditing(true)
return true
}
}
Main.storyboard:
一旦您将视图控制器设置为 UITableViewDataSource(如示例代码中所示),table 视图应该会消除任何手动管理单个视图的需要,从而使事情变得更简单。
这是您正在寻找的功能吗? (注意示例:它是在 Xcode 中设置的,启用了“使用核心数据”。)
这是官方文档的link: https://developer.apple.com/documentation/uikit/uitableview