イムでの操作を実行してキャンセルすることはできませんグラフデータを再計算する必要があります。ユーザーがチャートデータフィルタリングボタンを非常に素早くクリックすると(パワーユーザー)、GCDディスパッチの非同期が終了するたびにグラフがループします。は、私はもともとGCDを使いましたが、毎回ユーザーがボタンを押すことでグラフのデータをフィルタリングし、バックグラウンドスレッド</p> <p>上のチャートデータを作成するために、いくつかの長い計算をやってOperationQueue迅速
GCDでスレッドをキャンセルできませんだから実装しようとしましたOperationQueue
私は0を呼び出しますキューに新しい操作を追加する前に
キューの操作はファンキーな動作をしますが、キャンセルされたように見えることもありますが、キューに入れられた最新のものではない場合があります。
私も、私は事業完了ブロックでそれを確認したときの動作の.isCancelledプロパティがtrueになることはありませんとして実行する操作をキャンセルするトラブルを抱えています
チャートデータの計算は、現在で起こっている場合は私が本当に欲しいのですバックグラウンドスレッドで、別のフィルタボタンをクリックしてバックグラウンドスレッドで別のチャート計算を開始すると、直前のチャートバックグラウンド計算が終了し、直近の追加操作で「置き換えられました」
これは可能ですか?さておき、それは完全に真実ではないのと同じように
func setHistoricalChart() -> Void {
self.lineChartView.clear()
self.lineChartView.noDataText = "Calculating Historical Totals, Please Wait..."
self.historicalOperationsQueue.qualityOfService = .utility
self.historicalOperationsQueue.maxConcurrentOperationCount = 1
self.historicalOperationsQueue.name = "historical operations queue"
let historicalOperation = Operation()
historicalOperation.completionBlock = { [weak self] in
//dictionary of feeds, array of data for each feed
var valuesByFeed = [String:[String]?]()
var dates = [String:[String]?]()
var chartDataSets = [IChartDataSet]()
//get data and values from DataMOs in the activeFeeds
if (self?.activeFeeds.count)! > 0 {
//check if operation is cancelled
if historicalOperation.isCancelled {
return
}
for (key, feed) in (self?.activeFeeds)! {
dates[key] = feed?.datas?.flatMap({ Utils.formatUTCDateString(utcDateString: ($0 as! DataMO).utcDateString) })
valuesByFeed[key] = feed?.datas?
.sorted(by: { (($0 as! DataMO).utcDateString)! < (($1 as! DataMO).utcDateString)! })
.flatMap({ ($0 as! DataMO).value })
}
//Create Chart Data
for (key, valuesArray) in valuesByFeed {
var dataEntries = [ChartDataEntry]()
for (index, value) in (valuesArray?.enumerated())! {
let dataEntry = ChartDataEntry(x: Double(index), y: Double(value)!)
dataEntries.append(dataEntry)
}
let singleChartDataSet = LineChartDataSet(values: dataEntries, label: key)
singleChartDataSet.drawCirclesEnabled = false
switch key {
case "Solar":
singleChartDataSet.setColors(UIColor(red: 230/255, green: 168/255, blue: 46/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 230/255, green: 168/255, blue: 46/255, alpha: 0.8)
break
case "Wind":
singleChartDataSet.setColors(UIColor(red: 73/255, green: 144/255, blue: 226/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 73/255, green: 144/255, blue: 226/255, alpha: 0.8)
break
case "Battery":
singleChartDataSet.setColors(UIColor(red: 126/255, green: 211/255, blue: 33/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 126/255, green: 211/255, blue: 33/255, alpha: 0.8)
break
case "Gen":
singleChartDataSet.setColors(UIColor(red: 208/255, green: 1/255, blue: 27/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 208/255, green: 1/255, blue: 27/255, alpha: 0.8)
break
case "Demand":
singleChartDataSet.setColors(UIColor(red: 128/255, green: 133/255, blue: 233/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 128/255, green: 133/255, blue: 233/255, alpha: 0.8)
break
case "Prod":
singleChartDataSet.setColors(UIColor(red: 241/255, green: 92/255, blue: 128/255, alpha: 1))
singleChartDataSet.drawFilledEnabled = true
singleChartDataSet.fillColor = UIColor(red: 241/255, green: 92/255, blue: 128/255, alpha: 0.8)
break
default:
break
}
chartDataSets.append(singleChartDataSet)
}
}
//check if operation is cancelled
if historicalOperation.isCancelled {
return
}
//set chart data
let chartData = LineChartData(dataSets: chartDataSets)
//update UI on MainThread
OperationQueue.main.addOperation({
if (self?.activeFeeds.count)! > 0 {
self?.lineChartView.data = chartData
} else {
self?.lineChartView.clear()
self?.lineChartView.noDataText = "No Feeds To Show"
}
})
}
historicalOperationsQueue.cancelAllOperations()
historicalOperationsQueue.addOperation(historicalOperation)
}
操作をキャンセルすると、競合状態が発生する可能性があります。回避することはできません。 GUIまたはその他のローカルでない状態変数を更新する前に、操作の始めにすべての時間のかかる呼び出しをスケジュールすることは有益です。あなたの操作で最も時間のかかる機能は何ですか? –
また、WWDC 2015から[Advanced NSOperations](https://developer.apple.com/videos/play/wwdc2015/226/?time=307)をお勧めします。取り消しについては、5:00のマーク –
で議論されています。ユーザーがボタンをクリックするたびにこの関数が呼び出されます。ユーザーがボタンを3回すばやくクリックしないようにしてから、チャートをゆっくり3回更新すると、ユーザーには遅く感じられます。 –