简体   繁体   中英

Terminating app due to 'NSInternalInconsistencyException' error

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert section 50 but there are only 1 sections after the update'

Hey everyone I have been stuck on this error all day. It crashes the app after the set Batch Load Limit of 50 cells. I believe I am populating the tableView incorrectly. Here is a snippet of the code directly working with sections in the table.

import UIKit import Firebase import Foundation

class NotificationViewController: GradientViewController {

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var GVX3: UIView!

var isVisible = false

var notifications: [GActionNotification] = []

//Pull to Refresh
lazy var refresher: UIRefreshControl = {
    let refreshControl = UIRefreshControl()
    refreshControl.tintColor = primaryColor
    refreshControl.addTarget(self, action: #selector(requestData), for: .valueChanged)
    return refreshControl
}()
//Pull to Refresh
@objc func requestData() {
    print("requesting data")
    let deadline = DispatchTime.now() + .milliseconds(856)
    DispatchQueue.main.asyncAfter(deadline: deadline) {
        self.refresher.endRefreshing()
    }
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    isVisible = true
    NotificationService.shared.setSeen(notifications: notifications)
    setNotificationsBadge()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    isVisible = false
}
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)


}
override func viewDidLoad() {
    super.viewDidLoad()
    configureTableView()



    tableView.clipsToBounds = true
    tableView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
    if #available(iOS 13.0, *) {
        tableView.backgroundColor = UIColor.systemBackground
    } else {
        // Fallback on earlier versions
        tableView.backgroundColor = UIColor.white
    }
    tableView.allowsSelection = false


    if #available(iOS 10.0, *) {
        tableView.refreshControl = refresher
    }else{
        tableView.addSubview(refresher)
    }



    self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]


    navigationController?.navigationBar.isTranslucent = true
    navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    navigationController?.navigationBar.shadowImage = UIImage()

    observeNotifications()
}

var loader: BatchCollectionLoader?

func requestMoreNotifications() {
    loader?.getNextSnapshot(completion: { [weak self] (snapshot) in
        NotificationService.shared.process(snapshot: snapshot, completion: { (notifications) in
            guard notifications.count > 0 else { return }
            guard let strongSelf = self else { return }

            var indexSet = IndexSet.init(integer: strongSelf.notifications.count)

            if notifications.count > 1 {
                let range = (strongSelf.notifications.count...(strongSelf.notifications.count + notifications.count - 1))
                indexSet = IndexSet.init(integersIn: range)
            }

            let shouldUpdate = strongSelf.notifications.count == 0

            strongSelf.notifications.append(contentsOf: notifications)

            if shouldUpdate {
                strongSelf.tableView.reloadData()
            } else {
                strongSelf.tableView.beginUpdates()
                strongSelf.tableView.insertSections(indexSet, with: .bottom)
                strongSelf.tableView.endUpdates()
            }

        })
    })
}

func observeNotifications() {
    guard let current = GUser.current else { return }
    loader = BatchCollectionLoader.init(collection: NotificationService.shared.notificationReference.document(current.uid).collection("notifications"))
    loader?.getNextSnapshot(completion: { [weak self] (snapshot) in
        NotificationService.shared.process(snapshot: snapshot, completion: { (notifications) in
            guard let strongSelf = self else { return }
            strongSelf.notifications = notifications.sorted(by: {$0.time > $1.time})
            DispatchQueue.main.async {
                strongSelf.tableView.reloadData()
            }
            if strongSelf.isVisible && isInForeground {
                NotificationService.shared.setSeen(notifications: notifications)
            }
            strongSelf.setNotificationsBadge()
        })
    })
}

func setNotificationsBadge() {
    UIApplication.shared.applicationIconBadgeNumber = notifications.filter({!$0.isSeen}).count
    if notifications.filter({!$0.isSeen}).count > 0 {
        self.tabBarController?.tabBar.items?[2].badgeValue = "\(notifications.filter({!$0.isSeen}).count)"
    } else {
        self.tabBarController?.tabBar.items?[2].badgeValue = nil
    }
}

func configureTableView() {
    tableView.register(UINib.init(nibName: LaunchNotificationCell.identifier, bundle: nil), forCellReuseIdentifier: LaunchNotificationCell.identifier)
    tableView.register(UINib.init(nibName: GNotificationCell.identifier, bundle: nil), forCellReuseIdentifier: GNotificationCell.identifier)
    tableView.rowHeight = 70
    tableView.delegate = self
    tableView.dataSource = self
}

}

extension NotificationViewController: UITableViewDelegate, UITableViewDataSource {

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return notifications.count > 0 ? notifications.count : 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if notifications.count == 0 {
        if let cell = tableView.dequeueReusableCell(withIdentifier: LaunchNotificationCell.identifier, for: indexPath) as? LaunchNotificationCell {
            return cell
        }
    }

    if let cell = tableView.dequeueReusableCell(withIdentifier: GNotificationCell.identifier, for: indexPath) as? GNotificationCell {
        cell.configure(notification: notifications[indexPath.row])

        cell.authorProfileTapped = { [weak self] uid in
            guard let strongSelf = self else { return }
            strongSelf.openProfile(id: uid)
        }
        cell.postTapped = { [weak self] postUid in
            guard let strongSelf = self else { return }

            let notification = strongSelf.notifications[indexPath.row]

            if notification.action == .friendRequest {
                strongSelf.openProfile(id: notification.user)
            } else {
                let alert = UIAlertController(title: nil, message: "Loading post...", preferredStyle: .alert)

                let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
                loadingIndicator.hidesWhenStopped = true
                loadingIndicator.style = UIActivityIndicatorView.Style.gray
                loadingIndicator.startAnimating();

                alert.view.addSubview(loadingIndicator)
                strongSelf.present(alert, animated: true, completion: nil)

                PostService.shared.getPost(id: postUid, location: nil, completion: {post, err in
                    alert.dismiss(animated: true, completion: nil)

                    if let post = post {
                        guard let commentsVC = strongSelf.storyboard?.instantiateViewController(withIdentifier: "CommentsViewController") as? CommentsViewController else {return}

                        commentsVC.post = post
                        strongSelf.navigationController?.pushViewController(commentsVC, animated: true)
                    }
                })
            }
        }

        return cell
    }
    return UITableViewCell()
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if notifications.count == 0 {
        return view.frame.height
    }
    return 70
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if indexPath.section == tableView.numberOfSections - 1 &&
        indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
        requestMoreNotifications()
    }
}

}

extension NotificationViewController: GPostHelperProtocol {} extension NotificationViewController: ProfileHelperProtocol {}

Probably it was intended the following, but it would be better to describe what is supposed to be shown when there are notifications and not.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if notifications.count != 0 { // << here !!
        if let cell = tableView.dequeueReusableCell(withIdentifier: LaunchNotificationCell.identifier, for: indexPath) as? LaunchNotificationCell {
            return cell
        }
    }
    return UITableViewCell() // << default ??

You are trying to insert 50 sections instead of 50 rows but your numberOfSections method claims there is only one section. That's why an exception is being thrown. Make sure you are inserting rows, not sections.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM