-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[iOS][Neo & JeJe] MainUI and NetworkRequest #8
[iOS][Neo & JeJe] MainUI and NetworkRequest #8
Conversation
Feat 1, 2 (feat-1-Initial_UI) and (feat-2-side-dish_model)
EndPoint Merge
Feat-4: Side Dish Data Source
Update: print() 제거
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
중요한 개념에 대한 인지가 부족한것 같습니다.
클로저의 캡쳐링에 관한 공부를 해서 꼭 짚고 넘어가시기 바랍니다.
연관 키워드로는 weak, strong, unowned가 있습니다.
static func createDI() -> SideDishViewModel { | ||
let networkManage = NetworkManager() | ||
let useCase = SideDishUseCase(networkManager: networkManage) | ||
let viewModel = SideDishViewModel(sideDishUseCase: useCase) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이건 DI라기 보다 생성자들을 모아놓은 느낌이네요.
} | ||
} | ||
|
||
enum Path: CaseIterable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Path라는 이름이 어색한거 같습니다.
|
||
static func execute(imageURLString: String) -> AnyPublisher<Data, Never> { | ||
guard let safeURL = URL(string: imageURLString) else { | ||
return Just(Data()).eraseToAnyPublisher() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL이 없을때 임의의 Data를 보내는건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL이 없을때는 빈 데이터를 내보내도록 했습니다!
return URLSession.shared.dataTaskPublisher(for: safeURL) | ||
.map({$0.data}) | ||
.catch({ _ in | ||
return Just(Data()).eraseToAnyPublisher() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도 catch에서 기본 생성자를 사용하는데 어떤 정책을 원한건지 궁금하네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미지를 불러오지 못한것에 대한 처리를 빈 데이터를 줌으로서 화면에 이미지가 보여지지 않게 하려고 이렇게 작성을 했습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미지가 보이지 않기위한 정책으로는 빈 데이터를 주는것보다는 nil이나 객체 내에서 hidden등을 가져갈 수 있게 하는 등의 정책이 더 나아보입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 알겠습니다!
func execute(path: Path) -> AnyPublisher<SideDishes, NetworkError> | ||
} | ||
|
||
class SideDishUseCase: SideDishProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SideDish의 UseCase가 excute라는 이름의 함수로만 진행되다보니 어떤 역할을 하는앤지 잘 모르겠어요. 어떻게 관리하면 좋을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좀 더 명확하게 함수명을 바꾸면 좋을거 같습니다
import UIKit | ||
|
||
enum Alert { | ||
static func controller(title: String) -> UIAlertController { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런식의 factory를 만드는거 좋네요. Factory라는 이름을 사용했으니 팁을 드리면 보통 팩토리 함수는 make나 create로 많이 사용됩니다.
} | ||
|
||
func setImage(itemURLString: String) { | ||
ImageUseCase.execute(imageURLString: itemURLString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Image의 UseCase는 무엇일까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cell의 이미지 네트워크 요청을 UseCase를 만들어 처리한 것인데 처리 방법에 대해 고민이 많습니다..ㅠ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ImageLoader 같은 도우미를 만드는것도 괜찮을거 같고, excute라는 함수명 대신 download등의 이름으로 바꾸기만 해도 덜 혼동될것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아아 네이밍이 좀더 명확한게 좋겠군요
private func hideView<T : UIView>(UI : T) { | ||
UI.isHidden = true | ||
} | ||
private func showView<T : UIView>(UI : T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수의 argument label은 보통 소문자로 시작합니다. 여기에선 소문자 ui
혹은 view
를 사용하던가 _
를 활용하여 parameter name을 없애는게 더 좋을 것 같네요
|
||
class SideDishViewController: UIViewController { | ||
|
||
@IBOutlet weak var SideDishCollectionView: UICollectionView! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로퍼티는 소문자로 시작하는게 일반적인 규칙입니다.
고민거리를 답변 안했었군요. |
제가 아직 동적으로 하는 것에 대해 못 찾았던 거 같습니다 좀 더 찾아보고 적용해보도록 하겠습니다! DIContainer의 목표는 IOC Container처럼 한 곳에서 의존성을 관리하고 싶은 마음에 작성했었습니다…. ㅎㅎ 혹시 구조적인 부분에서 아쉽거나, 부족한 점도 피드백 해주실 수 있을까요?? |
TableView와 기본 뼈대가 되는 Cell을 Storyboard에 추가
label 업데이트 함수 작성. 후에 수정 필요
테이블 뷰와 delegate 연결 커스텀 헤더 지정
Feature/메인 화면 UI 구성 (#8)
headerView의 백그라운드색 지정, init함수 수정
* [#1] init: 🎉 개발 환경 구축 * [#3] feat: ✨ Header 만들기 * [#5] feat: ✨ BestTab UI 구현 - BestTab UI - 상수 파일 - const.js - 재사용 컴포넌트 - Label.jsx - ItemCard.jsx * [#7] feat: ✨ Slide UI 구현 - App.jsx - SlideContainer import - BestItem.jsx - 삭제 (미사용) - BestItems.jsx - ItemCard prop 추가 - BestTab.jsx - 스타일 수정 - SlideContainer.jsx - UI 구현 - SlideItems.jsx - UI 구현 - SlideArrowBtn.jsx - UI 구현 - ItemCard.jsx - 스타일 수정 - prop 추가 - Label.jsx - prop 추가 - 기본 값 추가 * [#8] feat: ✨ ShowMoreBtn UI 구현 - App.js - ShowMoreBtn import - ShowMoreBtn.jsx - UI 구현 * [#10] feat: ✨ Header Dropdown 구현 - App.js - Header 경로 수정 - Header.jsx - 경로 변경 - HeaderLeft & Right 분리 - HeaderLeft.jsx - 컴포넌트화 - Navigations 컴포넌트화 - HeaderRight.jsx - 컴포넌트화 - Navigations.jsx - 컴포넌트화 - Dropdown 구현 * [#13] feat: ✨ API에 fetch 요청 로직 구현 * [#13] feat: ✨ API 요청, 베스트 기능구현 - BestItems.jsx - API 데이터 동기화 - BestTab.jsx - useState, useEffect, API 요청 - BestTabContainer.jsx - API 데이터 동기화 - BestTabNavigator.jsx - API 데이터 동기화 - ItemCard.jsx - prop 변경 - Label.jsx - COLOR변수 추가 * [#15] feat: ✨ 상세 modal 페이지 UI 구현 - App.js - PopUpContainer import - PopUpContainer.jsx - UI 구현 - PopUpImages.jsx - UI 구현 - PopUpInformations.jsx - UI 구현 Co-authored-by: kowoohyuk <kowoohyuk91@gmail.com>
앱 설계에 정답은 없습니다. 팀 혹은 개인의 전략이기 때문이죠. |
- 응답을 위한 DTO 객체 간단 추가 issue: #8
- 임베디드를 사용해 item 필드를 간략화 issue: #8
- 추가 되지 않았던 필드를 iOS와 합의하에 추가 issue: #8
- Item 객체에서 ItemDetail 객체를 얻을 수 있습니다. issue: #8
- Item에서 ItemSummary를 가져올 수 있습니다. issue: #8
- 모든 파일에 자동 포매팅 적용 issue: #8
* [#1] init: 🎉 개발 환경 구축 * [#3] feat: ✨ Header 만들기 * [#5] feat: ✨ BestTab UI 구현 - BestTab UI - 상수 파일 - const.js - 재사용 컴포넌트 - Label.jsx - ItemCard.jsx * [#7] feat: ✨ Slide UI 구현 - App.jsx - SlideContainer import - BestItem.jsx - 삭제 (미사용) - BestItems.jsx - ItemCard prop 추가 - BestTab.jsx - 스타일 수정 - SlideContainer.jsx - UI 구현 - SlideItems.jsx - UI 구현 - SlideArrowBtn.jsx - UI 구현 - ItemCard.jsx - 스타일 수정 - prop 추가 - Label.jsx - prop 추가 - 기본 값 추가 * [#8] feat: ✨ ShowMoreBtn UI 구현 - App.js - ShowMoreBtn import - ShowMoreBtn.jsx - UI 구현 * [#10] feat: ✨ Header Dropdown 구현 - App.js - Header 경로 수정 - Header.jsx - 경로 변경 - HeaderLeft & Right 분리 - HeaderLeft.jsx - 컴포넌트화 - Navigations 컴포넌트화 - HeaderRight.jsx - 컴포넌트화 - Navigations.jsx - 컴포넌트화 - Dropdown 구현 * [#13] feat: ✨ API에 fetch 요청 로직 구현 * [#13] feat: ✨ API 요청, 베스트 기능구현 - BestItems.jsx - API 데이터 동기화 - BestTab.jsx - useState, useEffect, API 요청 - BestTabContainer.jsx - API 데이터 동기화 - BestTabNavigator.jsx - API 데이터 동기화 - ItemCard.jsx - prop 변경 - Label.jsx - COLOR변수 추가 * [#15] feat: ✨ 상세 modal 페이지 UI 구현 - App.js - PopUpContainer import - PopUpContainer.jsx - UI 구현 - PopUpImages.jsx - UI 구현 - PopUpInformations.jsx - UI 구현 * [#16] feat: ✨ 모달 페이지 이벤트 구현중 * [#16] feat: ✨ 수량정보 컴포넌트 분리 * [#19] refactor: 🔨 리팩토링, 부족한 부분 추가 구현 - 파일 및 폴더 구조 변경 - common 폴더 생성 - Context.jsx - useContext 사용하여 prop drilling 개선 - 팝업 이벤트 구현 - 수량 변경 - 주문하기 - 주문결과 안내 메시지 UI * [#19] refactor: 🔨 리팩토링 * [#17] feat: ✨ dj-slider 폴더구조 구축 * [#17] feat: ✨ 슬라이드 1/2 구현 중 * [#23] refactor: 🔨 코드 리뷰 코멘트 반영 및 개선 * [#17] feat: ✨ 슬라이드 구현중/일부사항 수정 - util.js - price에 comma 붙이는 기능 구현 - PopUpItemCountContainer.jsx - price에 comma 붙이는 기능 import - ItemCard.jsx - price에 comma 붙이는 기능 import - 이미지 background로 수정 - Label.jsx - 라벨 배경색상 적용 * [#17] feat: ✨ 슬라이드 구현중 - 모듈화 - 시연을 위한 기능 구현을 위해 보류 * [#25] feat: ✨ 슬라이드 2/2 구현, API 데이터 동기화 - 슬라이드 명칭을 캐로셀로 변경 - API 데이터 동기화 - 캐로셀의 ItemCard를 children으로 변경 - 모듈화를 위함! - 아이템카드 mini, large 프로퍼티 추가 - 상세모달 캐로셀 추가 - 상세모달 스크롤 추가 - 모든 카테고리 보기 기능 구현 * [#27] feat: ✨ BestTab Skeleton UI 만들기 - Main.jsx - 시연을 위한 loop 설정 추가 - BestTab.jsx - SkeletonTab import - BestTabNavigator.jsx - 주석 제거 - SkeletonTab.jsx - Skeleton UI 구현 - DicoJsonCarousel.jsx - Carousel 구현중 * [#29] feat: ✨ PopUp Skeleton UI 만들기 - Context.jsx - 주석 제거 - BestTab.jsx - 주석 제거 - PopUpContainer.jsx - Skeleton import - PopUpItemsSlide.jsx - 주석 제거 - SkeletonPopUpContainerBody.jsx - Skeleton UI 구현 * feat: ✨ carousel loop 기능 구현 * [#31] feat: ✨ README.md 작성완료 Co-authored-by: kowoohyuk <kowoohyuk91@gmail.com>
(온라인 반찬서비스 ) Side-dish
주요 구현 목록
Study keywords
고민 및 해결
의존성을 주입하기 위해 DIContainer 객체를 만들어 주입을 시켜줬는데 좋은 방법일까 대한 의문입니다🤔
네트워크를 각각 요청하고 구분해서 응답 받는 요구사항이 있는데 순서가 상관없이 먼저 온 데이터에 대해 옵저버를 통해 도착한 데이터의 섹션을 전달하고 전달된 섹션의 아이템리스트를 가져와 화면에 표시하도록 해결했다
반찬 Title의 텍스트 양의 따라 동적으로 UI 조정되도록 했다
CollectionView ReusableView 뷰를 쓸때 높이를 정적으로 지정해서 사용하게되는데 높이를 동적으로 할 수 있을지 의문입니다!