Todo앱 시리즈 2 - Rx + Alamofire

라무·2023년 8월 9일

TodoApp 시리즈

목록 보기
2/3
post-thumbnail

Rx를 사용할 시 얻을 수 있는 장점

💡 비동기를 사용하기 때문에 데이터를 조금 더 편하게 수정하고 전달, 사용이 가능하다
  • 현재 todoList project에서는 alamofire를 사용해서 api를 처리했기 때문에 RxAlamofire를 사용해서 API를 처리해야 한다

RxSwift로 변경할 수 있는 부분

💡 API와 todoDataList라는 todoData가 들어가는 데이터관련 변수에 대해서 적용이 가능하다

적용한 API정리

  • 할일 목록 불러오기
  • 할일 목록 추가하기
  • 할일 목록 삭제하기
  • 할일 목록 수정하기
  • 선택된 할일 목록 전체 삭제하기

todoData가 들어가는 데이터 관련 변수 정리

  • 할일 목록이 불러와질 경우 todoListData에 데이터가 전부 새롭게 추가된다
  • 할일 목록이 하나 추가될 경우 todoListData에 데이터가 하나 추가된다
  • 할일 목록이 삭제되었을 때도 todoListData에 데이터를 삭제해줘야 한다
  • 할일 목록 수정할 때도 todoListData에 해당하는 데이터를 수정해줘야 한다
  • 선택된 할일 목록 전체 삭제시에도 선택된 할일 목록이 전부 성공적으로 삭제가 됐다면 todoListData에 있는 데이터도 삭제를 해줘야 한다

그 외 비동기 이벤트 처리 정리

  • 하나의 데이터(할일) 수정하기 버튼 클릭시 → 한 셀에 있는 데이터를 의미한다
  • 하나의 데이터(할일) 삭제하기 버튼 클릭시 → 한 셀에 있는 데이터를 의미한다
  • 할일 추가하기 버튼 클릭시(main viewController)
  • 선택된 할일 목록 전체 삭제하기

