2016-09-12 35 views
1

我在Crashlytics上發生了奇怪的崩潰,它在代碼中評論到該行顯示崩潰。在Crashlytics的tableView中碰到cellForRowAtIndexPath

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    if indexPath.row >= collectionArrayApiObject.collectionsArray.count { 
     return UITableViewCell(frame: CGRectZero) 
    } 

    var tableViewCell:CollectionsTableViewCell? = tableView.dequeueReusableCellWithIdentifier("collectionsCell") as? CollectionsTableViewCell 
    if (tableViewCell == nil) { 
     tableViewCell = CollectionsTableViewCell(style: .Default, reuseIdentifier: "collectionsCell") 
    } 
    // Got crash in below line 
    let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row] 
    tableViewCell!.setCollection(collectionObject) 

    return tableViewCell! 
} 

這是我得到的堆棧跟蹤..

Stack Traces

,但沒有得到爲什麼這甚至發生了什麼?我已經把檢查,

index.row >= collectionArrayApiObject.collectionsArray.count 

所以它不應該索引超出範圍的情況。任何人都可以給我一個這種情況發生的案例嗎?

注意:這發生在只有一個用戶,直到現在,但仍然爲什麼這甚至發生?

全表視圖控制器:

import UIKit 

class CollectionsViewController: CUIBaseViewController, CollectionArrayApiObjectDelegate, UITableViewDataSource, UITableViewDelegate, UIViewControllerPreviewingDelegate { 
var collectionsTableView : UITableView? 
var collectionArrayApiObject : CollectionArrayApiObject = CollectionArrayApiObject() 
var headerSearchButton : UIBarButtonItem? 
var cityId: String? 

required init?(coder aDecoder: NSCoder) { 
    fatalError("NSCoding not supported") 
} 

override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) { 
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 
} 

convenience init(CityId: String? = nil) { 
    self.init(nibName: nil, bundle: nil) 
    self.cityId = CityId 
    self.view.backgroundColor = Colors.white() 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    // Do any additional setup after loading the view. 
    self.setUpHeaderView() 
    self.createTableView() 
    self.getData() 
    self.listenToNotifications() 
    self.automaticallyAdjustsScrollViewInsets = false 
    if #available(iOS 9.0, *) { 
     registerForPreviewingWithDelegate(self, sourceView: collectionsTableView!) 
    } 
} 

override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 
    self.navigationController?.setNavigationBarHidden(false, animated: animated) 
} 

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 
} 

func listenToNotifications() { 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CollectionsViewController.cityChanged), name: Constants.NOTIFIICATION_LOCATION_CHANGED_CITY, object: nil) 
} 

func cityChanged() { 
    self.getData() 
} 

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    collectionsTableView?.frame = CGRectMake(0, Constants.NAV_BAR_HEIGHT, self.view.width, self.view.height - Constants.NAV_BAR_HEIGHT) 
} 

//MARK: view creation functions 
func setUpHeaderView() { 
    self.navigationItem.title = "Collections" 

    let negativeSpacer = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil) 
    negativeSpacer.width = 0; 

    headerSearchButton = UIBarButtonItem.init(title: "n", style: .Plain, target: self, action: #selector(CollectionsViewController.headerSearchButtonTapped)) 
    headerSearchButton?.width = 40 
    headerSearchButton?.setTitleTextAttributes([NSFontAttributeName: Fonts.iconFont(18), NSForegroundColorAttributeName: Colors.gray()], forState: .Normal) 

    self.navigationItem.rightBarButtonItems = [negativeSpacer, headerSearchButton!]; 
} 

func createTableView() { 
    collectionsTableView = UITableView(frame: CGRectZero, style: .Plain) 
    collectionsTableView?.separatorStyle = .None 
    collectionsTableView?.backgroundColor = Colors.white() 
    collectionsTableView?.dataSource = self 
    collectionsTableView?.delegate = self 
    self.view.addSubview(collectionsTableView!) 
} 

//MARK : tableview delegate methods 
func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return 1; 
} 

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

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    return CollectionsTableViewCell.getHeight() 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    if indexPath.row >= collectionArrayApiObject.collectionsArray.count { 
     return UITableViewCell(frame: CGRectZero) 
    } 

    var tableViewCell:CollectionsTableViewCell? = tableView.dequeueReusableCellWithIdentifier("collectionsCell") as? CollectionsTableViewCell 
    if (tableViewCell == nil) { 
     tableViewCell = CollectionsTableViewCell(style: .Default, reuseIdentifier: "collectionsCell") 
    } 

    let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row] 
    tableViewCell!.setCollection(collectionObject) 

    return tableViewCell! 
} 

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    Commons.trackEvent(Commons.createGAcategory([Constants.COLLECTIONS_PAGE, "collection"]), action: "click", label: nil, value: 1) 

    let exploreFeedForCollection = ExploreFeedViewController.init(collection: collectionArrayApiObject.collectionsArray[indexPath.row]) 

    //self.presentViewController(CUINavigationController.init(rootViewController: exploreFeedForCollection), animated: true, completion: nil) 
    self.navigationController?.pushViewController(exploreFeedForCollection, animated: true) 
} 

