# Color
SwiftUI
에서는 컬러 구조체를 제공한다. 시스템 컬러들은 다크모드에 따라 자동으로 최적화된다. 같은 컬러라고 하더라도 각 모드에 최적화된 시스템 컬러를 제공하기 때문에 세부 RGB는 다르게 설정되어 있다.
또한 컬러는 View
프로토콜을 채택하기 때문에 뷰처럼 프레임 지정 등의 레이아웃 설정이 가능하다.
struct Color_Tutorials: View {
var body: some View {
VStack {
Color.blue
Color.gray
}
}
}
당연히 컬러를 직접 생성할 수 있다.
Color(red: 70 / 255, green: 80 / 255, blue: 12 / 255, opacity: 0.5)
위와 같이 명시적인 컬러 지정을 한 경우 다크모드 여부에 상관없이 고정된 컬러를 표시한다.
번들의 Assets
파일에 다크 Appearance
로 생성된 컬러셋을 직접 정의하면 다크모드 여부에 따라 자동으로 컬러 변경이 이루어진다. 코드 단계에서 별도의 분기처리가 필요없어진다. 이러한 컬러를 네임드 컬러라고 한다.
네임드 컬러에 오타가 발생하지 않도록 주의하자.
Color("ColorSet")
// Color(name: String, bundle: Bundle)
# Materials
머터리얼은 불투명도를 나타낸다. 투명한 순서대로 차례대로 .ultraThinMaterial
, thinMaterial
, regularMaterial
, thickMaterial
, ultraThickMaterial
로 이어진다.
Text("Lorem Ipsum")
.frame(maxWidth: .infinity)
.frame(height: 80)
.background(.ultraThickMaterial)
# Images
이미지에는 labeled image
와 unlabeled image
가 있다. 보이스오버로 접근성 지원을 하는 경우 앱 내에서 중요하게 사용되는 이미지에는 labeled image
를 사용하고 그렇지 않은 단순 장식용 이미지에는 unlabeled image
를 사용한다. 보이스오버는 레이블 이미지만 인식하여 읽어준다.
labeled image
의 경우 Image
생성자 파라미터에 label
가 포함된 함수를 호출한다. unlabeled image
의 경우에는 decorative
파라미터가 붙어있는 함수를 호출한다.
이미지 사이즈를 조정해야 하는 경우 frame
모디파이어를 호출하면 되는데 프레임에 대한 변경만 이루어지고 이미지 자체 사이즈는 변경되지 않는다.
resizable
모디파이어를 호출하면 이미지 종횡비와 상관없이 프레임에 전달한 너비 높이값이 맞추게 된다.
이때 scaledToFill
이나 scaledToFit
모디파이어를 호출하면 종횡비에 맞춰 프레임 내에서 이미지 사이즈가 재조정된다.
scaledToFit
은 종횡비를 맞추는 과정에서 프레임을 벗어나지 않는 것을 우선순위로 하고, scaledToFill
은 프레임을 벗어나도 종횡비를 맞추는 것을 우선순위로 한다.
clipped
모디파이어로 프레임을 벗어나는 컨텐츠를 자르도록 할 수 있다. interpolation
모디파이어는 컨텐츠 품질을 지정할 수 있다.
또한 이미지는 renderingMode
모디파이어를 사용할 수 있다. 백그라운드가 없는 이미지에 템플릿 속성을 적용하면 컬러를 직접 적용할 수 있다.
Image("flower")
.resizable()
.renderingMode(.template)
.foregroundStyle(.yellow)
.frame(width:200, height: 200)
# SFSymbols
심볼 이미지는 폰트처럼 font
모디파이어로 사이즈를 지정할 수 있다. SF 심볼 이미지에 imageScale
모디파이어를 적용하면 텍스트와 어울리게 이미지 스케일을 조정할 수 있다.
Image(systemName: "star")
.font(.largeTitle)
.imageScale(.large)
심볼 이미지로 스케일을 조정하면 다이나믹 타입에 따라 크기가 자동으로 조정된다는 장점도 있다. 또한 심볼이미지는 벡터 기반의 이미지라 깨짐도 없다.
템플릿 이미지로 사용하는 경우 일반 이미지보다 자유도가 높다. SF 3.0 버전 이후부터 여러 색들을 지원한다.
Image(systemName: "cloud.sun.rain")
.font(.largeTitle)
.imageScale(.large)
.symbolRenderingMode(.palette) // 렌더링 모드 지정
.foregroundStyle(.gray, .yellow, .blue) // 컬러 각각 지정
# AsyncImage
AsyncImage
는 로컬 이미지를 사용하지 않고 서버로부터 이미지를 직접 다운로드 할때 비동기 처리를 자동으로 도와주는 뷰이다. 메인스레드 블록이 없으므로 메인스레드 처리는 불필요하다.
URL 객체를 파라미터에 전달하고, content
클로저에서 Image
파라미터에 뷰를 정의하면 된다. 클로저 파라미터가 Image
뷰이며 AsyncImage
는 이미지 다운로드를 도와주는 도구일 뿐이다.
placeholder
클로저에서 다운로드 과정에 표시할 뷰를 구현하면 된다.
AsyncImage(url: url) { image in
image.resizable()
.scaledToFit()
} placeholder: {
ProgressView()
}
다운로드 실패에 대한 처리를 하고싶은 경우 AsyncImagePhase
타입을 파라미터로 받는 content
클로저를 구현하면 된다. phase
를 switch문으로 분기처리하여 failure
케이스에서 다운로드 실패에 대한 뷰를 정의하면 된다.
AsyncImage(url: url) { phase in
switch phase {
case .success(let image):
image.resizable()
.scaledToFit()
case .failure(_):
Label("이미지 다운로드 실패", systemImage: "x.circle")
case .empty:
ProgressView()
@unknown default:
fatalError()
}
}