swift ~ uber/RIBs内存泄漏检测

笔者曾用过Instrument检测内存泄漏,泄漏并非完全能检测出来;
几番周折之后发觉 在每个dealloc或者deinit析构函数 打印日志能解决问题,虽然笨拙但能解决在编码时候的自我检测规范。

废话少说,本篇介绍uber/RIBs内存泄漏工具(LeakDetector.swift)很优雅的解决我的需求

核心思路:
    ///存储即将释放变量
    private let trackingObjects = NSMapTable.strongToWeakObjects()

    /// Sets up an expectation for the given object to be deallocated within the given time.
    ///
    /// - parameter object: The object to track for deallocation.
    /// - parameter inTime: The time the given object is expected to be deallocated within.
    /// - returns: The handle that can be used to cancel the expectation.
    @discardableResult
    public func expectDeallocate(object: AnyObject, inTime time: TimeInterval = LeakDefaultExpectationTime.deallocation) -> LeakDetectionHandle {
        expectationCount.value += 1

        let objectDescription = String(describing: object)
        let objectId = String(ObjectIdentifier(object).hashValue) as NSString
        trackingObjects.setObject(object, forKey: objectId)

        let handle = LeakDetectionHandleImpl {
            self.expectationCount.value -= 1
        }

        Executor.execute(withDelay: time) {
            // Retain the handle so we can check for the cancelled status. Also cannot use the cancellable
            // concurrency API since the returned handle must be retained to ensure closure is executed.
            if !handle.cancelled {
                let didDeallocate = (self.trackingObjects.object(forKey: objectId) == nil)
                let message = "<\(objectDescription): \(objectId)> has leaked. Objects are expected to be deallocated at this time: \(self.trackingObjects)"

                if self.disableLeakDetector {
                    if !didDeallocate {
                        print("Leak detection is disabled. This should only be used for debugging purposes.")
                        print(message)
                    }
                } else {
                    assert(didDeallocate, message)
                }
            }

            self.expectationCount.value -= 1
        }

        return handle
    }

NSMapTable需要了解一下

总结如下:

将需要释放的对象添加到trackingObjects,当添加的对象引用计数执行一次-1,添加的对象在内存中就会自动释放,并且相应的trackingObjects对象中的对象也会被自动移除.

接下来,在deinit方法调用expectDeallocate()方法,延迟一定时间检测trackingObjects对象的是否消失即可

so easy , look look deinit里的代码:
    ///PresentableInteractor.swift
    deinit {
        LeakDetector.instance.expectDeallocate(object: presenter as AnyObject)
    }

    ///Router.swift
    deinit {
        interactable.deactivate()

        if !children.isEmpty {
            detachAllChildren()
        }

        lifecycleSubject.onCompleted()

        deinitDisposable.dispose()

        LeakDetector.instance.expectDeallocate(object: interactable)
    }

    ///ViewableRouter.swift
    deinit {
        LeakDetector.instance.expectDeallocate(object: viewControllable.uiviewController, inTime: LeakDefaultExpectationTime.viewDisappear)
    }

基本思路就如此了,希望LeakDetector能成为你的好帮手

你可能感兴趣的:(swift ~ uber/RIBs内存泄漏检测)