How to Resolve Terminating with Uncaught Exception of Type NSException

Asked 2 years ago, Updated 2 years ago, 40 views

I am creating an application using collectionView.
I would like to implement the function of removing long pressed cells when I press and hold cells, but when I press and hold cells for a long time, libc++abi.dylib:terminating with uncaught exception of type NSException appears in the debug area.
When I looked into it, it looked like a connection problem, so I tried to reconnect the outlet connection in the collectionView, but it didn't work.
Is there something wrong with the code?
I would appreciate it if you could let me know.Thank you for your cooperation.

import UIKit

classViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UIGestureRecognizerDelegate{

    @IBOutlet weak var collectionView—UICollectionView!

    functioncollectionView(_collectionView:UICollectionView, cellForItemAtindexPath:IndexPath)->UICollectionViewCell{
        letcell:UICollectionViewCell=collectionView.dequeueReusableCell(withReuseIdentifier: "coinCell", for:indexPath)
        cell.backgroundColor=.init(red:CGFloat(drand48())), green:CGFloat(drand48())), blue:CGFloat(drand48()) , alpha:0.6)

        return cell
    }

    override func viewDidLoad(){
        super.viewDidLoad()

        _=UINib(nibName: "UICollectionElementKindCell", bundle:nil)

        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets (top:20, left:20, bottom:20, right:20)
        layout.itemSize = CGSize (width: 100, height: 100)
        collectionView.collectionViewLayout=layout

        let longPressGestureRecognizer = UILongPressGestureRecognizer(target:self, action:Selector(("cellLongPressed"))))
        longPressGestureRecognizer.delegate=self
        longPressGestureRecognizer.allowableMovement=15
        longPressGestureRecognizer.minimumPressDuration=0.6
        collectionView.addGestureRecognizer (longPressGestureRecognizer)
    }

    func numberOfSections (incollectionView:UICollectionView) - > Int {
        return1
    }

    functioncollectionView(_collectionView:UICollectionView, numberOfItemsInSection section:Int) - > Int {
        return365
    }

    functioncollectionView(_collectionView:UICollectionView, layoutCollectionViewLayout:UICollectionViewLayout, insertForSectionAtsection:Int)->UIEdgeInsets{
        return UIEdgeInsets (top:0, left:0, bottom:0, right:0)
    }

    functioncollectionView(_collectionView:UICollectionView, layoutCollectionViewLayout:UICollectionViewLayout,sizeForItemAtindexPath) ->CGSize{
        lethorizontalSpace —CGFloat=500
        let cellSize —CGFloat=self.view.bounds.width/5-horizontalSpace
        return CGSize (width:cellSize, height:cellSize)
        // gyou saishou yohaku
    }

    override funcdidReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
    }

    funcellLongPressPressed(sender:UILongPressGestureRecognizer) {
        letpoint —CGPoint=sender.location(in:collectionView)
        let indexPath=collectionView.indexPathForItem(at:point)

        if sender.state == UIGestureRecognizer.State.began {
            collectionView.deleteItems(at:[indexPath!])
            print("longPressed")
        }
    }

}

swift ios xcode

2022-09-30 11:34

1 Answers

Didn't you see more messages on the debug console besides the ones listed in the title when you pressed long on the cell?

It's been a little longer, but even if you solve the error in the title, the next one will be, so please read it carefully until the end.

I ran your code on the actual machine at hand and pressed it for a long time to see this message.(By the way, the simulator showed almost the same message.)

