2017-07-12 32 views
0

目前我的代碼是這樣的,當我在小區設置一個datepicker如何修改cellForRowAt斯威夫特之外的細胞

代碼A工作

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = Bundle.main.loadNibNamed("DailyTimesTableViewCell", owner: self, options: nil)?.first as! DailyTimesTableViewCell 
    cell.endTimeTapped = { (button) -> DailyTimesTableViewCell in 
     cell.datePicker.date = self.convertToDateObject(timeString: endTime as! String) 
    } 
    return cell 
} 

我想修改datePicker基於某些邏輯,因此當我嘗試下面的代碼B時,使用回調修改單元格中的datePicker setTimeInDatePicker似乎並不奏效。

請指教,我可能會出錯。

代碼B:不工作

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = Bundle.main.loadNibNamed("DailyTimesTableViewCell", owner: self, options: nil)?.first as! DailyTimesTableViewCell 
    cell.endTimeTapped = { (button) -> DailyTimesTableViewCell in 
    self.setTimeInDatePicker(time: endTime!, cell: cell){ modifiedCell in 
        return modifiedCell 
       } 
    } 
    return cell 
} 


func setTimeInDatePicker(time: String, cell: DailyTimesTableViewCell, completionHandler: @escaping(DailyTimesTableViewCell) -> DailyTimesTableViewCell) { 

    tableView.beginUpdates() 
    let row  = cell.tag 
    let rows = self.timesArray.count 

    if self.startTimeHighlighted{ 
     // Setting minimum startTime for datePicker 
     if row == 0{ // For first row 
      let minStartTimeString  = "0:05 am" 
      cell.datePicker.minimumDate = self.convertToDateObject(timeString: minStartTimeString) 
     } 
     else if row > 0 { // For remaining rows 
      let endTimeStringOfPreviousCell = self.timesArray[row - 1]["endTime"]! 
      let endTimeObjectOfPreviousCell = self.convertToDateObject(timeString: endTimeStringOfPreviousCell) 
      cell.datePicker.minimumDate  = endTimeObjectOfPreviousCell 
     } 

     // Setting maximum startTime for datepicker 
     let endTimeString   = self.timesArray[row]["endTime"]! 
     let endTimeObject   = self.convertToDateObject(timeString: endTimeString) 
     let maxStartTimeObject  = endTimeObject.addingTimeInterval(-5 * 60.0)   // removing 5mins 
     cell.datePicker.maximumDate = maxStartTimeObject 

     // Setting selected date in as startTime title 
     let dateString = self.convertDateToString(cell.datePicker.date) 
     cell.startTime.setTitle(dateString, for: .normal) 

     // Saving updated date to the timesArray 
     self.timesArray[row]["startTime"] = dateString 
     //print("endTime in DatePickerChanged: \(self.timesArray[row]["endTime"])") 
     print("timesArray when startTimeHighlighted: \(self.timesArray)") 
     completionHandler(cell) 

    } 
    else if self.endTimeHighlighted{ 
     print("datePicker changed 3") 
     // Setting minimum endTime for datePicker 

     let startTimeString = self.timesArray[row]["startTime"] 
     let startTimeObject  = self.convertToDateObject(timeString: startTimeString!) 
     let minEndTimeObject = startTimeObject.addingTimeInterval(5 * 60.0)   // adding 5mins 
     cell.datePicker.minimumDate = minEndTimeObject 

     // Setting maximum endTime for datePicker 
     if rows == 1 || row + 1 == self.timesArray.count{ // For first and last row 
      let maxEndTimeString = "11:55 pm" 
      cell.datePicker.maximumDate = self.convertToDateObject(timeString: maxEndTimeString) 
     } 
     else{ // If more than one row 
      let nextCellStartTime   = self.timesArray[row + 1]["startTime"]! 
      let nextCellStartTimeObject  = self.convertToDateObject(timeString: nextCellStartTime) 
      cell.datePicker.maximumDate  = nextCellStartTimeObject 
     } 

     // Setting selected date in as endTime title 
     let dateString = self.convertDateToString(cell.datePicker.date) 
     cell.endTime.setTitle(dateString, for: .normal) 

     // Saving updated date to the timesArray 
     self.timesArray[row]["endTime"] = dateString 
     print("timesArray when endTimeHighlighted: \(self.timesArray)") 

     completionHandler(cell) 

    } 

    tableView.endUpdates() 

} 
+0

看來你不明白回調關閉如何工作。通常他們不會返回任何東西。 – vadian

+0

你確定該方法被調用嗎? – Thomas

+0

你還有另外一個選擇來更新你的tableView的數據源,然後使用'didSet'並調用'tableView.reloadData()'。這樣你的數據也會被意識到更新。 – Honey

回答

1

好像你混淆了別的東西completionHandlers。

當任務異步時,通常會使用completionHandlers。所以總之,你開始一個任務(通常是網絡),當它完成時(可能需要非常長的時間),你可以調用一個處理程序讓應用程序知道它已經完成。

由於應用程序沒有等待這個非常長的異步任務完成,它仍然繼續運行,並且與第一次啓動任務時的狀態不同。簡而言之,無論您在完成處理程序中返回的內容是否將被使用。基於

