본문 바로가기

Swift/All

class의 배열만들기(약한 참조 하는 배열, weak array)

개발을 하다보니 class의 배열을 만들 일이 생겼다

 

정확히는 ViewController(이하 VC)의 배열을 만들고 deinit될 때는 해당 배열에서 없어져야 했다

 

딱 생각나는 방법이 두 가지가 있었는데

 

1. 해당 VC가 deinit될 때 배열에서 remove해주기

2. 해당 VC가 deinit되야 하는'곳'(예를 들변 pop되는 곳) 에서 remove해주기

 

딱 봐도 2번같은 경우에는 메모리가 해제되어야 하는 모든 부분을 알고 대응하기 어렵기 때문에 1번의 방법으로 가기로 했는데 이게 왠걸...?

 

너무나 당연한 얘기지만 배열에 VC가 추가되면서 참조를 하고 있기에 deinit이 호출이 안된다 ㅋ

 

그래서 생각난게 '약한 참조를 하는 배열을 만들면 되지 않을까? 근데 그걸 어케하지;;' -> 구글링

 

https://habr.com/en/articles/726320/

 

Array of weak in Swift

In Swift, when working with objects, it’s important to manage memory correctly. One way to do this is by using weak references to avoid retaining objects too long and causing memory leaks. In this...

habr.com

 

위 글을 찾았는데 너무나 똑똑한 사람들이 많다 세상에는

 

일단 코드를 보자면...

final class Weak<T: AnyObject> {
    weak var value: T?
    
    init(_ value: T) {
        self.value = value
    }
}

 

해결법은 간단하다. 제네릭으로 뭐든 일단 받고 그 안에 value로 약한참조 하는 프로퍼티를 만들어놓으면 VC가 deinit될 때 해당 value가 nil이 된다

그러면 배열에서는 nil인거 찾아서 지워버리면 된다

 

그렇게 아래와 같이 코드를 작성해봤다

 

//////// 대충 어딘가에 있는 VC의 배열
var someVCList = [Weak<SomeVC>]()

//////// SomeVC의 init&deinit
	
    init() {
        super.init(nibName: nil, bundle: nil)
        someVCList.append(Weak(self))
    }
    
    deinit {
        someVCList.removeAll { someVC in
            someVC.value == nil
        }
    }

좌좌~ 이러게 하면 화면에 무수히 많이 로드되어있는 SomeVC중 하나가 deinit이 되면 해당 VC를 배열에 넣을 때 생성해줬던 Weak class의 value는 nil이 될 것이기 때문에 삭제해주면 된다

 

근데 뭔가 맘에 안든다

그냥 value가 nil이 되면 자동으로 삭제되는 뭐 그런 기능 없나 고민 해봤는데

someVCList를 갖고 있는 배열을 만들고 그걸 갖고 있는 객체를 만들고 해서 nil되면 전달해서 없애버리고 할 수는 있을 것 같은데...