2019-07-1001:58:03.642096+0900 AppName [11357:2184859] - [AppName.ViewController cellLongPressed]—unrecognized selector sent to instance 0x10140e6c0
2019-07-1001:58:03.643874 +0900 AppName [11357:2184859] ***Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [AppName.ViewController cellLongPressed]: unrecognized selector sent to instance 0x10140ec0'c0
*** First throw call stack:
(0x18796527c 0x186b3f9f80x187881ab80x1b42caf600x18796 aac40x18796c75c 0x1b3ec88680x1b3ed0a700x1b3ece4140x1b3ec1c0x1b3ec1a1c 0x1878f65f1300x1878f189c0179c0x1709f0x189f0249f0179f0x1709f0x189f0x189f0179f0
libc++abi.dylib:terminating with uncaught exception of type NSException
(lldb)

This output contains very important information.If the application terminates abnormally during the test, please be careful to check all the messages that appear when you perform the cause operation.Also, if you are not able to solve the problem yourself, please include all the messages in the body of the question.

This time, we found suspicious parts everywhere, and it was always a reproduction error, so we knew the cause right away, but it is often difficult to solve without these messages.

The most important thing is here.

 - AppName.ViewController cellLongPressed—Unrecognized selector sent to instance

An unrecognized selector was sent to the instance.(Class is app ViewController class, selector is cellLongPressed)

In other words, your ViewController doesn't have a cellLongPressed method (from an Objective-C point of view), which results in runtime errors.This can be caused by "connection problems", but this is only one of many possible causes. Have you searched the unrecognized selector sent to instance section? Let's look it up.

The worst part is this line.

let longPressGestureRecognizer=UILongPressGestureRecognizer(target:self, action:Selector(("cellLongPressed"))

In Swift, remember that the syntax Selector(("character constant") should not be used.

If you look at the Swift code from ancient times, Xcode sometimes recommends this way of writing, but please don't swallow it.Let's not look at such ancient codes.

The method declared in the header funccellLongPressPressed(sender:UILongPressGestureRecognizer) is the Selector cellLongPressWithSender: for Objective-C.The last colon is also required for some method names.

There is a syntax that converts "Swift Method Name" to "Objective-C Selector" because this conversion is not normally possible for people who do not know Objective-C from Swift.

Please rewrite the previous line as follows:

let longPressGestureRecognizer=UILongPressGestureRecognizer (target:self, action:#selector(cellLongPressed))

The #selector(cellLongPressed) part can be written in various ways, such as #selector(cellLongPressed(sender:)), #selector(ViewController.cellLongPressed), or #selector(self.cellLongPressed).

The #selector syntax allows Swift to perform a confusing conversion to an Objective-C selector, and if you do not have such a method, she will display a error when compiling.

In , when you rewrite above, an error message similar to this appears along with the Fix It Suggestion.

Argument of '#selector' references to instance method' cellLongPressed (sender:) 'that is not exposed to Objective-C

Add'@objc' to export this instance method to Objective-C

Please follow the Xcode recommendations here.

@objc is added to the previous method header.

@objc funccellLongPressed (sender: UILongPressGestureRecognizer) {

Here it is.

@objc funccellLongPressed (sender: UILongPressGestureRecognizer) {
        letpoint —CGPoint=sender.location(in:collectionView)
        let indexPath=collectionView.indexPathForItem(at:point)
        if sender.state == UIGestureRecognizer.State.began {

            collectionView.deleteItems(at:[indexPath!])//<-
            print("longPressed")

        }
    }

In your code, collectionView calls deleteItems(at:) to tell collectionView(_:numberOfItemsInSection:), but collectionView(_:numberOfItemsInSection:) keeps returning 365.

Therefore, iOS reports runtime errors such as NSInternalInconsistencyException in the sense of "I deleted it, but it's not decreasing!"

If you call deleteItems(at:), you will need to comment out collectionView(_:numberOfItemsInSection:) until you also reduce the number of collectionView.deleteItems(at:[indexPath!].

What is this line for?

_=UINib(nibName: "UICollectionElementKindCell", bundle:nil)

Without it, if it doesn't work, there are other parts that are not well organized.It would be better to delete it and correct the "other part".Of course, if it doesn't matter if you delete it, just delete it.

How to find random numbers on the latest Swift

This line:

cell.backgroundColor=.init(red:CGFloat(drand48())), green:CGFloat(drand48()) , blue:CGFloat(drand48()) , alpha:0.6)

is rewritten like this with the current Swift.

cell.backgroundColor=.init(red:CGFloat.random(in:0...1), green:CGFloat.random(in:0...1), blue:CGFloat.random(in:0...1), alpha:0.6)

Although it is longer in terms of number of characters, drand() eliminates the need to use functions for the C language that you do not understand.

(cell.backgroundColor=.init(red:.random(in:0...1), green:.random(in:0...1), blue:.random(in:0...1), alpha:0.6) can be written.)

However, if you use random numbers every time in collectionView(_:cellForItemAt:), the color will change randomly when scrolling or when you delete and redraw cells.

For example,
Prepare an instance variable representing the color of the cell and

 var colorArray: [UIColor] = [ ]

Initialize it in viewDidLoad().

override func viewDidLoad(){
        super.viewDidLoad()

        //...

        for_in0..<365{
            colorArray.append(UIColor(red:CGFloat.random(in:0...1), green:CGFloat.random(in:0...1), blue:CGFloat.random(in:0...1), alpha:0.6))
        }
    }

This is how the collectionView(_:numberOfItemsInSection:) is rewritten.

func collectionView(_collectionView:UICollectionView, cellForItemAtindexPath:IndexPath) ->UICollectionViewCell{

        letcell=collectionView.dueReusableCell(withReuseIdentifier: "coinCell", for:indexPath)

        cell.backgroundColor=colorArray [indexPath.item]//<-

        return cell
    }

Further

 func collectionView(_collectionView:UICollectionView, numberOfItemsInSection section:Int) - > Int {
        return colorArray.count//<-
    }

    //...

    @objc funccellLongPressed (sender: UILongPressGestureRecognizer) {
        letpoint —CGPoint=sender.location(in:collectionView)
        let indexPath=collectionView.indexPathForItem(at:point)
        if sender.state == UIGestureRecognizer.State.began {

            colorArray.remove(at:indexPath!.item)//<-
            collectionView.deleteItems(at:[indexPath!])
            print("longPressed")

        }
    }

Then, deleteItems(at:) and the rest will be consistent, so you will be able to make sure that delete with long press

works.


2022-09-30 11:34

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.