我有UITableViewController
。在第1部分中,有一个显示JTAppleCalendar的单元格,容易填充:
if indexPath.section == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("calendarViewCell") as! CalendarViewCell
print(eventDatesAsNSDates)
cell.calendarView.selectDates(eventDatesAsNSDates)
return cell
}
eventDatesAsNSDates
填充在viewDidAppear
。
理论上,一切都按我的意愿运作。但是如果我向下和向上滚动TableView,就会发生完全令人讨厌的行为。
cellForRowAtIndexPath print(eventDatesAsNSDates)
中的print语句证明eventDatesAsNSDates
没有改变,但日历仍然被填充一次而不是另一次,然后再次填充......
App中的其他时间都不会设置或调用cell.calendarView.selectDates
或eventDatesAsNSDates
。
我错过了什么?非常感谢帮助。
根据要求,selectDates函数:
public func selectDates(dates: [NSDate], triggerSelectionDelegate: Bool = true, keepSelectionIfMultiSelectionAllowed: Bool = false) {
var allIndexPathsToReload: [NSIndexPath] = []
var validDatesToSelect = dates
// If user is trying to select multiple dates with multiselection disabled, then only select the last object
if !calendarView.allowsMultipleSelection && dates.count > 0 { validDatesToSelect = [dates.last!] }
let addToIndexSetToReload = {(indexPath: NSIndexPath)->Void in
if !allIndexPathsToReload.contains(indexPath) { allIndexPathsToReload.append(indexPath) } // To avoid adding the same indexPath twice.
}
let selectTheDate = {(indexPath: NSIndexPath, date: NSDate) -> Void in
self.calendarView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None)
addToIndexSetToReload(indexPath)
// If triggereing is enabled, then let their delegate handle the reloading of view, else we will reload the data
if triggerSelectionDelegate {
self.internalCollectionView(self.calendarView, didSelectItemAtIndexPath: indexPath)
} else { // Although we do not want the delegate triggered, we still want counterpart cells to be selected
// Because there is no triggering of the delegate, the cell will not be added to selection and it will not be reloaded. We need to do this here
self.addCellToSelectedSetIfUnselected(indexPath, date: date)
let cellState = self.cellStateFromIndexPath(indexPath, withDate: date)
if let aSelectedCounterPartIndexPath = self.selectCounterPartCellIndexPathIfExists(indexPath, date: date, dateOwner: cellState.dateBelongsTo) {
// If there was a counterpart cell then it will also need to be reloaded
addToIndexSetToReload(aSelectedCounterPartIndexPath)
}
}
}
let deSelectTheDate = { (oldIndexPath: NSIndexPath) -> Void in
addToIndexSetToReload(oldIndexPath)
if let index = self.theSelectedIndexPaths.indexOf(oldIndexPath) {
let oldDate = self.theSelectedDates[index]
self.calendarView.deselectItemAtIndexPath(oldIndexPath, animated: false)
self.theSelectedIndexPaths.removeAtIndex(index)
self.theSelectedDates.removeAtIndex(index)
// If delegate triggering is enabled, let the delegate function handle the cell
if triggerSelectionDelegate {
self.internalCollectionView(self.calendarView, didDeselectItemAtIndexPath: oldIndexPath)
} else { // Although we do not want the delegate triggered, we still want counterpart cells to be deselected
let cellState = self.cellStateFromIndexPath(oldIndexPath, withDate: oldDate)
if let anUnselectedCounterPartIndexPath = self.deselectCounterPartCellIndexPath(oldIndexPath, date: oldDate, dateOwner: cellState.dateBelongsTo) {
// If there was a counterpart cell then it will also need to be reloaded
addToIndexSetToReload(anUnselectedCounterPartIndexPath)
}
}
}
}
for date in validDatesToSelect {
let components = self.calendar.components([.Year, .Month, .Day], fromDate: date)
let firstDayOfDate = self.calendar.dateFromComponents(components)!
// If the date is not within valid boundaries, then exit
if !(firstDayOfDate >= self.startOfMonthCache && firstDayOfDate <= self.endOfMonthCache) { continue }
let pathFromDates = self.pathsFromDates([date])
// If the date path youre searching for, doesnt exist, then return
if pathFromDates.count < 0 { continue }
let sectionIndexPath = pathFromDates[0]
// Remove old selections
if self.calendarView.allowsMultipleSelection == false { // If single selection is ON
let selectedIndexPaths = self.theSelectedIndexPaths // made a copy because the array is about to be mutated
for indexPath in selectedIndexPaths {
if indexPath != sectionIndexPath { deSelectTheDate(indexPath) }
}
// Add new selections
// Must be added here. If added in delegate didSelectItemAtIndexPath
selectTheDate(sectionIndexPath, date)
} else { // If multiple selection is on. Multiple selection behaves differently to singleselection. It behaves like a toggle. unless keepSelectionIfMultiSelectionAllowed is true.
// If user wants to force selection if multiselection is enabled, then removed the selected dates from generated dates
if keepSelectionIfMultiSelectionAllowed {
if selectedDates.contains(calendar.startOfDayForDate(date)) {
addToIndexSetToReload(sectionIndexPath)
continue // Do not deselect or select the cell. Just add it to be reloaded
}
}
if self.theSelectedIndexPaths.contains(sectionIndexPath) { // If this cell is already selected, then deselect it
deSelectTheDate(sectionIndexPath)
} else {
// Add new selections
// Must be added here. If added in delegate didSelectItemAtIndexPath
selectTheDate(sectionIndexPath, date)
}
}
}
// If triggering was false, although the selectDelegates weren't called, we do want the cell refreshed. Reload to call itemAtIndexPath
if /*triggerSelectionDelegate == false &&*/ allIndexPathsToReload.count > 0 {
delayRunOnMainThread(0.0) {
self.batchReloadIndexPaths(allIndexPathsToReload)
}
}
}
答案 0 :(得分:1)
每次您的单元格再次可见时,cellForRow
委托方法都会尝试更新tableView行/部分。
我肯定会在其他地方准备数据(用于日历),我更愿意仅渲染数据。 UITableViewCell的可重用性将正确处理内容。
不要在cellForRow方法中调用该方法。尝试放置它,例如进入viewDidAppear()
方法。如果selectDates()
方法完成了更新tableView的所有工作,它仍然可以正常工作。