9

There are a lot of question with the same title but somehow I felt that every case is different as my problem is still not resolved and I've no clue why and also there are not enough solutions for Swift. So here is my scenerio:

I've used CarbonKit to show 4 view controllers in a single view controller. The FourthViewController sends a get call using AlamoFire. It successfully loads the data and reload tableView. However when I drag this table view my app crashes and I get EXC_BREAKPOINT and sometimes EXC_BAD_ACCESS for the same thing.

Here is what I've tried:

  1. Upon searching I came to know about zombies. So I enabled it and when the app gives me EXC I get this:

-[CALayer removeAllAnimations]: message sent to deallocated instance

So as I checked there was no animation I might have been using in this class. But considering it's inside CarbonKit they might have something to do with it but I'm unable to figure it out.

  1. I run Product > Analyze from xCode and the most of the blue icons are on FBSDK which have nothing to do with this class so it was not useful to debug at all.

Here are the screenshots: EXC_BREAKPOINT and EXC_BAD_ACCESS and here is what Instruments 9.0 zombies message gave me: Zombie Message and More Detailed Zombie

I get this in console of xCode: enter image description here If you need more information I'll update my questions.

UPDATE
Here is my code when I'm getting the data from web using Alamofire. Now this call runs successfully and I can scroll down to view all the data that is loaded in the table. But when i scroll up then it crashes with the above errors.

let headers = [
            "security-token": "MY_SECURITY_CODE_HERE",
            "Content-Type": "application/x-www-form-urlencoded"
        ]

        let url = "URL_GOES_HERE"
        //print(url)
        Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON { response in

            if let result = response.result.value as? [String: AnyObject] {

                switch response.result {
                case .success:
                    if result["status"] as! Int == 0
                    {
                        self.clearAllNotice()
                        let alert = UIAlertController(title: "Error",
                                                      message: "\(result["msg"] ?? "Our Server is not responding at the moment. Try again later!" as AnyObject)",
                            preferredStyle: UIAlertControllerStyle.alert)

                        let cancelAction = UIAlertAction(title: "OK",
                                                         style: .cancel, handler: nil)

                        alert.addAction(cancelAction)
                        self.present(alert, animated: true)
                    }
                    else
                    {
                        self.clearAllNotice()

                        for docReviewDict in (result["data"] as! [AnyObject]) {

                            let docReview = DoctorReview(dict: docReviewDict as! [String : AnyObject])
                            self.mainDoctorReviewsArray.append(docReview)
                        }

                        self.tableView.reloadData()
                    }
                case .failure(let error):
                    self.clearAllNotice()
                    let alert = UIAlertController(title: "Something is wrong",
                                                  message: error.localizedDescription,
                                                  preferredStyle: UIAlertControllerStyle.alert)

                    let cancelAction = UIAlertAction(title: "OK",
                                                     style: .cancel, handler: nil)

                    alert.addAction(cancelAction)
                    self.present(alert, animated: true)
                }
            } else {
              print("Somethins is wrong with the URL")
            }
        }

Just in case here is the cell which is loaded in the tableview. enter image description here

Latest:

Based on the comment I've done this:

DispatchQueue.main.async {
                        self.tableView.reloadData()
                        }

but still the same result I'am getting

Thread 1: EXC_BAD_ACCESS (code=1, address=0xb4c4beb8)

on let cell = tableView.dequeueReusableCell(withIdentifier: "ReviewCell") as! ReviewsTableViewCell line when I drag down on table view.

IMPLEMENTATION OF CELL

The class name is ReviewsViewController which has a @IBOutlet fileprivate var tableView: UITableView!.

Then in viewDidLoad():

tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()

Then I've table view delegate and datasource:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mainDoctorReviewsArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "ReviewCell") as! ReviewsTableViewCell //WHEN THE APP IS CRASHED AS I DRAG THE TABLE VIEW IT CRASH ON THIS LINE. As this line is highlighted in red with message "Thread 1: EXC_BREAKPOINT (code=1, subcode=0x186ddd61c)"

        cell.userPhoto.layer.cornerRadius = cell.userPhoto.frame.width / 2;
        cell.userPhoto.layer.masksToBounds = true

        cell.userName.text = mainDoctorReviewsArray[indexPath.row].name

        cell.starRating.settings.fillMode = .precise

        if let rate = mainDoctorReviewsArray[indexPath.row].rating
        {
            cell.starRating.rating = Double(rate)!
        }
        else {
            cell.starRating.rating = 0
        }

        cell.desc.text = mainDoctorReviewsArray[indexPath.row].feedback
        cell.dateOfReview.text = mainDoctorReviewsArray[indexPath.row].dates
        cell.timeOfReview.text = mainDoctorReviewsArray[indexPath.row].times

        return cell
    }

