Я новичок в 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
}
Но когда я вызываю функцию из другого контроллера представления, я получаю фатальную ошибку из-за того, что он пытается развернуть нулевое значение.
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)
}
}
Так что я должен попытаться объединить контроллеры представления, чтобы все было доступно? или переместить экземпляр гардероба в другой класс? или есть приятное простое дополнение, которое я могу сделать к вызову функции, которое позволит получить доступ к таблице.
Спасибо!
Второй 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
}
}
Вот первые вызовы контроллера просмотра
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()
/// }
}
}
Итак, здесь я определяю «гардеробный ход» как переход, который перемещается в контроллер навигации. Я закомментировал оператор if, потому что в этом случае целевой контроллер представления является контроллером навигации, а не контроллером WizardTableViewController, в котором хранится массив одежды. Когда я запускаю отладчик, я вижу, что он передает информацию и назначается массив одежды. но он все равно исчезает до этого.
Между контроллером навигации и контроллером WizardTableViewController находится контроллер табличного представления, который имеет несколько ячеек, и когда выбирается первая, он открывает контроллер WizardTableViewController.
Это немного беспорядок, я следовал двум руководствам, и я думаю, что второе, с добавлением контроллера навигации, немного испортило.





РЕДАКТИРОВАТЬ 2: вы не устанавливали свойство одежды экземпляра класса, для которого выполняется переход (но вы устанавливали новый экземпляр). Измените так:
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 и реализовать prepareForSegue для установки одежды. Что-то вроде:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueIdentifier" {
if let destinationVC = segue.destination as? SecondViewController {
destinationVC.clothes = returncolumns()
}
}
}
Я добавил это. Все очень просто. Я читал, что это может иметь какое-то отношение к контроллеру навигации, вызывающему отмену распределения предыдущих значений? Но я не уверен в этом
см. мое редактирование, если все было настроено правильно, единственное, что вы пропустили, - это перезагрузить таблицу после установки массива
Второй параметр одежды var показывает недопустимое повторное объявление. Если я закомментирую эту строку, я все еще вижу пустой массив после достижения второго контроллера представления.
Да, это было частью старого ответа. Если вы поделитесь кодом о том, как вы выполняете переход и готовитесь, возможно, мы сможем это выяснить
Я добавил то, что думаю поможет. Я очень ценю помощь
см. мое редактирование, когда вы инициализировали новый объект контроллера представления вместо использования контроллера представления segue.destination
Попался, думаю, теперь я понимаю, как работает segue. Поэтому я думаю, что моя проблема в том, что я не перейду к WizardTableViewController прямо из ViewController. Поэтому, когда сегмент доходит до этой строки, он проверяет оператор if, а затем проходит мимо него. Сегмент «гардеробный ход» переходит на навигационный контроллер. И есть еще один переход в точке, где загружается WizardTableViewController, но он исходит из табличного представления, а не из исходного контроллера представления, где переход и данные ...
Я добавил несколько комментариев в свой ответ. В основном поток таков: firstVC выполняет переход к secondVC, в prepareForSegue вы хотите проверить, совпадает ли идентификатор с этим segue (у вас может быть несколько сегментов), и вы хотите проверить, является ли пункт назначения вторымVC. Если это так, то вы хотите установить какое-то свойство вашего назначенияVC. Сообщите мне, помог ли вам мой ответ!
Привет, последнее обновление. Я вырезал средний контроллер навигации, так как это мешало эффективной передаче данных. Спасибо, что показали (и объяснили!) функцию подготовки к переходу. Я очень это ценю!
Привет, думаю, я близок к этому. В отладчике я вижу, что он присваивает правильные значения массиву одежды во втором контроллере представления. Проблема в том, что как только я выхожу из первого контроллера и перехожу ко второму, массив становится пустым. Я не знаю почему он пустеет