如何将 IBOutlet 值从视图传递到 VIPER iOs 中的交互器?
How to pass IBOutlet value from view to interactor in VIPER iOs?
我有一个随视图一起加载的 textView。然后用户可以编辑和修改该值,当用户在导航按钮中按下返回时,将启动 viewWillDisappear() 并将 textView 出口的值传递给交互器,该交互器应该从 dataManager 中触发一个方法来保存它对核心数据的价值。
我的问题是在不违反 viper 规则的情况下传递此参数的最佳方法是什么?
我是那样做的,但我几乎可以肯定我做错了。这是我第一次使用 VIPER 架构,如有任何帮助,我们将不胜感激。
查看文件:
import Foundation
import UIKit
class NoteDetailView : UIViewController {
var presenter: NoteDetailPresenterProtocol?
@IBOutlet weak var detailNoteText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
presenter?.viewDidLoad()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
presenter?.updatedText = detailNoteText.text
presenter?.viewWillDisappear()
}
}
extension NoteDetailView : NoteDetailViewProtocol {
func showNote(noteDetail note: NoteModel) {
detailNoteText.text = note.noteText
}
}
主持人:
import Foundation
class NoteDetailPresenter : NoteDetailPresenterProtocol {
var view: NoteDetailViewProtocol?
var updatedText: String?
var note: NoteModel?
var router: NoteDetailRouterProtocol?
var interactor: NoteDetailInteractorProtocol?
func viewDidLoad(){
view?.showNote(noteDetail: note!)
}
func viewWillDisappear() {
guard note?.noteText.isEmpty == false, let text = updatedText else {return}
interactor?.retrieveNote(note: note!, updatedText : text)
}
}
互动者:
import Foundation
class NoteDetailInteractor : NoteDetailInteractorProtocol {
var dataManager: NewNoteDataManagerProtocol?
var localDataManager: NoteListLocalDataManagerInputProtocol?
func retrieveNote(note: NoteModel, updatedText : String) {
do {
if let noteList = try localDataManager?.retrieveNoteList() {
let noteModelList = noteList.map(){
return NoteModel(noteText : [=13=].noteText != nil ? [=13=].noteText! : "", creationDate : [=13=].creationDate != nil ? [=13=].creationDate! : "")
}
if !noteModelList.isEmpty {
var noteTextExist = false
var indexPath = 0
for (index,newnote) in noteModelList.enumerated(){
if newnote == note {
noteTextExist = true
indexPath = index
}
}
if noteTextExist == true {
do {
noteList[indexPath].noteText = updatedText
try dataManager?.updateNote(note: noteList[indexPath])
}
catch {
print(error)
}
}
}
}
}
catch {
print(error)
}
}
}
数据管理器:
import Foundation
import CoreData
import UIKit
class NewNoteDataManager : NewNoteDataManagerProtocol{
func deleteNote(note: Note) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
managedOC.delete(note)
do {
try managedOC.save()
}
catch let error as NSError {
print(error)
}
}
func updateNote(note: Note) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
do {
try managedOC.save()
}
catch let error as NSError {
print(error)
}
}
func saveNote(noteText: String) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
if let entity = NSEntityDescription.entity(forEntityName: String("Note"), in: managedOC) {
do {
let newNote = Note(entity: entity, insertInto: managedOC)
newNote.noteText = noteText
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
newNote.creationDate = formatter.string(from: date)
try managedOC.save()
}catch let error as NSError {
print(error)
}
}else {
throw PersistenceError.couldNotSaveObject
}
}
}
完整的项目可以在这里找到:
https://github.com/AlfroMlg/Notes
说实话,我觉得你的做法还可以。有人可能会争辩说最好不要在演示者中存储 "updatedText" 和 "note" 之类的数据,而是使用方法通过演示者传递这些数据。
您应该引用 presenter 中的视图 weak 以避免保留周期。
并且由于当演示者处于活动状态时交互器和路由器都不会为零,因此您可以将它们声明为非可选的并在 init 中初始化它们。 interactor 中的 dataManager 引用也是如此。
我有一个随视图一起加载的 textView。然后用户可以编辑和修改该值,当用户在导航按钮中按下返回时,将启动 viewWillDisappear() 并将 textView 出口的值传递给交互器,该交互器应该从 dataManager 中触发一个方法来保存它对核心数据的价值。
我的问题是在不违反 viper 规则的情况下传递此参数的最佳方法是什么?
我是那样做的,但我几乎可以肯定我做错了。这是我第一次使用 VIPER 架构,如有任何帮助,我们将不胜感激。
查看文件:
import Foundation
import UIKit
class NoteDetailView : UIViewController {
var presenter: NoteDetailPresenterProtocol?
@IBOutlet weak var detailNoteText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
presenter?.viewDidLoad()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
presenter?.updatedText = detailNoteText.text
presenter?.viewWillDisappear()
}
}
extension NoteDetailView : NoteDetailViewProtocol {
func showNote(noteDetail note: NoteModel) {
detailNoteText.text = note.noteText
}
}
主持人:
import Foundation
class NoteDetailPresenter : NoteDetailPresenterProtocol {
var view: NoteDetailViewProtocol?
var updatedText: String?
var note: NoteModel?
var router: NoteDetailRouterProtocol?
var interactor: NoteDetailInteractorProtocol?
func viewDidLoad(){
view?.showNote(noteDetail: note!)
}
func viewWillDisappear() {
guard note?.noteText.isEmpty == false, let text = updatedText else {return}
interactor?.retrieveNote(note: note!, updatedText : text)
}
}
互动者:
import Foundation
class NoteDetailInteractor : NoteDetailInteractorProtocol {
var dataManager: NewNoteDataManagerProtocol?
var localDataManager: NoteListLocalDataManagerInputProtocol?
func retrieveNote(note: NoteModel, updatedText : String) {
do {
if let noteList = try localDataManager?.retrieveNoteList() {
let noteModelList = noteList.map(){
return NoteModel(noteText : [=13=].noteText != nil ? [=13=].noteText! : "", creationDate : [=13=].creationDate != nil ? [=13=].creationDate! : "")
}
if !noteModelList.isEmpty {
var noteTextExist = false
var indexPath = 0
for (index,newnote) in noteModelList.enumerated(){
if newnote == note {
noteTextExist = true
indexPath = index
}
}
if noteTextExist == true {
do {
noteList[indexPath].noteText = updatedText
try dataManager?.updateNote(note: noteList[indexPath])
}
catch {
print(error)
}
}
}
}
}
catch {
print(error)
}
}
}
数据管理器:
import Foundation
import CoreData
import UIKit
class NewNoteDataManager : NewNoteDataManagerProtocol{
func deleteNote(note: Note) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
managedOC.delete(note)
do {
try managedOC.save()
}
catch let error as NSError {
print(error)
}
}
func updateNote(note: Note) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
do {
try managedOC.save()
}
catch let error as NSError {
print(error)
}
}
func saveNote(noteText: String) throws {
guard let managedOC = CoreDataStore.managedObjectContext else {
throw PersistenceError.managedObjectContextNotFound
}
if let entity = NSEntityDescription.entity(forEntityName: String("Note"), in: managedOC) {
do {
let newNote = Note(entity: entity, insertInto: managedOC)
newNote.noteText = noteText
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
newNote.creationDate = formatter.string(from: date)
try managedOC.save()
}catch let error as NSError {
print(error)
}
}else {
throw PersistenceError.couldNotSaveObject
}
}
}
完整的项目可以在这里找到: https://github.com/AlfroMlg/Notes
说实话,我觉得你的做法还可以。有人可能会争辩说最好不要在演示者中存储 "updatedText" 和 "note" 之类的数据,而是使用方法通过演示者传递这些数据。
您应该引用 presenter 中的视图 weak 以避免保留周期。 并且由于当演示者处于活动状态时交互器和路由器都不会为零,因此您可以将它们声明为非可选的并在 init 中初始化它们。 interactor 中的 dataManager 引用也是如此。