728x90

SwiftUI 53

TimelineView

안녕하세요. 이번에는 TimelineView에 대해 간단하게 알아볼게요. 스케줄에 따라 업데이트가 되는 뷰. 즉, TimelineView는 일정한 주기에 따라서 뷰가 업데이트되는 컨테이너 뷰입니다. 아래처럼 1초마다 뷰가 다시 그려지도록 구현할 수도 있죠. TimelineView의 클로저는 context라는 파라미터가 있는데, context는 업데이트를 트리거하는 스케쥴러에 대한 시간(date)을 가지고 있습니다. 그래서 아래처럼 context.date를 활용할 수도 있어요. context는 cadence라는 프로퍼티도 가지고 있어요. cadence는 TimelineView가 업데이트되는 속도를 나타냅니다. enum 타입으로 아래 같은 3가지 타입을 가지고 있어요. (실시간 업데이트, 약 1초마다 업데이..

SwiftUI 2022.06.17

trim

안녕하세요. 이번에는 trim 수식어에 대해 알아볼게요. trim 수식어는 아래처럼 생겼어요. trim 수식어를 사용하면 Shape 뷰의 path를 일정 부분 잘라서 반환해줍니다. 정확하게는 Shape의 전체 경로를 1이라고 봤을 때, 1 x startFraction 지점부터 1 x endFraction 지점까지의 Shape을 반환해주는 것이에요. (당연히 startFraction과 endFraction은 0 ~ 1 사이의 값을 가집니다) 만약 시작 지점이 끝나는 지점보다 뒤에 있을 경우(즉, startFraction >= endFraction인 경우)에는 아무것도 출력되지 않습니다. 예를 들어서, 아래 같은 Shape이 있다고 했을 때 Path { path in path.addLines([ .init(..

SwiftUI 2022.06.06

PreferenceKey

안녕하세요. 이번에는 SwiftUI의 PreferenceKey에 대해 알아볼게요. ## PreferenceKey A view with multiple children automatically combines its values for a given preference into a single value visible to its ancestors. PreferenceKey는 자식 뷰에서 상위 뷰 계층으로 데이터를 전달하고 싶을 때 사용합니다. 즉, 하위에서 값을 수정하고 이를 상위 계층에 알려줘야 할 때 사용되는 게 PreferenceKey입니다. 하위 -> 상위 계층으로 데이터를 전달하는 개념도 생각보다 간단해요. 1. PreferenceKey 프로토콜을 준수한 Key를 하나 만들고, 2. 상위 뷰에서..

SwiftUI 2022.05.30

Environment

안녕하세요. 이번에는 Environment에 대해 알아볼게요. ## Environment Environment property wrapper를 사용하면 SwiftUI 뷰의 환경에 저장된 값을 읽을 수 있어요. Environment 프로퍼티를 선언할 때 아래처럼 EnvironmentValues key path를 사용해서 어떤 값을 읽을지 결정합니다. 뷰 환경 또는 앱 환경에 따라 다른 뷰를 그리고 싶은 경우 아래처럼 조건문을 달아줄 수도 있어요. 만약 Environment 값이 변경이 되면, SwiftUI가 알아서 이와 관련된 모든 뷰를 업데이트해주니 크게 걱정할 필요 없습니다. 그럼 Environment 프로퍼티는 언제 사용하면 좋을까요?? 뭐... 여러 관점이 있겠지만, 애플은 앱 전체에 값을 배포..

SwiftUI 2022.05.29

SwiftUI에서 ViewController를?

안녕하세요. SwiftUI를 써보셨나요? SwiftUI를 쓰다 보면... UIKit에서 자주 사용하던 MVC 패턴을 사용하고 싶다는 생각이 들 때가 있습니다. 물론 SwiftUI에서 MVC 패턴을 사용 못한다는 것은 아니에요. 그런데 막상 SwiftUI에서 MVC 패턴을?? 어떻게???라는 의문점이 들더라구요. 그래서 이번 글에서는 SwiftUI에서 MVVM 패턴에 얽매이지 않고 ViewController라는 개념을 적용해보는 시간을 가져볼게요. # 1. SwiftUI에서의 ViewModel 이런 화면을 ViewModel을 사용해서 만든다고 가정해볼게요. (cow 모듈은 여기를 참고해주세요!) import SwiftUI import cows struct ContentView: View { var body..

SwiftUI 2022.05.11

복잡한 Navigation Flow 처리 (feat. Combine)

안녕하세요. 이번에는 SwiftUI에서 복잡한 Navigation Flow를 처리하기 좋은 방법(구조?)에 대해 소개한 글이 있어서, 아래 글을 토대로 공부해볼게요. - https://betterprogramming.pub/flow-navigation-with-swiftui-revisited-791f89421923 Flow Navigation With SwiftUI (Revisited) How to implement navigation effectively in your code bases betterprogramming.pub 전체 코드는 이곳을 참고해주세요! # 1. Navigation Flow를 처리할 때 고려해야 할 규칙들 아름다운 구조와 코드를 만들기 위해서 몇 가지 고려해주면 좋습니다. [규칙..

SwiftUI 2022.05.10

MotionScape

안녕하세요. 이번에는 MotionScape라는 앱에 대해서 소개해보려고 합니다. SwiftUI에는 여러 가지 애니메이션 옵션이 있습니다. easnIn(duration:) 같은 수식어는 워낙 명확하다 보니... 파라미터가 무엇을 의미하는지 바로 알 수 있고, 그에 따른 기대 동작도 어느 정도 예상이 가능한데요, interpolationSpring(mass:stiffnetss:damping:initialVelocity:) 같은 수식어는 파라미터가 어떤 설정인지 살펴봐야하고, 기대 동작이 쉽게 예상되지 않더라구요... (저만 그런가요...;;; 🥺 ) 애니메이션 파라미터에 어떤 값을 넣냐에 따라서 간단한 샘플 애니메이션을 봤으면... 했는데 마침 그런 앱이 출시되었습니다. MotionScape라는 앱이에요! ..

SwiftUI 2022.05.06

Dismiss Presented View

안녕하세요. Cancel을 누르면 modal sheet가 닫히는 이런 화면 많이 보셨죠?? 기존에는 presentationMode를 사용해서 presented 되어 있는 뷰를 닫았는데, iOS 15부터는 dismiss라는 것을 사용하도록 바뀌었어요. 그래서 이번에는 iOS 14 이하와 iOS 15 이상에서 화면에 띄워져 있는 뷰를 dismiss 시키는 방법에 대해 알아볼게요. ## 1. PresentationMode (iOS 14 이하) 뷰를 화면에 출력할 때는 보통 아래처럼 sheet 수식어나 fullScreenCover 수식어를 사용합니다. struct ContentView: View { @State private var isShowingCart = false var body: some View {..

SwiftUI 2022.04.25

Custom Adaptive StackView (feat. ViewBuilder)

안녕하세요. 이번에는 SwiftUI에서 레이아웃에 따라 뷰가 재배치되도록 사용성을 고려한 간단한 적응형 Stack 뷰를 만들어보는 시간을 가져볼게요. 이번 글에서는 horizontalSizeClass와 dynamicTypeSize를 사용하니, 잘 모르시면 아래 글을 먼저 읽어보시는 것을 추천드려요. - horizontalSizeClass, dynamicTypeSize horizontalSizeClass, dynamicTypeSize 안녕하세요. 이번에는 SwiftUI EnvironmentValues 중 horizontalSizeClass 프로퍼티와 dynamicTypeSize 프로퍼티에 대해 알아볼게요. # 1. horizontalSizeClass 끝에 Class라는 이름이 붙긴 했지만, 이 친구는 프...

SwiftUI 2022.04.17

horizontalSizeClass, dynamicTypeSize

안녕하세요. 이번에는 SwiftUI EnvironmentValues 중 horizontalSizeClass 프로퍼티와 dynamicTypeSize 프로퍼티에 대해 알아볼게요. # 1. horizontalSizeClass 끝에 Class라는 이름이 붙긴 했지만, 이 친구는 프로퍼티입니다. Environment property wrapper로 아래처럼 선언해서 사용할 수 있구요 horizontalSizeClass에는 enum 타입인 UserInterfaceSizeClass 값이 설정되며 아래의 값 중 하나를 가집니다. 쉽게 생각해서 compact = 작은 화면, regular = 큰 화면이라고 보면 될 것 같아요ㅎㅎ "그래서 이 값은 어떻게 결정되는데???" "SwiftUI가 알아서!!!" SwiftUI가 ..

SwiftUI 2022.04.17