Sang
Sang

Reputation: 1715

EXC_BAD_ACCESS in Custom UITableViewCell

I've been banging my head against a wall for the past day or so trying to figure out this problem, so I hope someone can help!

I'm just trying to create a custom subclass of a UITableViewCell, but my app keeps crashing with an EXC_BAD_ACCESS error in the init function of my custom TableViewCell. I'm on Xcode 7.01

DiscoverViewController.swift

import UIKit

class DiscoverViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let networkInterface: GfyNetwork = GfyNetwork()

    var gfyArray: Array<GfyModel> = []
    var tableView: UITableView = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.title = "Discover"

        let navbar = self.navigationController!.navigationBar
        navbar.tintColor = UIColor(red:0.32, green:0.28, blue:0.61, alpha:1.0)

        networkInterface.getTrendingGfys("", completionHandler: printGfys)

        tableView.frame         =   CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
        tableView.delegate      =   self
        tableView.dataSource    =   self
        tableView.separatorStyle = .None
        tableView.rowHeight     = 260
        tableView.contentInset  = UIEdgeInsetsMake(10, 0, 10, 0)
        tableView.registerClass(GfyTableViewCell.self, forCellReuseIdentifier: "gfycell")

        self.view.addSubview(tableView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func printGfys(gfyJSON: Array<GfyModel>) -> Array<GfyModel> {
        // Array of fetched gfys
        self.gfyArray = gfyJSON
        // Update Tableview
        dispatch_async(dispatch_get_main_queue()) {
            self.tableView.reloadData()
        }
        return gfyJSON
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCellWithIdentifier("gfycell", forIndexPath: indexPath) as? GfyTableViewCell else { fatalError("unexpected cell dequeued from tableView") }
        cell.gfy = self.gfyArray[indexPath.row]

        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You selected cell #\(indexPath.row)!")
    }
}

GfyTableViewCell.swift

import UIKit

class GfyTableViewCell: UITableViewCell {

    let padding: CGFloat = 5

    var gfy: GfyModel!

    var bgView: UIView!
    var imageURL: UIImageView!
    var title: UILabel!

    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
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    convenience override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        self.init(style: style, reuseIdentifier: reuseIdentifier) // Error happens here

        backgroundColor = UIColor.whiteColor()
        selectionStyle = .None

        bgView.frame = CGRectMake(8, 0, contentView.frame.width-16, 250)
        bgView.layer.cornerRadius = 3
        bgView.layer.borderColor = UIColor(red:0, green:0, blue:0, alpha:0.4).CGColor
        bgView.layer.borderWidth = 0.5
        bgView.clipsToBounds = true
        bgView.backgroundColor = UIColor.whiteColor()

        title.frame = CGRectMake(10, 210, bgView.frame.width-100, 10)
        title.text = gfy.title
        title.font = UIFont.systemFontOfSize(10)

        imageURL.frame = CGRectMake(0, 0, bgView.frame.width, 200)
        if let url = NSURL(string: gfy.thumbUrl) {
            if let data = NSData(contentsOfURL: url){
                imageURL.contentMode = UIViewContentMode.ScaleAspectFill
                imageURL.image = UIImage(data: data)
            }
        }

        contentView.addSubview(bgView)
        bgView.addSubview(imageURL)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
    }

}

Any help would be much appreciated. The app works when using standard UITableViewCells, but as soon as I try to add custom tableviewcells, it blows up :(

edit:

This is what my stack looks like. I'm pretty sure I'm doing something wrong in my override init() function in GfyTableViewCell.swift, but I don't know what that is:

call stack

Upvotes: 2

Views: 2456

Answers (3)

Sanju
Sanju

Reputation: 1168

Fix:For Custom TableviewCell in Xcode 7.1.1.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
   let cellT = cell as! CustomTableViewCellName
    //enter code here
}

Upvotes: 0

Sang
Sang

Reputation: 1715

Wow, as I expected, it was a simple error on my part.

Instead of calling:

convenience override init(style: UITableViewCellStyle, reuseIdentifier: String?) { ... }

It seems like I need to ditch the convenience and just call:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) { ... }

Then I can do as Anthony posted above and call super.init(style: style, reuseIdentifier: reuseIdentifier) without any errors.

Upvotes: 0

Anthony Mattox
Anthony Mattox

Reputation: 7118

The problem here is that the init method calls itself. Replace the following line:

    self.init(style: style, reuseIdentifier: reuseIdentifier)

with:

    super.init(style: style, reuseIdentifier: reuseIdentifier)

If you call a method within itself it will recursively call itself until the program eventually crashes because of a stack overflow or running out of memory. It's not obvious why this crashes with EXC_BAD_ACCESS, but it's possible this leads to one instance failing to actually be allocated.

Upvotes: 6

Related Questions