'fixing Memory Issue in Swift

I'm having a memory issue while pushing/segueing to certain UIViewControllers [ChallengePrivacySettingViewC].

All of component of the ChallengePrivacySettingViewC are created programmatically. I have extensively checked all the tools and I can't seem to figure out what is going on. It doesn't seems to be any kind of acyclic reference or weird pointer.

This is the ViewController that has being instantiated and allocates about 2 X 60+ MB while checking it through Allocations tool.

class ChallengePrivacySettingViewC:UIViewController{
    deinit {
        print("Got deinit") // this is called
    }
    typealias ChangeHandler = (([Bool]) -> Void)
    var changeHandler: ChangeHandler?

    let menuView = UIView()
    private var tableView:UITableView = {
        let tb = UITableView()
        tb.translatesAutoresizingMaskIntoConstraints = false
        return tb
    }()
    lazy var backdropView: UIView = {
        let bdView = UIView(frame: self.view.bounds)
        bdView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        return bdView
    }()

    var privacyGroup:[Bool] = [true,false] //get dependency injection
    let menuHeight = UIScreen.main.bounds.height / 3
    var isPresenting = false

    var dataSource:[ChallengePrivacyModel] = [ChallengePrivacyModel]()

    init() {
        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .custom
        transitioningDelegate = self
    }
    fileprivate func setupConstraints() {
        view.backgroundColor = .clear
        view.addSubview(backdropView)
        view.addSubview(menuView)
        menuView.addSubview(tableView)

        menuView.layer.cornerRadius = 20
        tableView.layer.cornerRadius = 20
        menuView.backgroundColor = .white
        menuView.translatesAutoresizingMaskIntoConstraints = false
        menuView.heightAnchor.constraint(equalToConstant: menuHeight).isActive = true
        menuView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        menuView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        menuView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: menuView.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: menuView.trailingAnchor),
            tableView.topAnchor.constraint(equalTo: menuView.topAnchor),
            tableView.bottomAnchor.constraint(equalTo: menuView.bottomAnchor),
        ])

    }
    fileprivate func setup() {
        setupConstraints()

        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(ChallengePrivacyCell.self, forCellReuseIdentifier: "cellId")
        tableView.isScrollEnabled = false


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ChallengePrivacySettingViewC.handleTap(_:)))
        backdropView.addGestureRecognizer(tapGesture)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        dataSource = ChallengePrivacyModel.loadData()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    }

    @objc func handleTap(_ sender: UITapGestureRecognizer) {
        changeHandler?(privacyGroup)
        dismiss(animated: true, completion: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

The way I show the viewController:

 @objc func tapOnPrivacyBtn(_ sender: UIButton) {
        let vc = ChallengePrivacySettingViewC()
        vc.privacyGroup = self.privacyGroup
        vc.changeHandler = { [weak self] privacyGroup in
            self?.privacyGroup = privacyGroup
        }
        present(vc, animated: true, completion: nil)
  }

deinit() is called every time popping out of the ChallengePrivacySettingViewC. There is no dangling reference.

Growth of memory on Allocation tool:

 VM: CoreUI image data      122.05 MiB  3
  0x14a75b000   00:51.346.892   60.06 MiB    
  0x13c3ed000   00:51.314.556   60.06 MiB    
  0x138ca5000   00:51.378.480   1.94 MiB     

I saw this on stack trace for [0x14a75b000 and 0x13c3ed000]:

   0 libsystem_kernel.dylib mmap
   1 CoreUI -[_CSIRenditionBlockData _allocateImageBytes]
   2 CoreUI -[_CSIRenditionBlockData initWithPixelWidth:pixelHeight:sourceRowbytes:pixelFormat:]
   3 CoreUI __csiCompressImageProviderCopyImageBlockSetWithOptions
   4 CoreGraphics CGImageProviderCopyImageBlockSetWithOptions
   5 QuartzCore CA::Render::(anonymous namespace)::create_image_from_image_provider(CGImage*, CGImageProvider*, CGColorSpace*, unsigned int)
   6 QuartzCore CA::Render::create_image(CGImage*, CGColorSpace*, unsigned int, double)
   7 QuartzCore CA::Render::copy_image(CGImage*, CGColorSpace*, unsigned int, double, double)
   8 QuartzCore CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double)
   9 QuartzCore CA::Layer::prepare_commit(CA::Transaction*)
  10 QuartzCore CA::Context::commit_transaction(CA::Transaction*)
  11 QuartzCore CA::Transaction::commit()
  12 UIKitCore _afterCACommitHandler
  13 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
  14 CoreFoundation __CFRunLoopDoObservers
  15 CoreFoundation __CFRunLoopRun
  16 CoreFoundation CFRunLoopRunSpecific
  17 GraphicsServices GSEventRunModal
  18 UIKitCore UIApplicationMain
  19 Company main /Users/Company/Desktop/Original/frontend-current/company/Module/LoginSignup/SignupVC/BankingSetupC.swift:26
  20 libdyld.dylib start

Strange bit out of all is that. I will have these 2 chunk of 60MB floating in memory unless I go out of the app. Pressing in home button will reset memory back to normal memory usage. App was never killed on at any point.

Any idea what is going on here ? Much appreciated



Solution 1:[1]

Which method will cause creating a lot of VM: CoreUI image data

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chi Victor