and in the cell class there is just:

import UIKit
import Cosmos

class ReviewsTableViewCell: UITableViewCell {

    @IBOutlet var timeOfReview: UILabel!
    @IBOutlet var dateOfReview: UILabel!
    @IBOutlet var desc: UITextView!
    @IBOutlet var starRating: CosmosView!
    @IBOutlet var userName: UILabel!
    @IBOutlet var userPhoto: UIImageView!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

The screenshot of tableView is above in this question.

This is the parent class under which 4 ViewControllers loads: dropbox.com/s/d5sh4ej1ssv6873/… And this is the class which has the tableview is and on scroll it crashed the app: dropbox.com/s/3kiju9hn3uewzar/ReviewsViewController.swift?dl‌​=0

Chaudhry Talha
  • 7,231
  • 11
  • 67
  • 116

4 Answers4

0

As someone mentioned above it probably is related with working with ui objects not from main thread. If your using xCode 9 you should see as a runtime warning. (You can set checkmark in EditScheme->Diagnostics->MainThreadChecker->pause on issues).

Also you can override dealloc method of you ReviewsTableViewCell and add some logs\asserts to check if it's called from main thread.

Usually it happens if you pass your view\cell to some block, and you will have this crash on releasing this object when exiting from block.

livsik
  • 416
  • 3
  • 7
  • I got this: `Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState] PID: 11684, TID: 3261572, Thread name: com.google.Maps.LabelingBehavior, Queue name: com.apple.root.default-qos.overcommit` when it is on the first tab. – Chaudhry Talha Nov 15 '17 at 13:23
  • [UIApplication applicationState] is not the problem. – livsik Nov 16 '17 at 09:29
  • This is what I got when as I turned the pause on issues on. Other that that I get the issues mentioned in the question. – Chaudhry Talha Nov 16 '17 at 10:31
0

I'm gonna make some small suggestions to clean up your code. Not sure if it will solve the problem but it will help to ensure that your issue isn't based on something trivial.

  1. I'm not sure where you're calling it, but in the request load completion handler make sure to capture self weakly.

    Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON { [weak self] response in

    This way you're not forcing the object to stay alive until the loading finishes, which may cause it to load in the wrong place.

  2. Make sure that the completion block (mentioned above) is running on the main thread. You're making calls to UI, so just check it to be safe.

  3. Your IB outlets should be declared as @IBOutlet weak var foo: UIView? You might be causing yourself problems by strongly referencing the views.

  4. dequeueReusableCell(withReuseIdentifier:) can return nil. You should be using dequeueReusableCell(withReuseIdentifier:for:) - and don't forget to register the cell using register(_:forCellWithReuseIdentifier:) first.

Guy Kogus
  • 7,251
  • 1
  • 27
  • 32
  • Got the same error: `[CALayer removeAllAnimations]: message sent to deallocated instance 0x1c103e240` and `Thread 1: EXC_BREAKPOINT (code=1, subcode=0x186ddd61c)` on the line mentioned in the question. – Chaudhry Talha Nov 16 '17 at 10:57
0

Did you register the cell class type?

If not add in viewDidLoad:

self.tableView.register(ReviewsTableViewCell.self, forCellReuseIdentifier: "ReviewCell")

Next just dequeue it in cellForRow:

let cell = tableView.dequeueReusableCellFor(identifier: "ReviewCell", indexPath: indexPath) as! ReviewsTableViewCell

Check if the error is still happening

lopes710
  • 315
  • 1
  • 3
  • 19
0

In my case, this happened when I executed this (myView is a subview on a cell)

myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }

I don't find anything removing a layer from your code but if you did it outside of that, then I think that's the problem.

Manabu Nakazawa
  • 1,983
  • 22
  • 23