纯代码解释runloop

       最近做项目碰到个问题,具体的操作是在一个线程里面开启一个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.youkuaiyun.com/detail/itpeng523/9588702


<think>好的,我现在需要回答用户关于iOS内存管理实现的问题。用户要求用纯文本描述,所以我要确保内容结构清晰,分步骤说明,并且符合LaTeX格式的要求。首先,我得回忆iOS内存管理的基本机制,然后整理出关键点,最后用简明易懂的中文解释清楚。 首先,iOS主要使用自动引用计数(ARC)来管理内存。ARC是什么?它如何工作?用户可能对这些基础概念感兴趣。我需要解释ARC的基本原理,包括引用计数的增减机制,比如alloc、new、copy等会增加引用计数,而release会减少。还要提到编译器在编译时自动插入这些代码,不需要手动管理,这样可以减少内存泄漏和野指针的问题。 接下来,应该讨论内存管理中的所有权修饰符,比如__strong、__weak、__unsafe_unretained和__autoreleasing。每个修饰符的作用是什么?例如,__strong是默认的,持有强引用;__weak用于避免循环引用;__unsafe_unretained类似weak但不自动置nil,可能造成悬垂指针;__autoreleasing用于延迟释放。需要简明扼要地说明它们的区别和适用场景。 然后,循环引用是一个常见问题,尤其是在闭包和代理模式中。用户可能想知道如何避免这种情况。这里需要解释强引用循环的形成,以及如何通过使用weak或unowned来打破循环。例如,两个对象互相强引用,或者闭包捕获self而没有使用弱引用,都会导致循环引用,内存无法释放。 内存管理策略方面,除了ARC,还有自动释放池(Autorelease Pool)的概念。自动释放池用于延迟对象的释放,适用于需要返回临时对象的情况。主线程的RunLoop在每个周期会自动创建和销毁自动释放池,但手动创建池可以优化内存峰值,尤其是在循环中创建大量临时对象时。 另外,iOS系统在内存紧张时会发出警告,比如UIViewController的didReceiveMemoryWarning方法。开发者需要响应这些警告,释放不必要的资源,避免应用被系统终止。还要提到内存分页和压缩技术,iOS如何高效利用物理内存,以及OOM(Out Of Memory)终止机制,当内存不足时系统会终止优先级低的应用。 最后,调试工具也是重要的一环。Xcode提供的工具如Instruments中的Allocations和Leaks工具,帮助开发者检测内存泄漏和内存使用情况。静态分析工具可以在编译时发现潜在的内存问题。 需要确保每个部分逻辑连贯,不遗漏关键点,同时避免技术术语过于复杂,让不同层次的读者都能理解。可能需要检查是否有错误,比如ARC是否完全自动化,循环引用的例子是否准确,以及各部分之间的衔接是否自然。现在将这些内容组织成一个结构化的回答,确保符合用户的要求,使用纯文本并正确应用LaTeX格式。</think>iOS内存管理采用自动引用计数(ARC)为核心机制,以下是实现原理和关键组成部分的详细说明: 1. **自动引用计数(ARC)** $$引用计数 = 对象被持有的次数$$ - 编译器在编译阶段自动插入retain/release代码 - 对象创建时引用计数+1(如alloc/new/copy/mutableCopy) - 强引用使引用计数+1,超出作用域时自动-1 - 引用计数归零时立即释放内存 2. **所有权修饰符** ```objc __strong id obj = ... // 默认修饰符(强引用) __weak typeof(self) weakSelf = self; // 弱引用(自动nil化) __unsafe_unretained id unsafeObj; // 非安全弱引用 __autoreleasing NSError **error; // 延迟释放 ``` 3. **循环引用解决方案** - 典型场景:对象A强引用对象B,B反向强引用A - 打破方法: $$弱引用链(weak\ unowned)$$ - Delegate模式使用weak修饰 - Block中使用__weak修饰外部变量 4. **自动释放池** ```objc @autoreleasepool { // 临时对象在此区间结束时会收到release NSData *data = [NSData dataWithContentsOfFile:...]; } ``` - 主RunLoop自动管理池生命周期 - 手动创建池可优化内存峰值(如大数据循环处理) 5. **内存警告处理** ```swift override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // 释放缓存/非可见资源 } ``` - 收到系统警告时主动释放非必要内存 - 未正确处理可能导致进程终止 6. **底层内存管理** - 采用虚拟内存系统(分页+压缩) - 内存页压缩技术(iOS 7+) - OOM终止机制(Jetsam优先级排序) 7. **调试工具** - Xcode Instruments套件: - Allocations(内存分配追踪) - Leaks(泄漏检测) - VM Tracker(虚拟内存分析) - 静态分析器(Analyze) $$内存管理优化公式:$$ $$内存峰值 = \sum_{i=1}^{n}(临时对象内存) - 及时释放量$$ 实际开发中应重点关注: - 合理使用weak/unowned打破强引用环 - 及时处理AutoReleasePool - 响应内存警告事件 - 避免过度使用单例和全局缓存 - 使用值类型(struct/enum)替代对象类型 这种设计平衡了开发效率与运行时性能,使应用内存使用量维持在iOS系统安全阈值内(典型上限为设备RAM的50%-70%)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值