処理中に一定時間経ったらキャンセルさせる場合
処理が一定時間経ったらタイムアウトさせたいと思い、以下のソースをswiftで書き換えてみました。
dispatchのcancelの方法を実践してみる
var source: dispatch_source_t?
func setTimer(date: NSDate, block:() -> ()) {
// deltaIntervalを取得してあげる
let deltaInterval: NSTimeInterval = date.timeIntervalSinceDate(NSDate())
asyncAfterDelay(deltaInterval, block: block)
}
func cancelTimer() {
print("キャンセルロジック外側に入りました。")
if source != nil {
print("キャンセルロジックに入りました。")
dispatch_source_cancel(source!)
}
}
func asyncAfterDelay(delay: NSTimeInterval, block:() -> ()) {
return asyncAfterDate(NSDate(timeIntervalSinceNow: delay), block: block)
}
func asyncAfterDate(date: NSDate, block:() -> ()) {
let queue: dispatch_queue_t = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL)
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
dispatch_source_set_event_handler(source!, {
dispatch_async(dispatch_get_main_queue(), {
// 時間になったら呼ばれるもの
block()
// 呼ばれたら処理をキャンセルする
if self.source != nil {
dispatch_source_cancel(self.source!)
}
})
})
let delta: dispatch_time_t = getDiapatchTimeByDate(date)
dispatch_source_set_timer(source!, delta, NSEC_PER_SEC, 0)
dispatch_resume(source!)
}
func getDiapatchTimeByDate(date: NSDate) -> dispatch_time_t {
var interval: NSTimeInterval
var second = Double()
var subsecond = Double()
var time = timespec()
var milestone: dispatch_time_t
interval = date.timeIntervalSince1970
subsecond = modf(interval, &second)
time.tv_sec = __darwin_time_t(second)
time.tv_nsec = Int(subsecond) * Int(NSEC_PER_SEC)
milestone = dispatch_walltime(&time, 0)
return milestone
}
そして以下の内容で動作を確認してみました。
しかし予定では3秒後にタイムアウトするはずが一向にならずループから抜けられません・・・
func doReadInputStream(connectTime: Int) -> Int {
// connectTime = 30
// 現在日時にconnectTime/10の値を足した日時を取得
let df = NSDateFormatter()
df.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let jpLocale = NSLocale(localeIdentifier: "ja_JP")
df.locale = jpLocale
df.dateFormat = "yyyyMMddHHmmssS"
let now = df.stringFromDate(NSDate())
let fmt = NSDateFormatter()
fmt.calendar = NSCalendar.init(calendarIdentifier: NSCalendarIdentifierGregorian)
fmt.dateFormat = "yyyyMMddHHmmssS"
var date = fmt.dateFromString(now)
let dComp = NSDateComponents()
let connectNum = connectTime / 10
dComp.second = connectNum
date = NSCalendar.currentCalendar().dateByAddingComponents(dComp, toDate: date!, options: NSCalendarOptions())
if let uwDate = date {
fmt.stringFromDate(uwDate)
} else {
print("dateがnilです。")
}
// タイマーセット
var isKeika = true
setTimer(date!, block: {
isKeika = false
})
// 以下のループを一定時間経ったら抜けたい
var num = 1
while isKeika == true {
print("ループ:\(num)回目")
num += 1
}
// ループを抜けた後の処理
書き換えを間違っている、もしくは足りない記述などがあるのでしょうか?