【问题标题】:How to add item to a UICollectionViewController from a separate UIViewController without using Storyboard segue?如何在不使用 Storyboard segue 的情况下将项目从单独的 UIViewController 添加到 UICollectionViewController?
【发布时间】:2020-02-16 15:03:36
【问题描述】:

我有一个 UICollectionViewController 显示一组称为倒计时的数据。我有一个 UIViewController 以模态方式呈现,用户可以在其中创建新的倒计时。当用户点击“添加”(一个 UIBarButtonItem)时,我想将新的倒计时从 UIViewController 添加到 UICollectionViewController 上的数组(以及集合视图)。

我正在完全以编程方式构建我的应用程序(没有故事板文件)。我能找到的每篇文章/堆栈溢出帖子/YouTube 教程都涉及使用 UIStoryBoardSegue 和/或关于将数据从 CollectionView 推送到另一个 ViewController,但不是相反。我还没有找到一种 100% 以编程方式做到这一点的方法。

在我阅读的过程中,纯粹以编程方式创建和使用 segues 通常是不好的。这是真的?如果是这样,我只需要使用代表吗?我将如何实现它?

这里有一些代码:

Countdown 类:(还有其他属性,但为了简单起见,我只包括 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])
}

【问题讨论】:

    标签: ios swift uiviewcontroller uicollectionview segue


    【解决方案1】:

    我会在这里使用委托。

    创建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来展示ViewController

    let vc = ViewController()
    ...
    present(vc, animated: true, completion: nil)
    

    就在present之前,您可以将self设置为代表:

    vc.delegate = self
    

    【讨论】:

    • 这很完美!谢谢!最后一点(在当前之前将 vc delegate 设置为 self)正是我会想念的,然后我会挠头一个小时或更长时间。感谢您为我节省了大量时间。干杯!
    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 2016-02-26
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 2021-11-07
    • 1970-01-01
    相关资源
    最近更新 更多