Передача данных с 2 на 1 контроллер без unwindSegue


#1

Добрый день, разрабатываю тестовый проект по видеокурсу https://swiftbook.ru/content/26-index/ нахожусь на 17 уроке (Realm), проект делаю не через storyboard, возникла проблема, передачи данных из второго контроллера в первый. в уроке делается через unwindSegue, я пробовал делегатом передавать и замыканием, но что-то недопонимаю, в контроллере

MainTableViewController.swift

var places: Results!

массив данных, а с контроллера где передаю

NewPlaceTableViewController

просто создается модель с конструктором FavoritePlace(…)
и собственно не получается передать данные и чтобы они обновились в первом контроллере когда закрываю второй

проект https://github.com/Constantine1995/MyFavoritePlaces


#2

#3


#4

29
У вас в проекте нет такой функции…

А вообще по подсказке идёт невоспадение типов


#5

потому что я сделал это из вашего примера про делегаты, залил коммит.
Я не развернуто может описал проблему, первый тип массив данных от realm Results а второй тип просто структура, что можно сделать?


#6

Так и непонятно что где.
Вы или сделайте коммит с тем что не получается, чтобы было видно где ошибка вызывается.
Или вставьте сюда код двух контроллеров, связанных делегированием.

что за структура/класс FavoritePlace?


#7

Протокол делегата

protocol NewPlaceCloseProtocol {
func saveData(place: FavoritePlace)
}

класс модели

import RealmSwift
import UIKit

class FavoritePlace: Object {
@objc dynamic var name = “”
@objc dynamic var location: String?
@objc dynamic var type: String?
@objc dynamic var imageData: Data?

convenience init(name: String, location: String?, type: String?, imageData: Data?) {
    self.init()
    self.name = name
    self.location = location
    self.type = type
    self.imageData = imageData
}

}

класс MainTableViewController, первый контроллер

class MainTableViewController: UITableViewController, NewPlaceCloseProtocol {

var newPlaceTVC: NewPlaceTableViewController?

var places: Results<FavoritePlace>!

var favoritePlaceCellId = "favoritePlaceCellId"

let titleHeader: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 20, weight: .medium)
    label.text = "Favorite Places"
    label.textColor = .black
    label.textAlignment = .center
    return label
}()

override func viewDidLoad() {
    super.viewDidLoad()
    places = realm.objects(FavoritePlace.self)
    setupTableView()
    setupNavigation()
    newPlaceTVC?.delegate = self
}

func saveData(place: FavoritePlace) {
    places = place
}

func setupTableView() {
    tableView.register(FavoritePlaceTableViewCell.self, forCellReuseIdentifier: favoritePlaceCellId)
    tableView.separatorStyle = .none
}

func setupNavigation() {
    navigationItem.titleView = titleHeader
    let rightAddButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(goToNewPlace))
    navigationItem.rightBarButtonItem = rightAddButton
}

@objc func goToNewPlace() {
    let newPlaceTableViewController = UINavigationController(rootViewController: NewPlaceTableViewController())
    newPlaceTableViewController.modalTransitionStyle = .flipHorizontal
    navigationController?.present(newPlaceTableViewController, animated: true)
}

// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return places.isEmpty ? 0 : places.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: favoritePlaceCellId, for: indexPath) as! FavoritePlaceTableViewCell
    
    let place = places[indexPath.item]
    cell.nameLabel.text = place.name
    cell.locationLabel.text = place.location
    cell.typeLabel.text = place.type
    cell.placeImageView.image = UIImage(data: place.imageData!)
    
    return cell
}

}

класс второго контроллера NewPlaceTableViewController

class NewPlaceTableViewController: UITableViewController {

var delegate: NewPlaceCloseProtocol?

let newPlaceImageCellId = "newPlaceImageCellId"
let newPlaceInfoCellId = "newPlaceInfoCellId"
let placeCellHeaderData: [PlaceCellHeaderData] = PlaceCellHeaderData.fetchData()
var imageIsChanged = false

let titleHeader: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 20, weight: .medium)
    label.text = "Favorite Places"
    label.textColor = .black
    label.textAlignment = .center
    return label
}()

var placeNameTextField: UITextField = {
    let textfield = UITextField()
    textfield.font = UIFont.systemFont(ofSize: 14)
    return textfield
}()

var placeLocationTextField: UITextField = {
    let textfield = UITextField()
    textfield.font = UIFont.systemFont(ofSize: 14)
    return textfield
}()

var placeTypeTextField: UITextField = {
    let textfield = UITextField()
    textfield.font = UIFont.systemFont(ofSize: 14)
    return textfield
}()

