IOS app crashing with EXC_BAD_ACCESS (code = 1, address = 0x0)
I have a problem with some code that I cannot understand. When I start my application, sometimes it loads my cell, sometimes it fires immediately. I believe my problem is related to mine cellForRowInIndexPath
.
My error is on the line cellForRowInIndexPath
:
cellDrawer.insertDescriptionLabel(cell, text: offer.title)
That's my fault:
Thread 1: EXC_BAD_ACCESS(code=1,address=0x0)
This is my code:
import UIKit
class ProdutsViewController: UIViewController, UITableViewDelegate,UITableViewDataSource,UISearchResultsUpdating{
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var tableViewFooter: MyFooter!
var searchResults:[Offer] = []
var resultSearchController = UISearchController()
var loading = false
lazy var offers:[Offer]? = {
print("lazy of offers\n")
var restConnection = RestFulConnection()
restConnection.fetchDataFromServer()
return DataBaseChecker.getDataFromDatabase()
}()
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad\n")
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
// Reload the table
self.tableView.reloadData()
self.tableViewFooter.hidden = true
loadSegment()
}
class MyDataProvider {
class func getInstance() -> MyDataProvider {
print("getInstance of MyDataProvider\n")
return MyDataProvider() //return a new instance since class vars not supported yet
}
func requestData(listener:([Offer]) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
//simulate delay
sleep(1)
print("requestData of MyDataProvider\n")
//generate items
var restConnection = RestFulConnection()
restConnection.fetchDataFromServer()
var arr = DataBaseChecker.getDataFromDatabase()
//call listener in main thread
dispatch_async(dispatch_get_main_queue()) {
listener(arr)
}
}
}
}
func scrollViewDidScroll(scrollView: UIScrollView) {
print("scrollViewDidScroll\n")
let currentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if (maximumOffset - currentOffset) <= 40 {
print("IF of scrollViewDidScroll\n")
loadSegment()
}
}
func loadSegment() {
print("loadSegment\n")
if (!self.loading) {
self.setLoadingState(true)
print("IF of loadSegment\n")
MyDataProvider.getInstance().requestData(
{(offers:[Offer]) -> () in
print("block of requestData on method loadSegment\n")
for offer:Offer in offers {
print("for of loadSegment\n")
if(DataBaseChecker.isItNew(offer)){
self.offers?.append(offer)
}
}
self.tableView.reloadData()
self.setLoadingState(false)
})
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
print("didReceiveMemoryWarning\n")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell",forIndexPath: indexPath) as! UITableViewCell
print("CellForRowAtIndexPath\n")
// var offer:Offer?
// if (self.resultSearchController.active) {
// offer = searchResults[indexPath.row]
// } else {
// offer = offers?[indexPath.row]
// }
if(offers != nil){
var offer:Offer = offers![indexPath.row]
print("IF of offers not nil, offers = \(offer.title)\n")
var cellDrawer = CellDrawer()
if (cell.viewWithTag(1) == nil){
cellDrawer.createWhiteContentInCell(cell)
}
cellDrawer.insertImageInCell(offer.images, cell: cell)
cellDrawer.insertBlackContentInCell(cell)
cellDrawer.insertDescriptionLabel(cell, text: offer.title)
cellDrawer.insertLocalLabel(cell, text: "String Sample")
cellDrawer.insertOldPriceLabel(cell, number: offer.oldPrice)
//cellDrawer.insertFromPriceLabel(cell, text: "a partir de")
cellDrawer.insertNewPriceLabel(cell,number:offer.newPrice)
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("NumberOfRowsInSection\n")
if(offers != nil){
print("IF offers not nil of NumberOfRowsInSection\n")
if (self.resultSearchController.active) {
print("IF2 of NumberOfRowsInSection\n")
return searchResults.count
} else {
print("ELSE of NumberOfRowsInSection, offers count = \(offers!.count)\n")
return offers!.count
}
}
return 0
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
print("numberOfSectionsInTableView\n")
if(offers != nil && offers!.count >= 1){
print("if of numberOfSectionsInTableView\n")
return 1
}
return 0
}
func setLoadingState(loading:Bool) {
print("setLoadingState\n")
self.loading = loading
self.tableViewFooter.hidden = !loading
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
print("heightForRowAtIndexPath\n")
return 235
}
func updateSearchResultsForSearchController(searchController: UISearchController)
{
print("updateSearchResultsForSearchController\n")
if(offers != nil){
print("if of updateSearchResultsForSearchController")
searchResults.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "title CONTAINS[c] %@", searchController.searchBar.text)
let array = NSArray(array: offers!)
array.filteredArrayUsingPredicate(searchPredicate)
self.searchResults = array as! [Offer]
self.tableView.reloadData()
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
print("prepareForSegue\n")
if segue.identifier == "detailsSegue" {
print("IF of prepareForSegue\n")
let DetailTVC = segue.destinationViewController as! DetailsTVC
if sender as! UITableView == self.resultSearchController.active {
print("IF2 of prepareForSegue\n")
let indexPath = self.tableView.indexPathForSelectedRow()!
let offer = self.searchResults[indexPath.row]
DetailTVC.offer = offer
} else {
print("Else of prepareForSegue\n")
let indexPath = self.tableView.indexPathForSelectedRow()!
let offer = self.offers![indexPath.row]
DetailTVC.offer = offer
}
}
}
}
Hope someone can help.
If offer.title is nonzero, it is possible that the cellDrawer is doing something on the cell that is no longer valid.
Set a breakpoint and check the offer.title property using po (print object) in the debugger.
It can also be a race condition where the offer array is updated when the box tries to load the header.
It doesn't look like you are registering the class for a reuse id. Your viewDidLoad function should have:
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
In this case, I think the sentence itself is null and you get a crash when you try to get the title / ivar property.
I had a very similar problem with the same error. Finally, I based the error and it happened because @IBOutlet is a custom class (MyMapView class). When using custom classes in the user interface, you must specify the class in the Identity Inspector Interface Builder. He decided my case.