본문 바로가기

iOS

(11)
SwiftUI + TCA 튜토리얼 4 - Scope 하나의 스토어로 메인,서브 스토어 간 State, Action 을 연결지을 수 있는 Scope 에 대해 학습합니다. 우선 CounterFeature 를 CounterReducer 라는 이름으로 변경해서 사용했으며,메인 탭에서 사용할 CounterAppReducer 를 생성합니다. TabView 를 통해 각 Reducer 를 분리해서 사용할 수 있게끔 하려고 합니다.State 구조체에는 각각의 CounterReducer 의 State 를 인스턴스 프로퍼티로 갖고,Action 열거형도 마찬가지로 각각의 CounterReducer 의 Action 을 케이스로 갖습니다. 자, 그럼 CounterAppReducer 의 body 프로퍼티에는 Scope 를 사용합니다. 스코프는 KeyPath 를 사용하여 각 Stat..
SwiftUI + TCA 튜토리얼 3 - Timer + Cancellable 이번엔 다른 비동기 작업인 타이머를 사용합니다. Tiemr Button 을 생성합니다.isTimerRunning 상태에 따라 Text 가 변경되고, 탭하면 send 를 진행합니다. isTimerRunning, timerTick 추가 Composable Architecture의 강력한 기능 중 하나인 "효과 취소(effect cancellation)"를 활용할 수 있습니다. cancellable(id:cancelInFlight:) 메소드를 사용하여 어떤 효과도 취소 가능하게 표시할 수 있으며,ID를 제공함으로써 이를 수행할 수 있고, 나중에 cancel(id:)를 사용하여 해당 효과를 취소할 수 있습니다. Cancellable 이라는 것을 사용하기 위해 새로운 열거형을 생성합니다. 조건문으로 isTimer..
SwiftUI + TCA 튜토리얼 2 - Network 이번엔 네트워크 통신을 해봅시다. 누르면 통신작업을 진행할 FactButton 을 놓고,if 구문으로 isLoading 에 따른 ProgreeView 가 보이거나 Text 가 보이게끔 뷰를 놓았습니다. State: fact, isLoading 프로퍼티를 생성합니다.Action: factButtonTapped, factResponse 케이스를 생성합니다.기존 tapped case 도 잘 써주세요 factButtonTapped Action 을 감지했다면, .run 을 통해 네트워크 호출을 진행합니다.try await 구문으로 data 를 가져오고, 디코딩을 진행합니다. 이때 중요한 지점이 결과 값을 바로 state.fact 에 접근해서 변경할 수 없다는 점이며, 사진을 참고해주시면 되겠습니다.그렇기에 awa..
SwiftUI + TCA 튜토리얼 1 - Feature + View SwiftUI + MVVM Input/Output 패턴을 사용해서 학습하다가 Apple 이 자체적으로 뷰에게 View + ViewModel 의 기능을 할 수 있도록 만들어주었기에 코드를 작성하면 작성할수록 뷰모델의 목적에 맞지 않는 점점 이상한 코드들이 쌓이기 시작해서 TCA 를 학습하고자 합니다. 우선 모든 것이 처음이니 저만의 단위대로 구조를 잘라서 작성해보겠습니다. 1. FeatureReducer Protocol 을 채택하는 Feature 라는 하나의 단위로State, Action, body 를 묶어서 사용하고 있습니다. 2. ViewFeature 라는 단위를 제네릭으로 갖는 store 를 프로퍼티로 가집니다.store 에 접근하여 send 로 액션을 방출할 수 있습니다. 프리뷰를 사용하여 View..
단락평가(short-Circuit Evaluation) swift 는 &&(and), ||(or) 연산 시 단락평가라는 것을 사용한다고 한다. 이게 뭔가 찾아봤더니,앞에서 이미 연산이 결정됐다면 뒤에 있는 연산은 하지 않고 넘어간다는 것이다.아래 예시를 확인해보자. AND 와 OR 는 대부분 알 것이라고 생각하고 넘기고,temp 메서드와 3번째 조건문을 확인해보자 temp 메서드를 실행하면 분명히 number 를 +1 하고, 출력하기로 되어있는데조건문에서 || 를 사용하기에 하나라도 true 가 되는 순간"앞에서 이미 연산이 결정됐기에 뒤에 있는 메서드는 모르는 일이 되었다"이렇듯 연산이 이미 결정이 됐다면 이후의 연산을 안하기에 효율적인 논리 연산을 진행하지만,혹여나 끝까지 연산이 진행되어야 한다면 어딘가에 프로퍼티로 값을 담아놓고, 그 값으로 연산을 진행..
복잡한 ViewController 에서의 VIewDidLoad or init 순서 내 앱은 팔로워 or 팔로잉을 탭 했을 때, 해당 탭에 맞는 화면이 보이게끔 화면전환이 들어가야했다. viewMode 열거형을 통해 값을 넘겨서 해당 탭에 맞는 화면이 보이게끔 구현했는데,이 때 이것저것 실험하면서 알게된 부분을 작성하고자 한다. 컨테이너뷰로 자식VC 을 넣어서 사용하는 경우,ViewDIdLoad 는 가장 내부에 있는 자식이 먼저 실행된다. 내 앱은 FollowVC → FollowTabVC (Tabman 사용) → FollowerVC or FollwingVC 형태로 되어있는 형태임 FollowerVC 가 먼저 실행되는 것을 확인할 수 있다.(사실 2번은 자식이라기 보다는 FollowVC 내부 인스턴스 프로퍼티입니다) 근데!모든 print 를 init 구문에 넣어서 순서를 확인해보면,2 →..
서버에서 주는 에러메세지도 디코딩으로 받아보기 성공 케이스가 아닌 실패케이스에서 주는 에러메세지도 디코딩해서 편하게 사용하기 위해 생성했다. 우선 서버에서 주는 에러메세지가 있을 수도 없을 수도 있는데 지금의 서버 응답은 이런 형태로 준다. 우선 responseString 으로 콜했을 때 받아오는 response 를 뜯어보았다. 서버에서 주는 숨겨야할 값들이 존재했기에 data 부분을 캡쳐해왔다. 세상에 data 메서드 .utf8 로 데이터 타입으로 변경해버리는 순간 출력 결과는 용량이 나옴 위에 있는 response.data 와 결과가 같은 dataType 이다. 그렇다는 말은 응답 값을 utf 타입으로 변환해서 JSONDecoder 의 data 부분에 그대로 넣어버리면 디코딩을 할 수 있다는 것이다. 자 그럼 에러메세지도 뽑아내보자. respon..
Kingfisher - Error Handling kingfisher 의 실패 케이스를 가져와봅시다 kingfisherError 는 열거형으로 이루어져 있고, case 에 responseError 라는 응답에러 및 이유가 담겨져 있는 곳이 있다. 음 저는 서버에서 보내주는 statusCode 를 사용하려고 하는데 여기서 사용하는 코드는 필요없으니 invalidHTTPStatusCode 쪽으로 더 깊게 들어가봅시다. 여기서 HTTPURLResponse 라는 녀석을 찾을 수 있네요 HTTPURLResponse 는 애플이 만든 클래스입니다. 드디어 찾았습니다,, 여기서 상태코드를 가져오면 되겠네요 자 이제 가져와봅시다 실제로 사용할때는 이렇게까지 작성해놔야 . 찍었을때 케이스들을 가져올 수 있네요 responseError 를 찾아주시고 케이스에는 reason..
Custom Modal · Alert 개인프로젝트를 진행했을 때, 애플의 기본 Modal, Alert 앱 컨셉에 맞지 않다고 판단하여, 사용자의 UI/UX 경험을 생각해 커스텀 Modal · Alert 을 생성했습니다. 1. UIPresentationController CustomPresentationController: UIPresentationController 상속받은 클래스 생성 frameOfPresentedViewInContainerView 메서드에서 containerView, PresentedView 의 사이즈와 위치를 CustomModalPresentationStyle 열거형 case 로 분기처리하여 지정 containerView, presentedView 는 무엇인가? containerView containerView는 현재 ..
Background Timer 개인 프로젝트를 진행하면서 발생했던 Background Timer 구현 과정입니다. 타이머 기능을 구현하기 위해 애플리케이션의 생명주기를 관리하고, 사용자와의 상호작용과 같은 다양한 이벤트를 처리하는 Run Loop 에 대한 개념을 익힌 뒤 메인 스레드의 RunLoop에 타이머 추가하고 삭제하는 scheduledTimer, invalidate 메서드를 이용하여 타이머를 사용했습니다. 기본적인 타이머의 시작, 중단, 리셋 기능은 쉽게 구현할 수 있었지만, 사용자가 E-Book 을 읽거나, 다른 기능을 이용하거나, 앱이 백그라운드로 이동하는 등 타이머를 중단하지 않는 한 타이머의 시간이 흐르도록 다양한 상황을 고려하고 대응해야 했습니다. 저는 보통 처음 기능을 구현할 때 많은 정보를 찾아보고 이해한 뒤, 종..