ios - 如何在不使用 Storyboard segue 的情况下将项目从单独的 UIViewController 添加到 UICollectionViewController?
问题描述
我有一个 UICollectionViewController 显示一个称为倒计时的数据数组。我有一个 UIViewController 以模态方式呈现,用户可以在其中创建新的倒计时。当用户点击“添加”(一个 UIBarButtonItem)时,我想将新的倒计时从 UIViewController 添加到 UICollectionViewController 上的数组(以及集合视图)。
我正在完全以编程方式构建我的应用程序(没有故事板文件)。我能找到的每篇文章/堆栈溢出帖子/YouTube 教程都涉及使用 UIStoryBoardSegue 和/或关于将数据从 CollectionView 推送到另一个 ViewController,但不是相反。我还没有找到以编程方式 100% 执行此操作的方法。
在我的狩猎过程中,我读到纯粹以编程方式创建和使用 segues 通常是不好的。这是真的?如果是这样,我只需要使用代表吗?我将如何实施?
这是一些代码:
倒计时类:(具有其他属性,但为简单起见,我只包括 title 属性)
class Countdown {
var title: String!
init?(title: String!) {
// Fail initialization if string is blank
if title.isEmpty {
return nil
}
// Initializing property
self.title = title
}
}
CountdownCollectionViewController:(这是应用程序的主视图)
class CountdownCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var countdowns = [Countdown]()
override func viewDidLoad() {
super.viewDidLoad()
loadSampleCountdowns()
}
private func loadSampleCountdowns() {
// created 3 sample countdowns here
countdowns += [countdown1, countdown2, countdown3]
}
UIViewController:(从 CountdownsCollectionViewController 模态呈现)
class ViewController: UIViewController {
var countdown: Countdown?
// here I have a textfield property where the user enters a title for a new countdown
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add", style: .done, target: self, action: #selector(addTapped))
}
@objc func addTapped(_ sender: UIBarButtonItem) {
let title = titleTextField.text ?? ""
countdown = Countdown(title: title)
// here is where I want an action to send the newly created countdown to CountdownCollectionViewController
}
我曾尝试在使用 segue 的 CountdownCollectionViewController 中使用此功能,但由于我没有情节提要,它当然不起作用。但是,我认为我正朝着正确的方向前进,其中的代码是:
func unwindToCountdownList(_ sender: UIStoryboardSegue) {
if let sourceViewController = sender.source as? ViewController, let countdown = sourceViewController.countdown {
// Add a new countdown:
let newIndexPath = IndexPath(row: countdowns.count, section: 0)
// Append the new countdown from UIViewController to the array:
countdowns.append(countdown)
// Add new item to collectionView:
collectionView.insertItems(at: [newIndexPath])
}
解决方案
我会在这里使用代表。
创建一个ViewControllerDelegate
:
protocol ViewControllerDelegate: class {
func didCreateCountDown(vc: ViewController, countDown: CountDown)
}
添加一个委托属性ViewController
并在适当的时候调用它:
weak var delegate: ViewControllerDelegate?
@objc func addTapped(_ sender: UIBarButtonItem) {
let title = titleTextField.text ?? ""
countdown = Countdown(title: title)
delegate.didCreateCountDown(vc: self, countDown: countDown)
dismiss(animated: true, completion: nil)
}
使CountdownCollectionViewController
符合ViewControllerDelegate
:
extension CountdownCollectionViewController : ViewControllerDelegate {
func didCreateCountDown(vc: ViewController, countDown: CountDown) {
// Add a new countdown:
let newIndexPath = IndexPath(row: countdowns.count, section: 0)
// Append the new countdown from UIViewController to the array:
countdowns.append(countdown)
// Add new item to collectionView:
collectionView.insertItems(at: [newIndexPath])
}
}
尽管您没有显示此内容,但应该有一个地方 CountdownCollectionViewController
可以调用present
present ViewController
:
let vc = ViewController()
...
present(vc, animated: true, completion: nil)
就在之前present
,您可以设置self
为委托:
vc.delegate = self
推荐阅读
- go - golang如何生成Diffie-Hellman参数
- php - 使用属性值作为方法名 php 按名称调用方法
- ios - 将函数存储在数组中
- jsf - 解决 p:repeat 中的 selectonemenu 索引
- akka-stream - Akka 流:重试元素处理
- shell - 用于替换日期的 sed 命令
- spring-batch - 没有为范围名称“作业”注册的范围,仅使用注释配置运行 Spring Batch 作业
- android - 外部链接在phonegap apk中不起作用
- vue.js - 检测爬虫并从服务器加载模板
- javascript - JS清除已写入txt div的输入值