func scrollViewDidScroll(scrollView: UIScrollView) { 
    let contentOffset = scrollView.contentOffset.y 
    if (collectionsTableView != nil) { 
     for cell in collectionsTableView!.visibleCells { 
      if (cell.isKindOfClass(CollectionsTableViewCell.self)) { 
       let cellOffset = cell.y - contentOffset; 

       //image parallax 
       let parallaxCut: CGFloat = 0.5 
       let percent = (cellOffset + cell.height)/(collectionsTableView!.height + cell.height); 
       let extraHeight = cell.height * (CollectionsTableViewCell.parallaxRatio-1.0) * parallaxCut; 
       let collectionCell = cell as! CollectionsTableViewCell;      
       collectionCell.bgImageView.y = -extraHeight*percent; 
      } 
     } 
    } 

} 

//MARK : get cities data functions 
func getData() { 
    collectionArrayApiObject = CollectionArrayApiObject() 
    collectionArrayApiObject.fetchCollections(Delegate: self, CityId: self.cityId) 

    if collectionArrayApiObject.collectionsArray.count == 0 { 
     self.showLoader("Hmm, things are getting interesting") 
    } 
} 

func collectionsFetchedSuccessfully() { 
    self.hideNothingHereViewAndLoader() 
    self.collectionsTableView?.reloadData() 
    self.scrollViewDidScroll(self.collectionsTableView!) 
} 

func collectionsFetchingFailed(errorType: ErrorType) { 
    self.showNothingHereView(errorType, icon: nil, showTryAgain: true) 
} 

override func didTapReloadButton() { 
    self.getData() 
} 

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

//MARK: UIViewControllerPreviewingDelegate 
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { 
    guard let indexPath = collectionsTableView?.indexPathForRowAtPoint(location) else{ 
     return nil 
    } 

    // Lifting cell up on 3D touch before peeking 
    if #available(iOS 9.0, *) { 
     let cellRect = collectionsTableView?.rectForRowAtIndexPath(indexPath) 
     let sourceRect = previewingContext.sourceView.convertRect(cellRect!, fromView: collectionsTableView) 
     previewingContext.sourceRect = sourceRect 
    } 

    return ExploreFeedViewController.init(collection: collectionArrayApiObject.collectionsArray[(indexPath as NSIndexPath).row]) 
} 

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { 
    self.navigationController?.pushViewController(viewControllerToCommit, animated: true) 
} 

//MARK : header button functions 
func headerSearchButtonTapped() { 
    let searchVC = SearchViewController(CityId: cityId) 
    self.navigationController?.pushViewController(searchVC, animated: true) 
} 

deinit { 
    NSNotificationCenter.defaultCenter().removeObserver(self) 
} 

}

回答

0

一些觀察:

首先

不要使用此if聲明:

if indexPath.row >= collectionArrayApiObject.collectionsArray.count { 
    return UITableViewCell(frame: CGRectZero) 
} 

您應該使用numberOfRowsInSection要做到這一點,就像這樣:

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

在你cellForRowAtindexPath你只需要出列的單元格,比其設置爲你所需要的,像這:

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

       //swift 3.0 
       let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CollectionsTableViewCell 
       //swift 2.2 
       let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CollectionsTableViewCell 

       let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row] 
       cell.setCollection(collectionObject) 
       return cell 
      } 

有沒有必要測試,如果你使用dequeueReusableCellWithIdentifier:forIndexPath:)根據文檔總是返回一個有效的單元格

+0

第一件事已經在代碼中,但很久以前我們得到崩潰說列表索引超出範圍,不知道爲什麼但上面如果條件解決問題當時。其次..檢查單元是否不爲零是必需的,因爲tableView.dequeueReusableCellWithIdentifier(「collectionsCell」)如果根本沒有創建,可以爲零。第三..在你的解決方案中,你只是想說刪除安全檢查,但是將不會解決當前索引超出範圍崩潰..請注意堆棧跟蹤.. CollectionsViewController.scrollViewDidScroll(UIScrollView) - >()試圖調用tableView函數。 –

+0

看起來你的問題不在於tableView。可能在提供你的數據的api中。如果可能的話,嘗試使用dequeueReusableCellWithIdentifier:forIndexPath :)而不是dequeueReusableCellWithIdentifier(「collectionsCell」)它將保證返回一個有效的單元格,並且您不需要cellForRowAtindexPath中的驗證。 – Sebastian

+0

Nope ..它現在在模擬器上更頻繁地崩潰,給出下面的堆棧跟蹤..斷言在 - [UITableView dequeueReusableCellWithIdentifier:forIndexPath:],/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit- 3512.60.7/UITableView的。m:6573 0 CoreFoundation 0x000000011043fd85 __exceptionPreprocess + 165 但最初一切工作正常,我無法重現我在crashlytics得到的問題..但我同意你的觀點,問題可能出現在api調用和加載數據。但不知道爲什麼以及如何解決? –

相關問題