스위프트는 꽤 정교하고 효율적인 메모리 관리를 한다고 알려져 있지만 상황에 따라서 프로그래머의 의도와 전혀 다르게 동작할 수 있습니다.
다음은 디비에서 데이터를 가져와서 사진갯수를 표시하는 코드인데 데이터의 갯수가 매우 많을 경우 앱 메모리 사용량 초과로 크래시가 발생합니다. 더 좋지 않은건 크래시 발생 로그만 봐서는 메모리 사용량 초과로 OS가 강제로 앱을 죽이는 상황을 알 수가 없습니다. 아래 루프에서 스위프트는 루프가 종료될 때까지 사진 데이터 메모리를 해제하지 않습니다. for 루프가 모두 종료된 후에 사진 데이터의 메모리를 해제합니다. (ARC 환경)
extension Entry { var _photoCount: Int { get { if let __photos = photos { do { let ps = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(__photos) as? [[String:Any?]] let count = ps?.count ?? 0 return count } catch { } } return 0 } } } var photoCount = 0 if let entrys = Fetch.entry([:]) { for e in entry { photoCount += e._photoCount } }
프로그래머가 원하는 바는 for 루프가 종료될 때 일괄적인 메모리 해제가 아닌 사진의 갯수를 읽은 후 데이터의 메모리 해제를 원할 겁니다. 이 때 autoreleasepool을 사용하면 됩니다. 아래처럼 autoreleasepool 키워드를 추가하여 autoreleasepool 이 해제될 때 함께 해제됩니다.
var _photoCount: Int { get { autoreleasepool { if let __photos = photos { do { let ps = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(__photos) as? [[String:Any?]] let count = ps?.count ?? 0 return count } catch { } } return 0 } //이 때 ps가 가리키고 있는 메모리도 함께 해제됨 } }