上,而這一切似乎事實是同步的,你可以重構你的功能,像這樣:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = Bundle.main.loadNibNamed("DailyTimesTableViewCell", owner: self, options: nil)?.first as! DailyTimesTableViewCell 
    cell.endTimeTapped = { [unowned self](_) in 
     // Use unowned to make sure you don't create a retain-cycle 
     self.setTimeInDatePicker(time: endTime!, cell: cell) 
    } 
    return cell 
} 


func setTimeInDatePicker(time: String, cell: DailyTimesTableViewCell) { 

    let row  = cell.tag 
    let rows = self.timesArray.count 

    if self.startTimeHighlighted{ 
     // Setting minimum startTime for datePicker 
     if row == 0{ // For first row 
      let minStartTimeString  = "0:05 am" 
      cell.datePicker.minimumDate = self.convertToDateObject(timeString: minStartTimeString) 
     } 
     else if row > 0 { // For remaining rows 
      let endTimeStringOfPreviousCell = self.timesArray[row - 1]["endTime"]! 
      let endTimeObjectOfPreviousCell = self.convertToDateObject(timeString: endTimeStringOfPreviousCell) 
      cell.datePicker.minimumDate  = endTimeObjectOfPreviousCell 
     } 

     // Setting maximum startTime for datepicker 
     let endTimeString   = self.timesArray[row]["endTime"]! 
     let endTimeObject   = self.convertToDateObject(timeString: endTimeString) 
     let maxStartTimeObject  = endTimeObject.addingTimeInterval(-5 * 60.0)   // removing 5mins 
     cell.datePicker.maximumDate = maxStartTimeObject 

     // Setting selected date in as startTime title 
     let dateString = self.convertDateToString(cell.datePicker.date) 
     cell.startTime.setTitle(dateString, for: .normal) 

     // Saving updated date to the timesArray 
     self.timesArray[row]["startTime"] = dateString 
     //print("endTime in DatePickerChanged: \(self.timesArray[row]["endTime"])") 
     print("timesArray when startTimeHighlighted: \(self.timesArray)") 

    } 
    else if self.endTimeHighlighted{ 
     print("datePicker changed 3") 
     // Setting minimum endTime for datePicker 

     let startTimeString = self.timesArray[row]["startTime"] 
     let startTimeObject  = self.convertToDateObject(timeString: startTimeString!) 
     let minEndTimeObject = startTimeObject.addingTimeInterval(5 * 60.0)   // adding 5mins 
     cell.datePicker.minimumDate = minEndTimeObject 

     // Setting maximum endTime for datePicker 
     if rows == 1 || row + 1 == self.timesArray.count{ // For first and last row 
      let maxEndTimeString = "11:55 pm" 
      cell.datePicker.maximumDate = self.convertToDateObject(timeString: maxEndTimeString) 
     } 
     else{ // If more than one row 
      let nextCellStartTime   = self.timesArray[row + 1]["startTime"]! 
      let nextCellStartTimeObject  = self.convertToDateObject(timeString: nextCellStartTime) 
      cell.datePicker.maximumDate  = nextCellStartTimeObject 
     } 

     // Setting selected date in as endTime title 
     let dateString = self.convertDateToString(cell.datePicker.date) 
     cell.endTime.setTitle(dateString, for: .normal) 

     // Saving updated date to the timesArray 
     self.timesArray[row]["endTime"] = dateString 
     print("timesArray when endTimeHighlighted: \(self.timesArray)") 

    } 

} 

注意endTimeTapped封閉如何使得[unowned self]用戶,以防止保留週期。

您還可以注意到beginUpdate/endUpdate已被刪除。原因是你沒有做任何影響有問題的單元格的高度,你只是簡單地改變日期,所以你不需要觸發tableView的刷新,因爲更改會自動應用。

檢查是否爲你做了什麼?

N.B.單元格是一個類,你發送給setTimeInDatePicker的參數是對它的引用,所以你真的不需要返回任何東西,所以你已經擁有了它。

+0

感謝您對完成處理程序的澄清。不幸的是,當我在函數setTimeInDatePicker完成執行之前返回單元格時,我嘗試了你的建議。 – user44776

+0

我認爲我錯過了一些東西,你是否也可以添加代碼。你的細胞在你的問題? – Thomas

+0

我實際上是錯誤地設置了一些標誌,這就是爲什麼你的建議不起作用,但是這一套,它的工作。這也似乎工作'cell.endTimeTapped = {(按鈕) - > DailyTimesTableViewCell在',很多感謝清楚的解釋。 – user44776

1

如果我理解正確,你只是想在一些回調或一些其他功能後能夠混淆一個單元格。只要需要,您可以使用tableView.cellForRow(at: IndexPath)來完成此目標。請注意,此函數返回UITableViewCell而不是您擁有的任何自定義單元格類型,因此您必須將其轉換爲(cell as? YourCustomCellClass)?.whateverFunctionOrPropertyHere。想想你希望如何傳遞信息 - 在單元格上設置完成塊並不是一個壞主意,但也有其他方法可以實現。