2017-07-12 3 views
0

は現在、私のコードは、このようなものがあり、どう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ので、コールバックsetTimeInDatePickerを使用してセル内のdatePickerを変更するには、以下のコードBを試してみると動作していないようです。

私が間違っている可能性のあるアドバイスをしてください。

コードB:あなたが何か他のものと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 = { (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が使用されます。つまり、タスク(通常はネットワーク)を開始し、完了すると(非常に長い時間がかかります)、アプリケーションが終了したことをアプリケーションに伝えるために呼び出すことができるハンドラがあります。

この非常に長い非同期タスクが終了するまでアプリケーションが待機しなかったため、アプリケーションは実行を継続し、タスクが最初に開始されたときと同じ状態ではありません。要するに、あなたが完了ハンドラで返すものは何でも使用されるべきであり/使用されるべきではありません。その上で

、すべてがあなたがそうのように、あなたの関数をリファクタリングでき、同期のようだという事実:endTimeTappedの閉鎖は保持サイクルから保護するために[unowned self]のユーザーを作る方法

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)") 

    } 

} 

注意。

また、beginUpdate/endUpdateが削除されていることがわかります。その理由は、問題のセルの高さに影響を与えることを何もしていないということです。単に日付を変更するだけなので、変更が自動的に適用されるため、tableViewのリフレッシュをトリガーする必要はありません。

これがあなたのために何かをしたかどうかを確認してください。

N.B.セルがクラスであるため、setTimeInDatePickerへのパラメータとして送信するものはそのセルへの参照です。したがって、実際に何かを返す必要はありません。

+0

完了ハンドラの説明に感謝します。残念ながら、あなたの提案を試みたとき、関数 'setTimeInDatePicker'の実行が完了する前に、セルが返されています。 – user44776

+0

私は何かが欠けていると思います。コードを追加することもできますか?あなたのセルはあなたの質問にありますか? – Thomas

+0

私は実際にいくつかのフラグを間違って設定していました。それはあなたの提案がうまくいかなかった理由です。これは 'cell.endTimeTapped = {(button) - > DailyTimesTableViewCell in'でも動作するようです。 – user44776

1

私が正しく理解していれば、コールバックの後、または他の機能の中でセルを混乱させたいだけです。必要に応じてtableView.cellForRow(at: IndexPath)を使用してこの目標を達成できます。この関数は、あなたが持っているカスタムセルタイプの代わりにUITableViewCellを返します。したがって、それを(cell as? YourCustomCellClass)?.whateverFunctionOrPropertyHereとしてキャストする必要があります。どのように情報を渡したいか考えてみましょう。セルの完成ブロックを設定することは悪い考えではありませんが、他の方法もあります。

関連する問題