You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法在Collection View中显示App Delegate存储的数组数据

问题:无法从AppDelegate获取Meme数组并在Collection View中实时更新

我正在开发一款Meme(表情包)生成器应用,该生成器以模态方式呈现,集成在Tab Bar View Controller中。第一个标签页通过Table View展示所有已保存的Meme,第二个标签页计划通过Collection View展示已保存的Meme。

Meme生成器功能正常,会将生成的Meme保存到App Delegate文件中的数组内(我知道这种做法有争议,但这是练习要求)。我尝试配置Collection View,但无法获取App Delegate中的Meme对象引用,且不清楚原因。

我的CollectionViewController代码如下:

import UIKit
class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
    @IBOutlet weak var collectionView: UICollectionView!
    var memes: [Meme]! {
        didSet {
            collectionView.reloadData()
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        memes = appDelegate.memes
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return memes.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.imageView.image = memes[indexPath].memedImage
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    }
}

该代码是基于可正常运行的Table View代码编写的,Table View代码如下:

import UIKit
class TableViewMemesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var tableView: UITableView!
    var memes: [Meme]! {
        didSet {
            tableView.reloadData()
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        memes = appDelegate.memes
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return memes.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
        let meme = memes[indexPath.row]
        cell?.imageView?.image = meme.memedImage
        cell?.textLabel?.text = meme.topText
        return cell!
    }
}

请问如何获取该数组数据,并在用户保存新Meme时在Collection View中显示?


回答

让我们一步步解决你的问题:

1. 修复Collection View Cell的核心访问问题

首先看你cellForItemAt方法里的代码,这里有两个关键错误:

  • UICollectionViewCell默认没有imageView属性(这和UITableViewCell的默认配置不一样),你需要创建自定义Collection View Cell类来绑定图片控件。
  • 访问数组元素时用了memes[indexPath],Collection View应该用indexPath.item(Table View才用row)。

先创建自定义Cell类:

import UIKit

class MemeCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var memeImageView: UIImageView!
}

然后在Storyboard中:

  • 选中Collection View Cell,在Identity Inspector里设置Class为MemeCollectionViewCell
  • 给Cell添加UIImageView,将其与memeImageView的IBOutlet绑定

修改后的cellForItemAt方法:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MemeCollectionViewCell
    let meme = memes[indexPath.item]
    cell.memeImageView.image = meme.memedImage
    return cell
}

2. 确保安全获取AppDelegate的数组

你的viewWillAppear逻辑是对的,但可以加安全判断避免空数组或nil导致的崩溃:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    memes = appDelegate.memes ?? []
}

同时修改numberOfItemsInSection方法,增加空值保护:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return memes?.count ?? 0
}

3. 实现保存新Meme时的实时更新

目前你的代码只有在标签页切换时才会刷新数据,想要在用户保存新Meme后立刻更新Collection View,有两种简单方案:

方案一:用NotificationCenter监听更新

在AppDelegate中,当新Meme被添加到数组时发送通知:

// 假设这是你保存Meme的方法
func saveMeme(_ newMeme: Meme) {
    memes.append(newMeme)
    NotificationCenter.default.post(name: NSNotification.Name("MemeAdded"), object: nil)
}

然后在CollectionViewController中监听这个通知:

override func viewDidLoad() {
    super.viewDidLoad()
    // 注册通知监听
    NotificationCenter.default.addObserver(self, selector: #selector(refreshMemes), name: NSNotification.Name("MemeAdded"), object: nil)
}

@objc private func refreshMemes() {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    memes = appDelegate.memes ?? []
}

// 记得在页面销毁时移除监听
deinit {
    NotificationCenter.default.removeObserver(self)
}

方案二:在模态返回时刷新

如果Meme生成器是通过present弹出的,可将刷新逻辑移到viewDidAppear(模态返回时viewWillAppear可能不会触发):

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    memes = appDelegate.memes ?? []
}

总结

先解决自定义Cell的问题,这是当前代码无法正常显示的核心原因;再添加空值保护避免崩溃;最后选择合适的方式实现实时更新。这样你的Collection View就能正确获取AppDelegate中的Meme数组,并在保存新Meme时及时展示了。

内容的提问来源于stack exchange,提问作者Andrew Tuzson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:51:52