从另一个 ViewController Swift 4 访问对象 (SQLite table)
Accessing an Object (SQLite table) from another ViewController Swift 4
我是 swift 的新手,我想做的是 return 我的 table 中的指定列显示在单独的 viewcontroller 中。我已经使用 SQLite.swift 定义了一个函数,将它们 return 放在一个数组中,就像我希望的那样。 (在同一个 viewcontroller 中调用时有效)
func returncolumns() -> Array<String> {
print("RETURNING")
var namearray = [String]()
do {
for wardrobe in try wardrobedb.prepare(wardrobe.select(name)) {
namearray.append(wardrobe[name])
}
} catch {
print("This no worko \(error)")
}
return namearray
}
但是当我从另一个 viewcontroller 调用该函数时,由于它试图解包 nil 值而出现致命错误。
var clothes = ViewController().returncolumns()
我收集到的是,由于我在没有 table 的情况下从 viewcontroller 调用函数,它无法获得所需的信息。
这里是第一个viewcontroller
的数据库
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var wardrobedb: Connection!
let wardrobe = Table("wardrobe")
let id = Expression<Int64>("id")
let name = Expression<String>("name")
let type = Expression<String>("type")
let color = Expression<String>("color")
let style = Expression<String>("style")
let weight = Expression<String>("weight")
let pattern = Expression<String>("pattern")
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory.appendingPathComponent("wardrobe").appendingPathExtension("sqlite3")
let wardrobedb = try Connection(fileUrl.path)
// let wardrobedb = try remove(fileUrl.path)
self.wardrobedb = wardrobedb
} catch {
print(error)
}
}
那么我是否应该尝试组合视图控制器以便它都可以访问?或者将衣橱实例移到另一个 class?或者我可以对函数调用进行一个很好的简单添加,这将允许访问 table。
谢谢!
第二个ViewController:
import UIKit
class WardrobeTableViewController: UITableViewController {
var clothes = [String]()
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return clothes.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath)
let clothesname = clothes[indexPath.row]
cell.textLabel?.text = clothes[indexPath.row]
cell.detailTextLabel?.text = "Very cool!"
// cell.imageView?.image = UIImage(named: clothesname)
return cell
}
}
这是第一个viewcontroller调用
func returncolumns() -> Array<String> {
print("RETURNING")
var namearray = [String]()
do {
for wardrobe in try wardrobedb.prepare(wardrobe.select(name)) {
namearray.append(wardrobe[name])
}
} catch {
print("This no worko \(error)")
}
return namearray
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "wardrobemove" {
// if let destinationVC = segue.destination as? WardrobeTableViewController {
WardrobeTableViewController().clothes = returncolumns()
/// }
}
}
所以在这里我将 "wardrobemove" 识别为移入导航控制器的 segue。我注释掉了 if 语句,因为在这种情况下,目的地 viewcontroller 是导航控制器,而不是存储衣服数组的 WardrobeTableViewController。当我 运行 调试器时,我看到它传递信息和正在分配的衣服数组。但在那之前它仍然消失了。
在导航控制器和衣柜之间TableViewController有一个 Table 视图控制器,它有几个单元格,当第一个被选中时,它打开衣柜TableViewController.
这有点乱,我遵循了两个指南,我认为第二个引入导航控制器的指南有点乱。
编辑 2:你没有设置 class 实例的衣服 属性 执行 segue(但你设置了一个新的实例)。改成这样:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//check if the performed segue has "wardrobemove" id
if segue.identifier == "wardrobemove" {
//check if the destination is kind of WardrobeTableViewController
if let destinationVC = segue.destination as? WardrobeTableViewController {
//if it is so, then set its property clothes
destinationVC.clothes = returncolumns()
}
}
}
编辑
在你的第二个 vc 中,你想在每次设置衣服数组时重新加载你的 tableView:
var clothes = [String]() {
didSet {
self.tableView.reloadData()
}
}
旧答案
var clothes = ViewController().returncolumns()
您的 FirstVC 中包含所有内容,并且您想在 SecondVC 中设置 衣服基于方法返回的值 returncolumns()
如果是这样,您可能希望在 FirstVC 和 SecondVC 之间执行 segue,并执行 prepareForSegue 来设置衣服。类似于:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueIdentifier" {
if let destinationVC = segue.destination as? SecondViewController {
destinationVC.clothes = returncolumns()
}
}
}
我是 swift 的新手,我想做的是 return 我的 table 中的指定列显示在单独的 viewcontroller 中。我已经使用 SQLite.swift 定义了一个函数,将它们 return 放在一个数组中,就像我希望的那样。 (在同一个 viewcontroller 中调用时有效)
func returncolumns() -> Array<String> {
print("RETURNING")
var namearray = [String]()
do {
for wardrobe in try wardrobedb.prepare(wardrobe.select(name)) {
namearray.append(wardrobe[name])
}
} catch {
print("This no worko \(error)")
}
return namearray
}
但是当我从另一个 viewcontroller 调用该函数时,由于它试图解包 nil 值而出现致命错误。
var clothes = ViewController().returncolumns()
我收集到的是,由于我在没有 table 的情况下从 viewcontroller 调用函数,它无法获得所需的信息。
这里是第一个viewcontroller
的数据库class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var wardrobedb: Connection!
let wardrobe = Table("wardrobe")
let id = Expression<Int64>("id")
let name = Expression<String>("name")
let type = Expression<String>("type")
let color = Expression<String>("color")
let style = Expression<String>("style")
let weight = Expression<String>("weight")
let pattern = Expression<String>("pattern")
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory.appendingPathComponent("wardrobe").appendingPathExtension("sqlite3")
let wardrobedb = try Connection(fileUrl.path)
// let wardrobedb = try remove(fileUrl.path)
self.wardrobedb = wardrobedb
} catch {
print(error)
}
}
那么我是否应该尝试组合视图控制器以便它都可以访问?或者将衣橱实例移到另一个 class?或者我可以对函数调用进行一个很好的简单添加,这将允许访问 table。
谢谢!
第二个ViewController:
import UIKit
class WardrobeTableViewController: UITableViewController {
var clothes = [String]()
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return clothes.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath)
let clothesname = clothes[indexPath.row]
cell.textLabel?.text = clothes[indexPath.row]
cell.detailTextLabel?.text = "Very cool!"
// cell.imageView?.image = UIImage(named: clothesname)
return cell
}
}
这是第一个viewcontroller调用
func returncolumns() -> Array<String> {
print("RETURNING")
var namearray = [String]()
do {
for wardrobe in try wardrobedb.prepare(wardrobe.select(name)) {
namearray.append(wardrobe[name])
}
} catch {
print("This no worko \(error)")
}
return namearray
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "wardrobemove" {
// if let destinationVC = segue.destination as? WardrobeTableViewController {
WardrobeTableViewController().clothes = returncolumns()
/// }
}
}
所以在这里我将 "wardrobemove" 识别为移入导航控制器的 segue。我注释掉了 if 语句,因为在这种情况下,目的地 viewcontroller 是导航控制器,而不是存储衣服数组的 WardrobeTableViewController。当我 运行 调试器时,我看到它传递信息和正在分配的衣服数组。但在那之前它仍然消失了。
在导航控制器和衣柜之间TableViewController有一个 Table 视图控制器,它有几个单元格,当第一个被选中时,它打开衣柜TableViewController.
这有点乱,我遵循了两个指南,我认为第二个引入导航控制器的指南有点乱。
编辑 2:你没有设置 class 实例的衣服 属性 执行 segue(但你设置了一个新的实例)。改成这样:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//check if the performed segue has "wardrobemove" id
if segue.identifier == "wardrobemove" {
//check if the destination is kind of WardrobeTableViewController
if let destinationVC = segue.destination as? WardrobeTableViewController {
//if it is so, then set its property clothes
destinationVC.clothes = returncolumns()
}
}
}
编辑
在你的第二个 vc 中,你想在每次设置衣服数组时重新加载你的 tableView:
var clothes = [String]() {
didSet {
self.tableView.reloadData()
}
}
旧答案
var clothes = ViewController().returncolumns()
您的 FirstVC 中包含所有内容,并且您想在 SecondVC 中设置 衣服基于方法返回的值 returncolumns()
如果是这样,您可能希望在 FirstVC 和 SecondVC 之间执行 segue,并执行 prepareForSegue 来设置衣服。类似于:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueIdentifier" {
if let destinationVC = segue.destination as? SecondViewController {
destinationVC.clothes = returncolumns()
}
}
}