首页 > 解决方案 > 从另一个 ViewController Swift 4 访问对象(SQLite 表)

问题描述

我是 swift 新手,我想做的是返回表中的指定列以显示在单独的视图控制器中。我已经使用 SQLite.swift 定义了一个函数,它将它们返回到一个数组中,就像我希望它们那样。(在同一个视图控制器中调用时有效)

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
}

但是当我从另一个视图控制器调用该函数时,由于它试图解开一个 nil 值,我得到了一个致命错误。

var clothes = ViewController().returncolumns()

我收集到的是,由于我从没有表的视图控制器调用函数,它无法获得它需要的信息。

这是第一个视图控制器中的数据库

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

那么我应该尝试组合视图控制器以使其全部可访问吗?或者将衣柜实例化到另一个类?或者我可以对函数调用进行一个很好的简单添加,以允许访问表。

谢谢!

第二个视图控制器:

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
}
}

这是第一个视图控制器调用

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 语句,因为在这种情况下,目标视图控制器是导航控制器,而不是存储衣服数组的 WardrobeTableViewController。当我运行调试器时,我看到它传递信息和分配的衣服数组。但在那之前它仍然消失了。

Between the Navigation controller and the WardrobeTableViewController there is a Table view controller which has a few cells and when the first one is selected, it opens the WardrobeTableViewController.

这有点乱,我遵循了两个指南,我认为第二个引入导航控制器的指南有点搞砸了。

标签: iosswiftxcodesqlitesqlite.swift

解决方案


EDIT 2: you were not setting the clothes property of the instance of the class the segue is performed (but you were setting a new instance). Change like this:

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

EDIT

In your second vc, you want to reload your tableView every time you set the array of clothes:

var clothes = [String]() {
    didSet {
        self.tableView.reloadData()
    }
}

Old answer

var clothes = ViewController().returncolumns()

You have everything in your FirstVC and you want to set clothes in the SecondVC based on the value returned by the method returncolumns()

If it is so, you might want to perform a segue between FirstVC and SecondVC, and implement prepareForSegue to set clothes. Something like:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segueIdentifier" {
        if let destinationVC = segue.destination as? SecondViewController {
            destinationVC.clothes = returncolumns()
        }
    }
}

推荐阅读