let placeImageView: UIImageView = {
    let imageView = UIImageView(image: #imageLiteral(resourceName: "Photo"))
    return imageView
}()

var saveBarButtonItem: UIBarButtonItem = {
    let barButton = UIBarButtonItem()
    return barButton
}()

var cancelBarButtonItem:  UIBarButtonItem = {
    let barButton = UIBarButtonItem()
    return barButton
}()

override func viewDidLoad() {
    super.viewDidLoad()
    setupTableView()
    setupNavigation()
    setupView()
}

func setupTableView() {
    let placeImageNib = UINib(nibName:  NewPlaceImageTableViewCell.identifier, bundle: nil)
    let placeInfoNib = UINib(nibName:  NewPlaceInfoTableViewCell.identifier, bundle: nil)
    tableView.register(placeImageNib, forCellReuseIdentifier: newPlaceImageCellId)
    tableView.register(placeInfoNib, forCellReuseIdentifier: newPlaceInfoCellId)
    tableView.tableFooterView = UIView()
}

func setupNavigation() {
    navigationItem.titleView = titleHeader
    cancelBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelAction))
    
    saveBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveAction))
    saveBarButtonItem.isEnabled = false
    navigationItem.leftBarButtonItem = cancelBarButtonItem
    navigationItem.rightBarButtonItem = saveBarButtonItem
}

func setupView() {
    placeNameTextField.delegate = self
    placeNameTextField.addTarget(self, action: #selector(textFieldChanged), for: .editingChanged)
}

// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 4
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    switch indexPath.item  {
    case 0:
        let cell = tableView.dequeueReusableCell(withIdentifier: newPlaceImageCellId, for: indexPath) as! NewPlaceImageTableViewCell
        cell.placeImageView.image = placeImageView.image
        cell.selectionStyle = .none
        cell.separatorInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
        return cell
    default:
        let cell = tableView.dequeueReusableCell(withIdentifier: newPlaceInfoCellId, for: indexPath)  as! NewPlaceInfoTableViewCell
        let index = indexPath.item-1
        placeNameTextField =  cell.placeTextField
        cell.placeTextLabel.text = placeCellHeaderData[index].title
        cell.placeTextField.addTarget(self, action: #selector(textFieldChanged), for: .editingChanged)
        cell.selectionStyle = .none
        cell.separatorInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
        return cell
    }
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.row == 0 {
        
        let cameraIcon = #imageLiteral(resourceName: "camera")
        let photoIcon = #imageLiteral(resourceName: "photo")
        
        let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
        let photoFromCamera = UIAlertAction(title: "Camera", style: .default) { _ in
            self.chooseImagePicker(source: .camera)
        }
        
        let photoFromGallery = UIAlertAction(title: "Photo", style: .default) { _ in
            self.chooseImagePicker(source: .photoLibrary)
        }
        
        photoFromCamera.setValue(cameraIcon, forKey: "image")
        photoFromCamera.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        photoFromGallery.setValue(photoIcon, forKey: "image")
        photoFromGallery.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        
        let cancel = UIAlertAction(title: "Cancel", style: .cancel)
        
        actionSheet.addAction(photoFromCamera)
        actionSheet.addAction(photoFromGallery)
        actionSheet.addAction(cancel)
        present(actionSheet, animated:  true)
        
    } else {
        view.endEditing(true)
    }
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.item == 0 {
        return 250
    } else {
        return 75
    }
}

@objc private func cancelAction(_ : UIButton) {
    dismiss(animated: true, completion: nil)
}

@objc private func saveAction(_ : UIButton) {
   
    var image: UIImage?
    if imageIsChanged {
        image = placeImageView.image
    } else {
        image = #imageLiteral(resourceName: "not-pace")
    }
    
    let imageData = image?.pngData()
    print("-- \(placeTypeTextField.text!)")
    let newPlace = FavoritePlace(name: placeNameTextField.text!, location: placeLocationTextField.text, type: placeTypeTextField.text, imageData: imageData)
    StorageManager.saveObject(newPlace)
    
    delegate?.saveData(place: newPlace)
    
    dismiss(animated: true, completion: nil)
}

@objc private func textFieldChanged() {
    if placeNameTextField.text?.isEmpty == false {
        saveBarButtonItem.isEnabled = true
    } else {
        saveBarButtonItem.isEnabled = false
    }
}

}


#8

решил просто обновить tableView с помощью наблюдателя NotificationCenter


#9

С Реалмом плотно не рботал. Но в доках по чтению из базы указано, что методы запросов возвращают коллекцию объектов! Что у вас указано и указано в объявлении
var places: Results<FavoritePlace>!
Вы получаете коллекцию объектов из базы
places = realm.objects(FavoritePlace.self)

А в функции делегата

func saveData(place: FavoritePlace) {
     places = place
 }

…пытаетесь коллекции places присвоить один объект place
Вам надо передавать в функцию такую же коллекцию Results<FavoritePlace> чем и является places Либо использовать методы добавления в коллекции типа .insert()


#10

ну в этом и проблема была… я пытался переделать всю структуру, но тогда ломается другая архитектура