2017-04-25 1 views
0

내 사용자 지정 셀에 타이머가 있습니다. 카운트 다운이 0에 도달하면 위임 메서드를 호출하고 셀이 자동으로 삭제됩니다. 문제는 두 번째 셀이 0에 도달하면 내 응용 프로그램이 오류 fatal error: Index out of range과 충돌합니다. 내 사용자 지정 셀 I 설정에서치명적인 오류 : 두 번째 셀 삭제시 범위를 벗어나는 인덱스

내 데이터 : cellForRowAt 안에 내 ViewController 내가 설정 내 셀 데이터에서

protocol MyDelegateName { 
func removeOfferExpired(offerId: String, indexPath: IndexPath) 
} 

class MyCustomCell: UITableViewCell { 
    var offer:Offers? 
    var cellIndexPath:IndexPath? 
    var delegate:MyDelegateName? 


    func setupData(offer:Offers, indexPath:IndexPath){ 
    self.offer = offer 
    self.cellIndexPath = indexPath 
    //...other code not relevant 
    } 

//When the time reach zero I call the following method 

func updateTime() { 
    if timeLeft > 0 { 
     timeLeft = endTime.timeIntervalSinceNow 
     offerExpiresLabel.textColor = UIColor.white 
     offerExpiresLabel.text = timeLeft.hmmss 
    }else { 
     offerExpiresLabel.textColor = UIColor.red 
     offerExpiresLabel.text = "Offer Expired" 
     timer.invalidate() 
     self.delegate?.removeOfferExpired(offerId: (self.offer?.offer_id!)!, indexPath: self.cellIndexPath!) 
    } 
} 

: 다음

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let offer = offers[indexPath.row] 
    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! MyCustomCell 
    cell.setupData(offer: offer, indexPath: indexPath) 
    cell.delegate = self 
    return cell 
} 

func removeOfferExpired(offerId: String, indexPath: IndexPath) 안에 내가 사용하는 것을 시도했다 :

1. self.offers.remove(at: indexPath.row) 
    self.tableView.reloadData() 

2. self.offers.remove(at: indexPath.row) 
    self.tableView.deleteRows(at: [indexPath], with: .automatic) 
    self.tableView.reloadData() 

3. //and even try to "wrap" it inside begin/end updates 
    tableView.beginUpdates() 
    self.offers.remove(at: indexPath.row) 
    self.tableView.deleteRows(at: [indexPath], with: .automatic) 
    tableView.endUpdates() 

항상 두 번째 충돌합니다. 첫 번째 셀을 삭제 한 후 setupData의 셀에 할당 한 indexPath가 같지 않지만 나머지 셀의 indexPath를 업데이트하는 방법은 reloadData이라고 생각합니다.

+0

셀이 다시로드되면 타이머를 잊지 않았습니까? 셀 외부에서 타이머/제거 로직을 이동해야합니다. 예를 들어, 모델 개체를 만들고 목록을 포함하고 컨트롤러로 제거되는 항목을 위임하는 등의 작업을 수행해야합니다. – vojer

+0

@vojer 감사합니다. 그러나 충돌이 타이머와 관련이 없다고 생각하지 않습니다. – mat

+0

이전 타이머가 실행되면 델리게이트가 더 이상 화면에없는 셀에서 전화를받을 수 있습니다. – vojer

답변

2

주요 문제는 셀에 인덱스 경로를 지정하고 셀이 해당 인덱스 경로를 해당 대리인에게 전달한다는 사실입니다. 그러나 셀의 인덱스 경로가 안정적이지 않습니다. 다른 행이 추가, 제거 또는 이동되면 변경됩니다.

셀 프로토콜의 메서드는 인덱스 경로가 아닌 매개 변수로 자체 전달됩니다. 그런 다음 대리인은 테이블 뷰를 쿼리하여 셀의 최신 인덱스 경로를 찾고 해당 인덱스 경로를 기반으로 행 삭제를 수행 할 수 있습니다.

+0

그것을 얻었습니다! 나는 그것을 시도 할 것이다.10-15 개의 제안을 스크롤하고 셀을 볼 수 없으면 셀에 타이머가있는 것이 문제가 될 것이라고 생각합니까? 라벨에 정확한 카운트 다운이 표시됩니까? – mat

+1

커스텀 셀이'prepareForReuse' 메소드에서 타이머를 무효로하고'setupData' 메소드에서 자신을 올바르게 리셋하는 한, 당신은 괜찮을 것입니다. 적어도 작은 코드를 기반으로 셀에 타이머가있는 것이 적절한 접근 방법 인 것 같습니다. – rmaddy

+0

고마워요! 나는 그것을 즉시 시도 할 것이다. – mat

0

rmaddy가 말했듯이 내가하고있는 일은 완전히 잘못되었습니다. 이것은 그의 대답을 기반으로 한 것입니다 :

func updateTime() { 
    if timeLeft > 0 { 
     timeLeft = endTime.timeIntervalSinceNow 
     offerExpiresLabel.textColor = UIColor.white 
     offerExpiresLabel.text = timeLeft.hmmss 
    }else { 
     offerExpiresLabel.textColor = UIColor.red 
     offerExpiresLabel.text = "Offer Expired" 
     timer.invalidate() 
     // when the time reach zero I passed self to the delegate instead of the indexPath 
     self.delegate?.removeOfferExpired(offerId: (self.offer?.offer_id!)!, cell: self as UITableViewCell) 
    } 
} 

protocol MyDelegateName { 
    func removeOfferExpired(offerId: String, cell: UITableViewCell) // delegate method now passes the cell instead of the index 
} 

func removeOfferExpired(offerId: String, cell: UITableViewCell) { 
    // and then I get the index path from the cell 
    let indexPath = tableView.indexPath(for: cell) 
    self.offers.remove(at: (indexPath?.row)!) 
    self.tableView.deleteRows(at: [indexPath!], with: .automatic) 
} 
+0

귀하의 옵션 물 처리가 중단됩니다. 'removeOffsetExpired' 메소드에서'indexPath'가'nil' 인 것을 안전하게 처리해야합니다. 그리고 여러분의 코드에서'! '를 사용할 때마다 충돌이 일어나기를 기다리고 있습니다. – rmaddy

+0

당신 말이 맞아요. 나는 언팩을하기 전에 무언가가 없는지 보통 확인합니다. 나는 고칠 것이다. 고마워. – mat

관련 문제