iphone – 后台线程NSTimer无效后NSRunloop运行不会退出!为什么?

我正在创建一个NSTimer并将其添加到后台线程的runloop中.

我的代码就像这个答案的后台线程示例:
iPhone-SDK:Call a function in the background?

在创建计时器并将其从gdb附加到runloop之后,我运行了runLoop并输出:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false,
current mode = kCFRunLoopDefaultMode,
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"}
}
,
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>}
}
,
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03, 
    sources0 = (null),
    sources1 = (null),
    observers = (null),
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 1, values = (
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>}
)}
},

}
}

这表明1个计时器连接到runloop
在我使计时器失效之后,NSRunloop运行方法没有退出,但在我暂停调试器后,再次从gdb我再次运行runLoop,它看起来像这样:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false,
current mode = kCFRunLoopDefaultMode,
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"}
}
,
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 0,
entries =>
}
,
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03, 
    sources0 = (null),
    sources1 = (null),
    observers = (null),
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 0, values = ()}
},

}
}

现在“计时器”条目有0个对象.但线程继续运行.我经常离开屏幕,然后回来,这导致后台线程的积累,最终会在使用太多资源后杀死应用程序.定时器在失效后不会触发,但后台线程仍然存在.

我知道我可以将计时器移回主线程或使用NSThread sleepForTimeInterval创建我自己的简单计时器线程,但我想保留GUI更新的主线程并尽可能使用NSTimer.

最佳答案 来自
-[NSRunLoop run]文档:

Manually removing all known input sources and timers from the run loop is not a guarantee that the run loop will exit.

您应该使用不同的方法,可能是runMode:beforeDate:在循环中,并且在您使计时器无效的同时,设置一个标志,指示运行循环应该结束.

点赞