I have a problem in my code that I can't figure out. When I run my app, sometimes it loads my cell, sometimes it crashes immediately. I believe my problem is with my cellForRowInIndexPath.
My error is in the line of cellForRowInIndexPath:
cellDrawer.insertDescriptionLabel(cell, text: offer.title)
This is my error:
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 anyone may help.
If offer.title is not nil, then possibly the cellDrawer is executing something on a cell that is no longer valid.
Set a breakpoint and check the offer.title property using po (print object) in the debugger.
It could also be a race condition that the offer array is being updated while the drawer is trying to load the title.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With