2

I have experienced this crash in cellForRowAt the line number Crashlytics pointed me to was:

cell.table = questionTable

the entire case around that line is:

case .mcq_single:
if let cell = tableView.dequeueReusableCell(withIdentifier: "IQ_MCQCell") as? IQ_MCQCell
{
       cell.table = questionTable;
       cell.delegate = self;
       cell.qID = answerIDs![indexPath.row];
       cell.selectionStyle = .none

       if questionNA[indexPath.row]
       {
           cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_selected"), for: .normal);
           cell.questionItem.isHidden = true;
       } else {
           cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_up"), for: .normal);
           cell.questionItem.isHidden = false;
       }

       let cell2 = cell.formatCell(with: item, for: cell, at: indexPath)
       textHeight[indexPath.row] = cell.questionText.numberOfVisibleLines
       return cell2;
}


Crashed: com.apple.main-thread
0  libswiftCore.dylib             0x10281a7e8 swift_unknownRetain + 8
1  AppName                        0x100f24b48 specialized InspectionItemVC.tableView(UITableView, cellForRowAt : IndexPath) -> UITableViewCell (InspectionItemVC.swift:887)
2  FlexConnect                    0x100f1f2b8 @objc InspectionItemVC.tableView(UITableView, cellForRowAt : IndexPath) -> UITableViewCell (InspectionItemVC.swift)
3  UIKit                          0x18f537ac4 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:]
4  UIKit                          0x18f538028 -[UITableView _createPreparedCellForGlobalRow:willDisplay:]
5  UIKit                          0x18f5168ac -[UITableView _updateVisibleCellsNow:isRecursive:]
6  UIKit                          0x18f2cd33c -[UITableView layoutSubviews]
7  UIKit                          0x18f1f9f00 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
8  QuartzCore                     0x189c89998 -[CALayer layoutSublayers]
9  QuartzCore                     0x189c8db20 CA::Layer::layout_if_needed(CA::Transaction*)
10 UIKit                          0x18f20eccc -[UIView(Hierarchy) layoutBelowIfNeeded]
11 UIKit                          0x18f2a46f4 -[UINavigationController _layoutViewController:]
12 UIKit                          0x18f2a1dc4 -[UINavigationController _layoutTopViewController]
13 UIKit                          0x18f2bac64 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
14 UIKit                          0x18f2ba908 -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:]
15 UIKit                          0x18f2ba4e0 -[UINavigationTransitionView _cleanupTransition]
16 UIKit                          0x18f234bb4 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
17 UIKit                          0x18f232cb8 +[UIViewAnimationState popAnimationState]
18 UIKit                          0x18f2adc48 -[UINavigationTransitionView transition:fromView:toView:]
19 UIKit                          0x18f2a3d24 -[UINavigationController _startTransition:fromViewController:toViewController:]
20 UIKit                          0x18f2a2e14 -[UINavigationController _startDeferredTransitionIfNeeded:]
21 UIKit                          0x18f2a2890 -[UINavigationController __viewWillLayoutSubviews]
22 UIKit                          0x18f2a2790 -[UILayoutContainerView layoutSubviews]
23 UIKit                          0x18f1f9f00 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
24 QuartzCore                     0x189c89998 -[CALayer layoutSublayers]
25 QuartzCore                     0x189c8db20 CA::Layer::layout_if_needed(CA::Transaction*)
26 QuartzCore                     0x189bfa36c CA::Context::commit_transaction(CA::Transaction*)
27 QuartzCore                     0x189c21b90 CA::Transaction::commit()
28 UIKit                          0x18f1ef5c8 _afterCACommitHandler
29 CoreFoundation                 0x185bededc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
30 CoreFoundation                 0x185beb894 __CFRunLoopDoObservers
31 CoreFoundation                 0x185bebe50 __CFRunLoopRun
32 CoreFoundation                 0x185b0be58 CFRunLoopRunSpecific
33 GraphicsServices               0x1879b8f84 GSEventRunModal
34 UIKit                          0x18f26067c UIApplicationMain
35 AppName                        0x100094590 main (AppDelegate.swift:23)
36 libdyld.dylib                  0x18562856c start

Update:

weak var delegate: inspQDelegate? 
// weak added here
var indexPath: IndexPath?
//var table   : UITableView?; table removed indexPath used instead.

inspQDelegate is defined like so:

public protocol inspQDelegate
{
    func setNA(at index: IndexPath);
    func setAnswer(at index: IndexPath, value: String);
    func setComment(at index: IndexPath, value: String);
    func scrollToMe(at index: IndexPath)
}

Update 2: When inspQdelegate was defined like so:

