Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does adding a gesture recognizer to UITableViewCell subclass in Interface Builder crash the app?

I have a custom UITableViewCell subclass and I'm trying to add a pinch gesture recognizer using Interface Builder to one of the views. My app crashes with:

2016-09-11 17:37:22.425 MYAPPNAME[4619:1284144] *** Assertion failure in -[ULFeedView _dequeueReusableViewOfType:withIdentifier:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.12/UITableView.m:6539

I've tried different gesture recognizers (e.g. tap recognizers) and different subviews, but they all crash my app.

An interesting observation: It doesn't crash if I add the recognizer to a view programmatically at awakeFromNib.

Here is some methods that might be relevant:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    if(indexPath.section != SECTION_CONTENT){
        return; //index path section is NOT equal to SECTION CONTENT for the cell in question, so it will always return.
    }
    ...
 }

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    switch (indexPath.section) {
        case SECTION_MAP:
        {
            ULMapCell *cell = [tableView dequeueReusableCellWithIdentifier:@"map" forIndexPath:indexPath];
            return cell; //the cell in question is this one, so it will always return this cell.
        }
     ...
}

UPDATE: I have no problems with registering nibs. It was already working perfectly before the gesture recognizer. Please stop telling me how to register nibs for table view, I already know that as a senior iOS developer.

UPDATE 2: I confirm that it is occuring only when I add it through Interface Builder and there is no problem if I add it anywhere programmatically.

Why would this be happening?

like image 490
Can Poyrazoğlu Avatar asked Sep 11 '16 14:09

Can Poyrazoğlu


1 Answers

The objects in a nib are organised hierarchically. Often there is just one object at the top level: the root view (in your case that's the cell). However, nibs can contain multiple top-level objects. In fact, gesture recognizers are added to the nib as top-level objects.

Any code that loads a nib with multiple top-level objects needs to know how to deal with this. For example, the code loading the nib for a UITableViewCell could:

  1. find the cell object in the array of top-level-objects
  2. make sure there is no other cell (because it would be impractical to add a heuristic for which one to choose)
  3. ignore all top-level UIGestureRecognizers since they are retained by the views they have been added to
  4. make sure there is nothing else in the top-level objects array

Unfortunately, the way Apple chose to deal with multiple top-level objects when loading UITableViewCell and UICollectionViewCell nibs is to throw an exception. That's why we cannot add gesture recognisers to cells in Interface Builder.

like image 104
nils Avatar answered Nov 06 '22 13:11

nils