오늘은 UIImage를 사용할 때 간단하지만 재밌는 사실을 정리해 보려고 한다.
UIKit으로 UIImage를 생성하기 위해 흔히 UIImage(named:)
로 초기화한다.
named를 파라미터로 받는 생성자를 사용할 경우 해당 이름의 이미지 에셋이나 파일을 찾아서 존재할 경우 이를 생성, 없을 경우 nil로 반환한다.
그런데 만약 같은 이미지를 계속해서 UIImage.init(named: "이미지 이름")
으로 생성하면 내부에서는 어떤 일이 발생할까?
(상상안)
- 이미지를 불러오기 위해서 파일(혹은 에셋)을 찾고
- 해당 파일이 존재할 경우 이를 메모리 상에 로드한다 (없으면 nil로 종료)
- 새롭게 생성된 UIImage를 사용한다.
이미지 사용이 다 끝나면 UIImage 객체가 해제되고 그럼 메모리에 로드된 파일도 함께 해제되는 것이 예상되는 동작이다.
하지만 named로 생성한 이미지는 이 과정에서 Caching 기능이 추가된다.
바로 NSCache 클래스를 내부적으로 사용하여 갖고 와야 할 이미지의 캐시 존재 여부를 확인하는 것이다.
그럼 위 동작이 아래처럼 수정된다.
- 불러올 이미지의 캐시가 존재하는지 확인하다.
- 캐시가 존재하면 캐시를 return 존재하지 않으면 파일을 찾고
- 해당 파일이 존재할 경우 이를 메모리 상에 로드한다 (없으면 nil로 종료)
- 새롭게 생성된 UIImage를 사용한다.
첫 번째 차이점이라 하면 캐싱 기능을 거치기 때문에 같은 파일을 여러 번 UIImage(named:)
로 호출할 때 성능이 좀 더 좋을 수 있다.
파일 경로로 이미지를 초기화할 수도 있다.
이 방법을 사용할 경우 UIImage(named:)
으로 초기화 한 것과 다르게 캐싱 과정이 생략된다. 매 생성 시 직접 이미지를 가져오기 때문에 정확하지만 반복적인 로드에는 적합하지 않은 초기화 방법으로 알려져 있다.
NSCache를 거치는데 Thread-safe 하게 관리될까? (각기 다른 Thread에서 동시에 같은 이미지를 UIImage(named:)
로 초기화하려고 하면?)
-> iOS 9 이후 부터는 thread-safe하게 관리되고 있다니 안심하고 사용하자!
참고
https://developer.apple.com/documentation/uikit/uiimage/1624146-init
https://developer.apple.com/documentation/uikit/uiimage/1624112-init