public protocol inspQDelegate: NSObjectProtocol
{
    func setNA(at index: IndexPath);
    func setAnswer(at index: IndexPath, value: String);
    func setComment(at index: IndexPath, value: String);
    func scrollToMe(at index: IndexPath)
}

I received a new crash on line cell.delegate = self below:

case .true_false:
     if let cell = tableView.dequeueReusableCell(withIdentifier: "IQ_FlipCell") as? IQ_FlipCell {
            cell.table = questionTable;
            cell.delegate = self;
            cell.qID = answerIDs![indexPath.row];
            cell.selectionStyle = .none

            if questionNA[indexPath.row]
            {
                cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_selected"), for: .normal);
                cell.questionItem.isHidden = true;
            } else {
                cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_up"), for: .normal);
                cell.questionItem.isHidden = false;
            }

            let cell2 = cell.formatCell(with: item, for: cell, at: indexPath, qtype: 0)
            textHeight[indexPath.row] = cell.questionText.numberOfVisibleLines
            return cell2;
     }

But when defined like:

public protocol inspQDelegate: class
{...}

I did not receive this new crash

Scriptable
  • 19,402
  • 5
  • 56
  • 72
user2363025
  • 6,365
  • 19
  • 48
  • 89

1 Answers1

1

It looks like you are creating a retain cycle between your tableView and it's cells. Cells are dequeued and reused often, so you shouldn't be using strong references. Your cell has a delegate which is set to the tableView anyway, so you shouldn't need to set cell.tableView, just use the delegate.

When declaring your delegate and tableView in the cell. (I would advise NOT to have the tableView property) make sure that you use a weak reference and this should solve your issue.

weak var delegate: MyTableViewDelegateProtoocol?
weak var tableView: UITableView?

Give it a try and let me know the outcome

Here is an article that helps explain retain cycles and memory management in Swift

UPDATE:

public protocol inspQDelegate: class
{
    func setNA(at index: IndexPath);
    func setAnswer(at index: IndexPath, value: String);
    func setComment(at index: IndexPath, value: String);
    func scrollToMe(at index: IndexPath)
}
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • Thanks for the answer. I will get rid of the tableview reference and instead pass in indexpath as the table property in the cell was just used for: delegate?.setNA(at: table!.indexPath(for: self)!); But I should also change my delegate to weak var? Should I be doing this in every cell's class that has a delegate? I will make the change but I wont know of the outcome straight away as this crash has only just came in after months of using the app i.e. I cannot reproduce it. Unless you can advise on how i might be able to reproduce? – user2363025 Feb 06 '18 at 08:30
  • yes, when you declare a variable like `var tableView` you are using a strong reference. in closures and for delegates its best to use a weak reference. you will notice that IBOutlets are all weak vars – Scriptable Feb 06 '18 at 08:34
  • Is it best practice for all properties in my tableview cell to be weak? or just delegates? – user2363025 Feb 06 '18 at 08:37
  • I've added a link above which would help explain. not all things should be weak. weak references could be lost and then you will get a nil value. If you aren't sure, use them for outlets, closures and delegates. – Scriptable Feb 06 '18 at 08:39
  • ok thanks, I'll change all delegate in all tableview cells to be weak vars and give the article a read! – user2363025 Feb 06 '18 at 08:40
  • When I changed my delegate to weak var I get an error: 'weak' may only be applied to class and class-bound protocol types not 'inspQDelegate' – user2363025 Feb 06 '18 at 08:53
  • update your question with your code, show your cell and inspQDelegate – Scriptable Feb 06 '18 at 08:54
  • I've updated the answer, just inherit class in your protocol. – Scriptable Feb 06 '18 at 09:02
  • thanks i had just found that answer myself. is there any advantage of inheriting from class rather than NSObjectProtocol? – user2363025 Feb 06 '18 at 09:04
  • not that I am aware of, i think it's pretty much the same thing – Scriptable Feb 06 '18 at 09:06
  • @pearl7721 I can't be sure if it solved the crash as it wasn't happening for me anytime I run the code myself through xCode. It happened with an external user and it's the first time it did happen so I'm not sure how I can reproduce? – user2363025 Feb 06 '18 at 09:19
  • @Scriptable.. something of note: i have multiple question types which each have their own associated tableViewCell class, but all implement this inspQDelegate protocol. When I inherited from NSObjectProtocol I received a crash when another cell was setting its delegate. I'll add this part to the question for clarity. But when I inherited from class in my inspQDelegate protocol, this crash did not happen – user2363025 Feb 06 '18 at 09:20
  • thanks for note, I don't fully understand the difference between using class/NSobject in this case but I will investigate it for clarification. – Scriptable Feb 06 '18 at 09:25
  • @Scriptable I'll mark this as accepted for now and if the problem re-occurs I'll get back here! – user2363025 Feb 06 '18 at 14:25