SWIFT:线程 1:致命错误:索引超出范围

时间:2021-03-01 08:14:16

标签: swift

过去 4 小时我一直在尝试解决此错误。它构建完美运行良好。但是当我在提要上向上滑动以重新加载时,它崩溃了。

它应该做的是,您拥有包含所有最新帖子的主页,然后向上滑动以重新加载该页面。向上滑动时,它会在顶部显示一个旋转轮,它会从提要中删除所有图像,并将新的和更新的图像带回来。 (这是一个非常糟糕的解释)。

感谢任何帮助。而且我提供了我的整个班级只是为了确保我不会错过我应该发送的任何代码。

这是我的 FeedController.swift 类

import Firebase

private let reuseIdentifier = "Cell"

class FeedController: UICollectionViewController  {
    
    // MARK: - Lifecycle
    
    private var posts = [Post]()
    var post: Post?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        fetchPosts()
    }
    
    //MARK: - Actions
    
    @objc func handleRefresh() {
        posts.removeAll()
        fetchPosts()
    }
    
    @objc func handleLogout() {
        do {
            try Auth.auth().signOut()
            let controller = LoginController()
            controller.delegate = self.tabBarController as? MainTabController
            let nav = UINavigationController(rootViewController: controller)
            nav.modalPresentationStyle = .fullScreen
            self.present(nav, animated: true, completion: nil)
        } catch {
            print("DEBUG: Failed to sign out")
        }
    }
    
    // MARK: - API
    
    func fetchPosts() {
        guard post == nil else { return }
        
        PostService.fetchPosts { posts in
            self.posts = posts
            self.collectionView.refreshControl?.endRefreshing()
            self.collectionView.reloadData()

        }
    }
    
    // MARK: - Helpers
    
    func configureUI() {
        collectionView.backgroundColor = .white
        
        collectionView.register(FeedCell.self, forCellWithReuseIdentifier: reuseIdentifier)
        
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout",
                                                           style: .plain,
                                                           target: self,
                                                           action: #selector(handleLogout))
        navigationItem.title = "Feed"
        
        let refresher = UIRefreshControl()
        refresher.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
        collectionView.refreshControl = refresher
    }
}

// MARK: - UIcollectionViewDataSource

extension FeedController {
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return post == nil ? posts.count : 1
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! FeedCell
        
        if let post = post {
            cell.viewModel = PostViewModel(post: post)
        } else {
            cell.viewModel = PostViewModel(post: posts[indexPath.row])
        }
        
        return cell
    }
}

// MARK: - UICollectionViewDelegateFlowLayout

extension FeedController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let width = view.frame.width
        var height = width + 8 + 40 + 8
        height += 50
        height += 60
        
        return CGSize(width: width, height: height)
    }
}


这是给我错误的行(刷新后)

cell.viewModel = PostViewModel(post: posts[indexPath.row])

2 个答案:

答案 0 :(得分:0)

Ans:当你没有得到任何数据时,显示虚拟数据或返回 0 个单元格。

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    if post.count == nil { return 0 } else { return post.count
}

问题:如果数据为 nil 时返回 1,这意味着编译器返回一个单元格。当该单元格的每个元素都绑定到数组中的特定值时。由于 post 数组为 nil,它返回范围异常的索引。

答案 1 :(得分:0)

覆盖 func collectionView(_collectionView:UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! FeedCell

if let post = post {
    cell.viewModel = PostViewModel(post: post)
} else {
    if posts.count != 0{
        cell.viewModel = PostViewModel(post: posts[indexPath.row])
    }
}
return cell

}