하면서 어려웠던 점

  1. requestJson으로 데이터를 보내는데 json을 통해서 받아지기는 하는데 decoding이 되지 않았다(해결)

    • JSONDecoder().decode를 써서 데이터를 decode를 하려고 하는데 from: json에서 json의 type이 Data로 변환되지 않아서 계속 디코딩이 되지 않았다

    → 그래서 request를하고 나서 바로 data()를 통해서 Observable 데이터를 만들고

    → 그 데이터를 JSONDecoder를 통해서 decoding을 함

    [🌱SeSAC] Rx복습, RxAlamofire/RxDataSource

  2. 데이터를 수정할 때 수정하기 모달에서 textField에 데이터가 있다면 request를 보내주는 부분에서 rx를 사용할 수 있을 것 같은데,,,

    • 그러니까 todoId.rx.text해서 글자 입력이 완료가 된다면 뭐 RxAlamfire해서 불러오는 것을 할 수 있지 않을까?
  3. todoDataList(table view에서 사용하는 data)를 observable로 만들어서 진행을 해야 한다
    1. 또한 현재 tableview에서 사용하고 있는 section이 하나이므로 dataSource를 굳이 import하지 않고 진행해도 된다
    - tableview에서 사용할 데이터를 observable로 바꾸려고 했는데 어떻게 바꿔야 하는지 모르겠음 + 어떻게 검색해야 방법이 나오는지 모르겠다ㅠ,,,
    - 일단 Observable.just는 한번 Observable을 방출하면 그 상태로 끝나는 함수이다. 하지만 todoListData는 observable이 한번 방출되면 끝나는 것이 아니라 계속해서 Observable을 관찰하고 변경되면 item을 방출해야하기 때문에 관찰 도중에 에러가 발생하거나 방출이 완료가 되더라도 관찰을 계속한다 → relay를 사용해야 한다!
    - 만약에 에러가 나거나 방출이 끝나면 관찰을 멈춰도 되는 Observable을 만들고 싶다면 그냥 subject를 사용하면된다

    → data.count, data.filter등으로 value를 이용해서 접근해야 하므로 behaviorRelay를 사용한다
    
    → behaviorRelay는 마지막 값을 보존하고 초기값이 반드시 필요하다
    
    → relay로 데이터를 변경했으므로 변경되어서 받은 데이터는 임시로 다른 곳에 보관해놨다가 변경이 끝나면 accept를 통해서 이벤트를 보낸 후 데이터를 변경해준다
    
    → 즉, 우리는 평소에 데이터를 append, insert, remove를 통해서 데이터 자체를 빼거나 더해주는 등 데이터를 변경해줬지만 relay는 변경된 데이터를 보내주면 알아서 데이터를 변경해준다

  4. 바닥을 감지했을 때 새로운 페이지를 불러오는 scrollViewDidLoad함수 부분도 rx로 변경할 수 있을 것 같은데 어떻게 변경할까?

    • 원래 scrollViewDidLoad는 UITableViewDelegate에 포함되어있다
      • 정확히 말하면 UITableViewDelegate이 scrollViewDelegate을 가지고 있고 그 scrollViewDelegate에 scrollViewDidLoad가 있다
    • 그러기 위해서는 rx에서 scrollViewDidLoad를 어떻게 불러오는지 알아야 한다
      • 이런것들은 RxCocoa에 다 정의가 되어있다
      • proxy는 delegate을 대신 받는데 사용되는데 UIScrollView+Rx를확인하면 proxy클래스가 UIScrollView와 UIScrollViewDelegate을 대신받아주는 것을 확인 할 수 있다
      • 그럼 이 delegate이 대신해서 event를 받아서 observable로 만들어준다
      • 그러므로 이걸 사용하면 scrollViewDidLoad등을 사용할 수 있다
    • scrollViewDidLoad에서 핵심은 contentOffSet이다 즉, y축의 위치가 어디인지 알아서 y축의 위치가 바닥이라면 데이터를 불러오는 것이기 때문에 contentOffSet이 핵심임
      • rx에서 기존의 delegate을 구현해놔서 우리는 그것들을 사용만 하면 된다
  5. 만약에 이렇게 스크롤이 맨 마지막일때, 즉, 바닥을 봤을때의 여부를 체크해야 하는 것이 여러번 있다면 그에 해당하는 비지니스 로직을 그때마다 여러번 작성을 해줘야한다. 하지만 그렇게 하기 귀찮으니까 UIScrollView일때 접근할 수 있는 로직을 만들어놓으면 그 로직만 호출해서 사용할 수 있다(즉, rx에 커스텀 로직 만들기)

  6. Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored

    • 이런 에러가 발생하면서 _ in을 넣으라고 하는데 무슨 의미일까?
      • 클로저는 암묵적으로 무시할 수 없는 인수에 대해서 반드시 _ 를 넣으라고 하는데 왜,,,?
  7. filter{ $0 == true }.map{ _ in }을 하면 Observable에서 Observer로 왜 바꿀 수 있지?

  8. 그 외에도 현재 api호출이 아닐때에만 api를 호출할 수 있도록 하는 부분도 rx로 변경할 수 있을 것 같은데 어떻게 할지 모르겠다

하면서 궁금했던 점

  1. addTodoBtn.rx.tap.bind{ [weak self] in self?.addTodo()}에서 왜 [weak self] in을 해줘야하는 걸까?

    1. 그걸 안하고 그냥 self.addTodo()를 실행하면 실행이 되지 않는다

    → 순환참조를 막기 위해서이다

  2. Rxswift에서 tableview를 어떻게 사용하는지 궁금해서 봤는데 왜 return 값이 3개나,,?

    • return 값이 세개인것이 아니고 return이 클로져인것이다
      - 즉, source가 configureCell을 반환하고 configureCell이 최종적으로 Disposable을 반환하는 구조로 이루어져있다


profile
ios 개발을 하고있는 라무의 사적인 기술 블로그

0개의 댓글