Delegate는 왜 속성에서 웹을 지정해야 합니까?

9195 단어 SwiftiOS

개시하다


만약strong,weak 등 모든 속성을 적당히 더하면
기억 유출이 발생하면 선배에게 자주 구설에 오르나요?
어떻게 된 건지 정리 좀 했어요.
흔히 말하는 상황은:
Outlet, Delegate, Closures 등인가요?
SwiftLight에서도 경고가 표시됩니다.
이번에는 Delegate를 예로 들어 설명하겠습니다.

샘플 설명


1st화면, 2nd화면, 3rd화면을 구성하는 3개의 화면.

1st 화면 사양


버튼을 누르면 두 번째 화면으로 이동합니다.
FirstViewController.swift
import UIKit

final class FirstViewController: UIViewController {

    @IBAction func didTap2ndScene(_ sender: UIButton) {

        let secondVC = UIStoryboard.viewController(storyboardName: "Main",
                                             identifier: "SecondViewController")
        self.navigationController?.pushViewController(secondVC!, animated: true)

    }
}

2nd 화면 규격


속성을 사용하여 제3화면을 관리하는 실례.
2nd 화면에서 3d 화면까지의 Delegate 속성은 자신을 설정합니다.
버튼을 누르면 세 번째 화면으로 이동합니다.
SecondViewController.swift
import UIKit

final class SecondViewController: UIViewController {

    var thirdVC: ThirdViewController?

    @IBAction func didTap3rdScene(_ sender: UIButton) {

        thirdVC = UIStoryboard.viewController(storyboardName: "Main",
                                             identifier: "ThirdViewController")
        if let vc = thirdVC {
            vc.delegate = self
            self.navigationController?.pushViewController(vc, animated: true)
        }
    }
}

extension SecondViewController: ThirdDelegate {

    func completion() {
        print(#function)
    }
}

3rd 화면 사양


delegate를 속성으로 관리합니다.모든 속성을 생략하여 strong으로 만듭니다.
버튼을 누르면delegate를 통해 2nd 화면에 알리고 화면을 닫습니다.
ThirdViewController.swift
import UIKit

protocol ThirdDelegate: class {
    func completion()
}

final class ThirdViewController: UIViewController {

    var delegate: ThirdDelegate?

    @IBAction func didTapGoBack(_ sender: UIButton) {

        delegate?.completion()
        self.navigationController?.popViewController(animated: true)
    }
}

그렇다면 메모리 유출은 언제 일어날까?


정답은 두 번째 화면을 닫을 때 메모리 유출을 일으킨다는 것이다.
이유는 2nd 화면이strong에서 세 번째 화면의 실례를 유지하고 있기 때문이다.
또한 세 번째 화면에서delegate는strong에서 유지된다.
즉, 이것은 순환 인용으로 상호 인용 대상의 상태에 있다.

이를 통해 인스트루먼트의 Leak Checks에서 모니터링을 해도 메모리 유출이 감지된다.

그럼 어떡하지?


3rd 화면에서 관리되는delegate의 모든 속성을 weak로 설정합니다.
또는 제2화면에서 관리하는 제3화면의 실례를 weak로 설정합니다.
이렇게 하면 순환 인용을 방지할 수 있다.

ThirdViewController.swift
import UIKit

protocol ThirdDelegate: class {
    func completion()
}

final class ThirdViewController: UIViewController {

    weak var delegate: ThirdDelegate?

    @IBAction func didTapGoBack(_ sender: UIButton) {

        delegate?.completion()
        self.navigationController?.popViewController(animated: true)
    }
}
인스트루먼트의 렉 체크에서 모니터링을 해도 메모리 유출은 발생하지 않는 것으로 확인됐다.

총결산


ARC를 잘 모르시는 분들.
Instruments의 Leak Checks로 모니터링을 해보면 곧 공부가 될 거야.
Closures의 생각도 마찬가지입니다.
클래스에서 클론 사용자를 참조하고 클론에서 클래스의 속성을 참조하기 때문입니다.
순환 인용이 발생하여 메모리 유출을 일으키다.
하지만 가능하면 변수의 범위를 좁히고 로컬 변수로 관리하면
메모리 유출을 막을 수 있을 것 같습니다.

좋은 웹페이지 즐겨찾기