UIKit에서 IBOutlet, IBAction 사용해보기
·
Study/iOS
천천히 iOS 공부를 해보면서 안드로이드 개발과 다른 점을 찾아보려고 한다. 내가 배운 방법이 유일한 사용법이 아닐 수도 있다는 점을 항상 의식하고 있다. ViewController와 IBOutlet 연결하기특이하게 스토리보드의 오브젝트를ViewController.swift 파일에 추가할 때 직관적인 방법이 있다. 스토리보드에서 Assistant 탭을 오른쪽에 열어두고Control을 누른 채로 드래그하는 것이다.Connection 타입을 Outlet,Type은 Object에 따라 맞춰주면 되는데보통 내가 만든 Object에 따라 자동으로 설정된다. Storage는 사실 아직 어떤 역할인지 모르겠다.(추후에 알게되면 또 주절주절 적어둘 날이 올지도) ViewController에 IBOutlet이 선언되고 ..
asLiveData 알아보기
·
Study/Kotlin
문제점 파악하기asLiveData를 알아보기 전에 지금까지 Flow를 공부하며 어떤 문제점이 있었을까 되짚어보자. 지금까지 공부하며 실행한 Flow는 전부 앱의 생명주기(Lifecycle)을 고려하지 않고 만들어졌다. 그렇다보니 API를 사용해 목록을 가져와 몇초마다 갱신하는 작업을 무한히 반복하고 있었다면앱이 백그라운드에 있어도 계속 해당 작업을 수행하고 있을 것이다. 앱의 생명주기를 확인하고 Flow를 적절하게 종료하는 과정이 필요한 것이다. 수동으로 종료하기라이브러리에서 생명주기를 감지해서 종료할 수 있는 기능이 없다면 어떻게 했을까? Flow를 시작하고 종료하는 함수를 만들어액티비티의 onStart, onStop에서 호출하면 될 것이다. 여기서도 문제점이 있다. 먼저, Flow를 제어하기 위해 많..
Intermediate operator 알아보기
·
Study/Kotlin
이번에는 우리가 Flow를 통해 특정 리스트를 업데이트할 때,초기 로딩 상태를 보여주길 원한다는 가정을 해보자. 심지어 이 리스트가 네트워크 작업으로 인해 얼마나 지연될지 모르기 때문에언제 업데이트가 끝날지 모른다면 더욱이 로딩 중이라는 표시를 해주는 것이 마땅하다. 이를 구현하기 전에 Intermediate operator를 먼저 알아보려 한다. Onstart이 함수로는 collect가 시작될 때 실행되는 동작을 정의할 수 있다. 함수로 정의한 동작의 실행은 다시 강조하면 첫번째값이 방출될 때가 아닌 collect가 시작될 때이다. OnCompletion이 함수는 Flow가 완료된 후 실행되는 동작을 정의할 수 있다. 여기서 Flow가 완료되는 방식은 두가지가 있다.모든 값이 정상적으로 방출된 경우예외..
launchIn 살펴보기
·
Study/Kotlin
이번에는 저번에 작성했던 기본적인 Terminal operator에 이어 launchIn을 소개해보려 한다. launchIn 문서보기이 함수는 정의부터 조금 특이하다. 다른 Terminal operator는 모두 suspend 함수였는데 이 함수는 일반 함수이다. 그리고 CoroutineScope를 전달하면 내부적으로 launch와 collect까지 실행한다는 사실을 볼 수 있다. 소스 코드를 확인해보면 실제로 그렇게 생겼다. 그렇다면 코드로 어떻게 실행하는 지 확인해보자. 예제 살펴보기fun main() { val flow = flow { println("Emit first value") emit(1) delay(100) prin..
Flow의 기본적인 최종 연산자 알아보기(Terminal operator)
·
Study/Kotlin
이전 글에서는 단순히 Flow를 만들어보았다. 이제 Flow에서 방출하는 값을 어떻게 가져올 수 있는지 그 방법에 대해 살펴보자. Flow 만들어보기다짜고짜 Flow를 만들어본다는 게 무슨 의미일까? fun main() { val flow = flow { println("Emit first value") emit(1) delay(100) println("Emit second value") emit(2) }}이렇게 Flow를 만들면 과연 나는 이 print문을 콘솔에서 확인할 수 있을까? 정답은 '아니다'이다. 간단히 생각해봤을때 이미 delay, emit 함수는 suspend function으로 코루틴 내부에서 실행되어..
Flow 만들어보기(feat. Flow builder)
·
Study/Kotlin
이번 글에서는 Flow builder를 사용해 Flow를 만들어본다. flowOf 사용하기첫번째는 flowOf라는 함수를 사용해 Flow를 생성해보겠다. val flow1 = flowOf()val flow2 = flowOf(1, 2, 3)흔히 MutableList를 만드는 방식과 매우 유사하다. 어떤 값을 넣지 않으면 제네릭으로 타입을 명시해주어야 하고,값을 넣게 된다면 타입을 명시하지 않아도 컴파일러가 자동으로 감지한다. asFlow 사용하기두번째로는 asFlow라는 함수를 사용하는 방법이다. listOf("a", "b", "c").asFlow()asFlow 함수는 Iterable, Sequence 등의 확장 함수로 선언되어 있다. flow 람다 사용하기마지막으로는 flow 람다를 사용하는 방법이다..
Flow 개념 살펴보기
·
Study/Kotlin
이번 예시는 팩토리얼 계산 함수를 사용할 예정이다. 일반적 함수 구현fun main() { val result = calculateFactorial(5) println("result: $result")}private fun calculateFactorial(num: Int): BigInteger { var factorial = BigInteger.ONE for (i in 1 .. num) { Thread.sleep(10) factorial = factorial.multiply(BigInteger.valueOf(i.toLong())) } return factorial}이렇게 작성된 함수에서는 계산 결과만 받을 수 있다. 그렇다면 계산 과정은 어떻게 ..
예외 처리에서 Lifecycle 고려하기
·
Study/Kotlin
이전 글에서 짧게 viewModelScope에서의 예외 처리 예시를 살펴보았다. 이번에는 이전 글을 바탕으로 발생할 수 있는 Lifecycle 관련 예외 처리 시나리오를 세워 본다. 문제가 될만한 상황 검토하기viewModelScope.launch { supervisorScope { val deferred = async { throw RuntimeException() } val result = try { deferred.await() } catch (e: Exception) { println(e) } // Some Ui updates(Vulnerable point) }}이 코드에서 가장 위험한 부분은 result 변수 이후에 viewModelSco..
viewModelScope 예외 처리 예시
·
Study/Kotlin
이전 글에서 coroutineScope와 supervisorScope 함수로 예외 처리하는 방법을 살펴보았다. 이제는 실전인 viewModelScope에서 어떻게 예외 처리를 하면 좋을까에 관한 내용이다. 문제 상황 살펴보기viewModelScope.launch { val deferred = async { throw RuntimeException() } val result = try { deferred.await() } catch (e: Exception) { println(e) }}이런 예시가 있다고 해보자. 내가 처음 예측했던 결과는 정상적으로 catch 문에서 예외를 잡을 수 있을 것이라 생각했다. 하지만, 결과는 앱 크래시로 이어졌다. 문제 상황 ..
supervisorScope 함수를 사용한 예외 처리
·
Study/Kotlin
이번에는 저번 글의 coroutineScope 함수와 달리 supervisorScope를 사용해보는 시간이다. 바로 예제 코드부터 보자. supervisorScope를 사용한 예외 처리 시도하기fun main() = runBlocking { try { supervisorScope { launch { throw RuntimeException() } } } catch(e: Exception) { println("Caught: $e") }}먼저 저번 글에서 coroutineScope를 supervisorScope로 대치해보았다. 실행 결과를 예측해보자. launch 내부에서 발생한 예외는 처리되지 않고 앱 크래시가 발생할 것이다. 왜..