最近做项目碰到个问题,具体的操作是在一个线程里面开启一个while循环执行相关的代码,当然功能是实现了但是发现CPU占用率很高,后来查到原因我这样做无疑让这个线程一直处于唤醒的状态这样做太耗资源,通过查资料想到了使用RunLoop。 理论知识推荐这篇文章 http://ios.jobbole.com/85759/ 认真有耐心的看下去会有收获。下面通过代码来详细解决上面碰到的难题。
swift代码:
overridefunc viewDidLoad() {
super.viewDidLoad()
let lockQueue:dispatch_queue_t =dispatch_queue_create(
"RunLoopQueue",DISPATCH_QUEUE_SERIAL
)
dispatch_async(lockQueue) {
while(true)
{
print(".........")
}
}
}
这是我以前的做法运行:
简简单单打印就耗了这么多的cpu,简直了。下面加上runloop:
<span style="font-size:18px;"> dispatch_async(lockQueue) {
while(true)
{
print(".........")
self.currentRunLoop =NSRunLoop.currentRunLoop()
//第一种 如果只有这一句没有给它soures,observer,timer则这个RunLoop会直接退出,不进入循环
self.currentRunLoop.runMode(NSDefaultRunLoopMode, beforeDate:NSDate.distantFuture())
}
}</span>
直接运行:
可以看到效果还是一样的感觉runloop没起作用,跟那篇文章讲的一样,因为我们没有为RunLoop添加任何的源,接下来加上source:
<span style="font-size:18px;"> dispatch_async(lockQueue) {
while(true)
{
print(".........")
self.currentRunLoop =NSRunLoop.currentRunLoop()
//第二种 加上一个source此时这个线程被带到一个循环里去了
self.currentRunLoop.addPort(NSPort.init(), forMode: NSDefaultRunLoopMode)
//第一种 如果只有这一句没有给它soures,observer,timer则这个RunLoop会直接退出,不进入循环
self.currentRunLoop.runMode(NSDefaultRunLoopMode, beforeDate:NSDate.distantFuture())
}
}</span>
直接运行
这是我们发现只被打印一次说明该线程已经被加入到RunLoop中去了,接下来看怎么去唤醒这个runloop,要唤醒RunLoop必须要用performSelector:
override func viewDidLoad() {
super.viewDidLoad()
stopBtn.frame = CGRectMake(self.view.frame.origin.x+50, self.view.frame.origin.y+50, 100, 50)
self.view.addSubview(stopBtn)
stopBtn.addTarget(self, action: #selector(ViewController.stopRunLoop), forControlEvents:.TouchUpInside)
let lockQueue:dispatch_queue_t = dispatch_queue_create(
"RunLoopQueue", DISPATCH_QUEUE_SERIAL
)
dispatch_async(lockQueue) {
while(true)
{
print(".........")
self.myThread = NSThread.currentThread() //获得当前子线程
print("go in while \(self.count)")
self.currentRunLoop = NSRunLoop.currentRunLoop() //获得当前子线程的RunLoop
//第二种 加上一个source 此时这个线程被带到一个循环里去了
self.currentRunLoop.addPort(NSPort.init(), forMode: NSDefaultRunLoopMode)
//第一种 如果只有这一句 没有给它soures,observer,timer 则这个RunLoop会直接退出,不进入循环
self.currentRunLoop.runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture())
//CFRunLoopRun() //使用CFRunLoopRun 启动 就可以用CFRunLoopStop来停止
print("go in while \(self.count)")
self.count += 1
self.myThread.cancel()
self.myThread = nil
}
}
sleep(2)
self.performSelector(#selector(ViewController.log), onThread:self.myThread, withObject: nil, waitUntilDone: false) //执行 performSelector 唤醒runloop
}
func log(){
count += 1
print("count = \(count)")
//CFRunLoopStop(CFRunLoopGetCurrent())
}
运行:
.........
go in while 0
count = 1
go in while 1
.........
go in while 2
说明达到了唤醒的功能,知道了这些解决我上面说的那个问题应该很简单了!最后分享一个OC代码很好的例子。
http://download.csdn.net/detail/itpeng523/9588702