메모리 누수 해결하기
사이드 프로젝트 중 네이버맵 API를 사용하고 있었는데 난리가 나버렸다…
메모리 누수 어쩔거야,,,
marker.touchHandler = { [weak self] (overlay) -> Bool in
guard let self = self else { return true }
if let currentInfoWindow = self.currentInfoWindow {
currentInfoWindow.close()
}
let infoWindow = NMFInfoWindow()
let dataSource = NMFInfoWindowDefaultTextSource.data()
dataSource.title = restaurant.title
infoWindow.dataSource = dataSource
infoWindow.open(with: marker)
self.currentInfoWindow = infoWindow
infoWindow.touchHandler = { [weak self] (overlay) -> Bool in
guard let self = self else { return true }
DispatchQueue.main.async {
self.selectedRestaurant = restaurant
}
return true
}
return true
}
Swift
복사
메모리 누수가 발생하는 이유는 NMFMarker의 touchHandler에서 강한 참조 순환(retain cycle)이 발생하기 때문이다.
NMFMarker는 자신 안에 있는 클로저(touchHandler)를 강하게 참조하고, 그 클로저는 self(즉, Coordinator 객체)를 강하게 참조하고 있다.
이로 인해 두 객체가 서로를 강하게 참조하게 되어 메모리 누수가 발생,,!!!
하지만 위 코드와 같이 [weak self] 를 했는데도 계속 메모리 누수 발생,,, ㅠㅜ
마커는 맵에 추가된 후에 명시적으로 해제되지 않는다면 계속 메모리에 남아있을 수 있다.
마커가 더 이상 필요 없을 때 명확히 해제해보자.
marker.touchHandler = { [weak self, weak marker] (overlay) -> Bool in
guard let self = self, let marker = marker else { return true }
if let currentInfoWindow = self.currentInfoWindow {
currentInfoWindow.close()
}
let infoWindow = NMFInfoWindow()
let dataSource = NMFInfoWindowDefaultTextSource.data()
dataSource.title = restaurant.title
infoWindow.dataSource = dataSource
infoWindow.open(with: marker)
self.currentInfoWindow = infoWindow
infoWindow.touchHandler = { [weak self, weak marker] (overlay) -> Bool in
guard let self = self else { return true }
DispatchQueue.main.async {
self.selectedRestaurant = restaurant
}
return true
}
return true
}
Swift
복사
•
marker.touchHandler 에서 [weak marker] , 이제 marker 자체를 약하게 참조하여 순환 참조를 방지
•
infoWindow.touchHandler 에서 [weak marker] , infoWindow와 marker 사이의 참조를 약하게 설정
이 개선된 코드에서는 marker와 infoWindow의 참조 순환을 방지하기 위해 모든 클로저에서 self와 marker를 약하게 참조했다.
이를 통해 메모리 누수가 발생하지 않고, 마커와 관련된 리소스가 적절하게 해제될 수 있다.
다행히 메모리 누수가 사라졌다~