감자주먹밥

[SwiftUI] Image, AsyncImage 본문

IOS/SwiftUI

[SwiftUI] Image, AsyncImage

JustHm 2023. 2. 28. 14:12
728x90
 

Image | Apple Developer Documentation

A view that displays an image.

developer.apple.com

Image

SwiftUI 의 Image는 Asset 또는 디스크의 이미지를 보여주거나, SFSymbols를 표시할 수 있는 View. UIImage, CGImage도 가능.

IOS 13.0 부터 사용가능 기본적으로 사용하는 이미지 표시 방법은 다음과 같다.

Image("tempImage")
Image(decorative: "tempImage")
Image(systemName: "chart.bar.fill")

asset에 있는 Image를 가지고 올 수 있으며 Bundle 파라미터도 존재한다. 기본값은 nil

공식 문서에서 Image 각 이미지 생성에 Label을 파라미터로 받는 초기화들이 있는데, Label은 실제로 보여지진 않으나 accessibility를 위해 사용되는 것으로 이미지에 대한 정보를 제공하기 위해 작성 할 수 있다.

systemName으로 SFSymbols의 기호들도 가져와 사용할 수 있다. 또한 variableValue라는 파라미터로 가변 Symbols의 표시형식을 다르게 해서 보여줄 수도 있다.

Image(systemName: "chart.bar.fill", variableValue: 0.4)

SFSymbols에서 가변(variable)탭을 누르면 variableValue가 적용 가능한 기호들을 볼 수 있고 직접 확인할 수 있다.

SF Symbols VariableValue

asset에서 가져오는 이미지에도 variableValue를 설정할 수 있는데, 이미지를 가변으로? 만드는 것을 어떻게 하는지 몰라서 못했다.

그런데 이대로 이미지를 표시하면 크기가 원본 크기로만 나오기 때문에 UIKit에서 contentMode, frame을 설정했던 것 처럼 modifier를 추가해줘야 한다.

Image("tempImage")
	.resizable()
	.frame(width: 50.0, height: 50.0, alignment: .center)
	.aspectRatio(contentMode: .fit)

이미지의 크기를 조정할 땐 .frame, 종횡비 설정은 aspectRatio로 해결할 수 있다.

 

aspectRatio(_:contentMode:) | Apple Developer Documentation

Constrains this view’s dimensions to the aspect ratio of the given size.

developer.apple.com

여기서 resizable을 빼고 사용한다면 적용한 modifier들이 동작하지 않는다. 

이미지 크기를 조정할 때면 resizable을 꼭 빼먹지 말고 사용해야한다.

Image(decorative: "tempImage")
                .renderingMode(.original)
                .resizable()
                .aspectRatio(contentMode: .fit)

asset에서도 설정이 가능하지만 View에도 modifier에 renderingMode를 설정 할 수 있다.

그런데 aspectRatio 이후에 renderingMode나 antialiased를 추가하면 자동완성도 안될 뿐만 아니라 사용자체가 안된다.

이유는 아직 못 찾았지만, 이미지 resizing을 하기전에 설정 할 것을 끝내고 마지막에 resizing을 해야 제대로 동작한다.

 

[SwiftUI] Modifier와 적용순서

modifier(\_:) : Applies a modifier to a view and returns a new view.Apple 공식문서에서는 위와 같이 modifer() (인스턴트메소드)는 view에 modifer를 적용해 새로운 view를 만들고 이 리턴한다고

velog.io

안됐던 이유는 modifier를 적용했을 때 반환하는 타입 때문이였다.

위 링크에서 상세하게 설명하고 있다. 간단하게 요약하자면,,

Text에만 추가 가능한 bold() modifier는 background modifier 뒤에 추가되었을 때 동작하지 않는다. 이유는? background는 View공통 modifier로 View를 리턴한다. bold()는 Text에만 사용가능한 modifier기 때문에 적용이 불가능 한 것.

aspectRatio 역시 View를 반환하고 있어서 Image에서만 사용 가능한 modifier들이 적용이 되지 않는 것이였다.


AsyncImage

IOS 15.0 부터 사용가능

URLSession 인스턴스를 사용해 비동기로 이미지를 받아와 표시해주는 View.

AsyncImage(url: URL?, scale: CGFloat = 1)
AsyncImage(url: URL?) { image in
    image.resizable()
} placeholder: {
    ProgressView()
}

기본적인 사용은 URL만 넣으면 알아서 이미지를 비동기로 가져와 준다. scale은 기본값으로 1.0이 지정되어 있다.

또한 이미지가 Load되었을 때 content 파라미터에 클로저로 전달되기 때문에 이미지에 대한 추가 작업도 가능하고, placeholder 파라미터에 클로저를 사용해 이미지가 띄워지기 전 뷰를 설정 할 수 있다.

content 파라미터가 따로 존재하는 이유가 있다! AsyncImage에 바로 resizing이 불가능 하기 때문... 이미지 크기나 추가적인 수정이 필요할 땐 content 클로저에서 직접 처리해줘야한다.

마치 KingFisher를 사용했을 때 같다. KingFisher를 깊이 사용하진 않았지만, 다른점은 KingFisher에서 사용하던 캐싱모드? 를 설정하는 것이 없다.

728x90
Comments