Skip to content
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

[Team09 - 쑤 & 쏭] 게임 진행 화면 구현 (Data binding & CALayer 추가) #16

Open
wants to merge 6 commits into
base: team9
Choose a base branch
from

Conversation

1song2
Copy link

@1song2 1song2 commented May 10, 2021

작업 목록

  • Combine 이용해 제목, 투수 및 타자 정보, 볼카운트 리스트 정보 binding
  • 진행현황판에 요소(1루, 2루, 홈플레이트 등) CALayer 및 UIBezierPath로 구현

학습 키워드

  • Combine
  • Generic
  • CALayer
  • UIBezierPath

고민과 해결

  • 지난 1차 PR에서 고민으로 말씀드렸던 Generic으로 함수를 추상화하는 부분을 개선해보았습니다. assign 메소드 대신 AnyPublisher를 리턴하고 그렇게 함으로써 ViewController 대신 ViewModel 안에서 데이터를 Binding 하는 방향으로 구현이 되었습니다.
  • CALayer나 UIBezierPath 관련 부분을 코드로 모두 작성하다 보니 파일이 길어지는 것 같아 중복되는 부분을 메소드로 묶어줄 수 있도록 신경 썼습니다.

Copy link

@mienne mienne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 데이터 바인딩으로 ViewModel에서 Combine, ViewController 클로저로 구현한 것을 확인하였습니다. ViewController에서 어떤 점이 어렵거나 불편해서 bind 제거하고 클로저로 구현하게 된 이유, 두 가지로 구현했을 때 각각 어떤 점이 좋고 나빴는지 잘 정리해두세요🙂

didSet {
count = viewModel?.game?.pitcherHistory.count ?? 0
count = viewModel?.game?.data.pitchHistories.count ?? 0
Copy link

@mienne mienne May 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 가져오게 되면 PlayerViewController에서 모델과 관계가 생깁니다. 이러면 GameViewModel 만든 의미가 없습니다. Model 정보(viewModel?.game?.data.pitchHistories.count)를 ViewModel(viewModel.numbersOfGame 이나 viewModel.gameCount)에서 View 표시할 정보로 가공하고 ViewController에서 ViewModel 정보 가져와서 사용하는 것이 좋습니다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그렇군요! 수정해보도록 하겠습니다!😉

@@ -79,12 +78,15 @@ class PlayViewController: UIViewController {

extension PlayViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel?.game?.pitcherHistory.count ?? 0
return viewModel?.game?.data.pitchHistories.count ?? 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분도 위 코멘트와 동일한 부분입니다!

case result
case pitchStrikeCount = "log"
case pitcher, batter, result
case strikeCount = "strike_count"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case strikeCount = "strike_count" 직접 작성하는 방법 말고도 디코딩 할 때 옵션을 줄 수 있습니다.

참고: JSONDecoder.KeyDecodingStrategy.convertFromSnakeCase

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오! 참고해서 수정해보겠습니다.😉 감사합니다.


class GameUseCase {
let apiRequestManager = APIRequestManager()

func start(url: URL) {
apiRequestManager.fetchGame(url: url, method: .get)
func start(url: URL) -> AnyPublisher<GameResponse, Error> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네트워킹 관련 로직을 고치니 한결 나아졌네요. 잘 수정하였습니다👏

case .finished:
break
case .failure(let error):
print(error.localizedDescription)
Copy link

@mienne mienne May 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

당장 수정해야 할 부분은 아니지만 에러에 대해서 print로 처리해서 추가적으로 코멘트 남깁니다. 추후, 지금 프로젝트를 개선하거나 앱을 만들 때 고려해야 할 부분입니다.

  • 실패 케이스에서도 서버 응답 실패, 지하철이나 네트워크가 잘 통하지 않는 곳에서 네트워크 OFF 되는 경우 등 다양하게 있습니다. 이 부분도 어떻게 처리할지, 예를 들어 화면에서 사용자에게 메세지를 알려줄 것인지, 재시도 요청할지 등 항상 고려해야 합니다🤔
  • API 요청하고 나서 화면이 구성할 때까지 사용자를 마냥 기다리게 하는 것이 아니라 로딩 인디케이터를 노출하거나 스켈레톤 뷰로 화면 구조가 어떻게 생겼는지 미리 알려줄 수 있습니다. 결과적으로 API 요청, 응답, 화면 구성할 때도 어떤 처리를 할 것인지 고려해야 합니다!

실제 앱 다운 받아서 네트워크 OFF 일 때나 화면 로딩이 어떻게 처리되어 있는지 한번 확인해보세요!

print(error.localizedDescription)
}
} receiveValue: { (response) in
self.game = response
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클로저 self 참조로 인해 순환 참조가 되서 메모리 릭 발생할 여지가 있습니다. 단순한 방법으로 deinit에서 로그 찍어서 잘 호출하는지 확인하는 방법이 있습니다. 또는 Xcode > Memory Graph Debugger 활용하는 방법이 있습니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weak self 약한 참조 관계로 수정했습니다. 😊

private let homePlateLayer = CAShapeLayer()
private var firstBaseLayer = CAShapeLayer()
private var secondBaseLayer = CAShapeLayer()
private var thirdBaseLayer = CAShapeLayer()

override func awakeFromNib() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
override func awakeFromNib() {
override func awakeFromNib() {
super.awakeFromNib()

@@ -9,6 +9,8 @@ import UIKit

class PitcherRecordTableViewCell: UITableViewCell {
@IBOutlet weak var numberLabel: UILabel!
@IBOutlet weak var result: UILabel!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numberLabel, result 중 View 종류를 드러내는 방법으로 변수 작성할지 어떤 스타일로 작성할지 통일하면 좋을거 같아요🙂

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View 종류를 명시하지 않는 방식으로 통일하겠습니다.🙂

@@ -18,4 +20,11 @@ class PitcherRecordTableViewCell: UITableViewCell {
numberLabel.layer.masksToBounds = true
numberLabel.layer.cornerRadius = numberLabel.frame.width / 2
}

func configure(record: Record) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cell도 Record 데이터 자체를 넘기는 것이 아니라 RecordCellViewModel을 넘길 수 없을까요🤔?

return platePath.cgPath
}

private func createBaseLayer(origin: CGPoint) -> CAShapeLayer {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공통적인 부분을 함수로 리팩토링 진행 잘하셨어요!👏

HTMLhead pushed a commit that referenced this pull request May 11, 2021
* Update README.md

* chore: 개발 환경설정

* feat: 기본적인 라우팅 설정

- 절대경로 설정
- /game 과 / 라우팅 경로 설정

* style: gametitle css

* [#2] chore: home 화면 기본적인 파일 구성과 UI 설계

* Feat: useFetch 커스텀 훅 생성

* feat: Home UI Link and click event

* Style: header style 작성

* Style: hover scrollbar

* feat: fetchTeamData

* Update README.md

* Update README.md

* [#3]Style: gameUI header

* refactor: Span 공통 컴포넌트 인자 변경

* Style: Main Component 생성

-   height: -webkit-fill-available; 속성으로 header의 height 에 남은 height 만큼 꽉채우게 해놨습니다.
- StyldeMain 안에 children으로 screen 과 history가 들어가면됩니다.

* Style: StyldeMain height 조정

* feat: theme.js 추가로 provider를 사용

* Style: screen component 생성

* [ #19 ] style: screen  UI

- style: screen.jsx 생성
- style: background img 삽입

* refactor. headerLeft theme 설정 및 스타일 리팩토링

* chore: Span 컴포넌트 스타일 수정

* [# 16] chore: HeaderRight UI 적용

* [#16] refactor: css::after 불필요한 padding 제거

* stlye: screen field svg 추가

* [#20]Style: ScreenRound  component 만듬

* [#21]style: ballcount UI

* style: pitch 버튼 만듬

* chore: merge to dev/FE

* [#17, #18] chore: History UI 작성

기본적인 History 컴포넌트 UI 작성
History 내의 Board UI도 스타일과 함께 작성하였다.

* stlye:BallCount BSO -> type 으로 바꿈

* chore: 상태관리 상위 컴포넌트 Game에 정의

Co-authored-by: 노을 <[email protected]>
Co-authored-by: eamon3481 <[email protected]>
sphilee pushed a commit that referenced this pull request May 12, 2021
fix: Fix Game background (#13)'
Resolve #13
ehgud0670 pushed a commit that referenced this pull request May 14, 2021
[iOS] 로그인 화면 + 게임 선택 화면 + 게임 진행 화면
ghis22130 added a commit that referenced this pull request May 14, 2021
ksundong pushed a commit that referenced this pull request May 16, 2021
crongro pushed a commit that referenced this pull request May 18, 2021
* chore: 프로젝트 초기화 설정

* add: cra | close min27604/baseball/#1

* feat: 시작 화면, 게임 화면 라우팅 처리
- min27604/baseball/#6

* add: 첫 화면에 필요한 컴포넌트 생성
- min27604/baseball/#2
- 게임 리스트 렌더링 하는 데에 에러 있음

* feat: 게임첫화면  mockData임시설정

min27604/baseball/#2

* style: 게임 진행화면 (수비) UI 구성중

- Component 4곳 구성
- Score, CurrentPlayer, Stadium, LogList Cmponent 생성
- Score, CurrentPlayer 구조완성
- min27604/basball/#11

* feat: Stadium 야구장 사진 입력

- img -> backgroundimg로 변경
- min27604/baseball/#11

* feat: Stadium UI 구성 및 rLogList 구조 설계

- Stadium component 내부 구조 설계 및 CSS 작업
- LogList component 폴더 구조 후 상세 작업 진행중
- min27604/baseball/#11

* feat: 시작 화면에 게임 목록 표시

- min27604/baseball/#45

* style: 게임 목록 스타일 수정

- min27604/baseball/#10
- 게임 목록에 3개씩 보이도록 수정
- 기타 자잘한 border-radius, font-size 등 수정

* style: 게임 목록 텍스트 정렬 수정

- min27604/baseball/#10
- vs가 가운데에 고정되도록 홈팀은 오른쪽 정렬 시킴

* feat: 팀 선점 여부에 따라 메시지 다르게 렌더링 (진행중)

- min27604/baseball/#10
- 게임 목록에 경기 번호 추가 (MatchNumber 스타일드 컴포넌트))
- useContext를 사용해보는 중

* refactor: Team 컴포넌트 분리

- min27604/baseball/#10
- Styled component였던 Team 컴포넌트를 일반 컴포넌트로 분리

* feat: 팀 선점 여부에 따라 메시지 다르게 렌더링 (구조 바꿀 예정)

- min27604/baseball/#10
- 서버와 통신하는 방법을 변경하기로 해서 현재까지 진행한 것 일단 타미와 합치기 위해 푸시

* fix: theme 적용 오류 해결

* feature: LogList UI 생성

- min27604/baseball/#11

* feat: Stadium에 ContextAPI 적용한 PlayBoard data 적용

- min27604/baseball/#15

* feat: Stadium S,B,O점수판 PITCH 이벤트 작성

- min27604/baseball/#15

* context 상태 정의를 App.jsx 안으로 수정, 로컬에서 mock data로 통신, axios 설치 (#16)

* refactor: startScreen 디렉토리 생성

- min27604/baseball/#10

* fix: 디렉토리 생성에 따른 경로 수정

- min27604/baseball/#10

* refactor: context.jsx 파일 분리 및 App단으로 변경

- min27604/baseball/#10

* add: localhost로 fetch 보내는 로직 추가, context를 일단 다시 App으로 넣음

- min27604/baseball/#10
- context를 App에 다시 넣은 이유는, setState 로직이 필요한데 useState를 컴포넌트 안에서만 사용할 수 있어서이다. 나중에 costom hook으로 만들 수 있겠다는 조언을 들었다.
- public directory 아래에 json 파일을 만들어 목데이터를 받아왔다.

* refactor: boardHistory 시 코드 개선

- Stadium의 PlayPitch 수정
- Stadium의 PlayBoardTemp 수정
- min27604/baseball/#15

* fix: command not found 오류 해결 중

* feat: reducer 폴더 생성 및 ballReducer 분리

- min27604/baseball/#15

* feat: 유저의 팀이 홈팀인지 여부에 따라 Score 부분에 Player 렌더링

- min27604/baseball/#15
- API 구조 변경에 따라 수정 필요

* feat: Stadium PITCH 이벤트 추가 기능

- Strike==3 or Ball==4 일 때 아웃과 안타 동작
- min27604/baseball/#15

* chore: API 변경에 따른 수정

* refactor: PlayPitch 사용 오류 해결

- PITCH 클릭시 LogList - LogLine 렌더링
- Stadium: 변환시킨 ballCnt를 조건문으로 사용하기 위해선 useEffect를 사용해야 함
- min27604/baseball/#15

* feat: LogList CSS 일부 수정

- min27604/baseball/#15

* feat: inning board 뷰 업데이트 기능 만드는 중

* chore: 포트 번호 수정

* refactor: LComponent명 및 폴더명 변경

- LogPitcher -> LogHitter
- ContextB -> Context
- min27604/baseball/#15

* feat: PlayScreen- H(안타)확률&LogList 멘트 추가

- min27604/baseball/#15

* fix: API 요청 주소 변경

* chore: console.log 삭제

* feat: PlayScreen- H(안타) 확률 추가 , LogList 일부 수정

- min27604/baseball/#15

* feat: 게임 화면의 양 팀 이름을 서버에서 받아온 데이터를 이용해 표시

- min27604/baseball/#15
- DD가 올려준 글에서 나타난 문제 (같은 함수 안에서는 setState가 바로 반영이 안되는 것) 때문에 상태 세팅하는 작업을 PlayScreen으로 옮김

* feat: 현재 투수 이름 표시 (아직 공수교대 시 바뀌는 것까지는 안 된 상태)

- min27604/baseball/#15

* feat: PlayScreen/LogList 에서 안타/아웃 시 현재 타자의 hit,out증가시키기

- LogList: 한박자 느린 Hitter변경, 현재 타자정보 변경 로직 미구현
- min27604/baseball/#15

* fix: 현재 투수표시- inning top이면 홈팀 투수, 아니면 원정팀 투수

- min27604/baseball/#15
- 기존에 isHome과 myTeam / counterTeam 으로 4가지 경우로 처리하던 것을 homeTeam, awayTeam을 이용하는 것으로  수정

* feat: PlayScreen-LogList 안타와 아웃시 totalOutCount++, CurrHitter 변경, 해당선수의 hit 변경 임시 성공

- min27604/baseball/#15

* chore: 오타 수정

* chore: S, B, H 나오는 확률 수정

* fix: 이닝, 초, 말 바꿔주는 로직 수정

- min27604/baseball/#15

* feat: LogList에 타자이름넣기

- min27604/baseball/#15

* feat: 현재 라운드 정보 표시 (회초, 회말, 공수)

- min27604/baseball/#15

* feat: LogList 일부 수정 그러나 미완성

- LogList는 현재 H(타자가 안타를 바로 칠 경우)를 잡지 못함(B4개 ok),  (O도 S3개 count해서 잡음)
- Stadium에서 S가 3번째 되었을 때 setTimeout으로 한번 보여주고 -> O으로 변경한게 문제로 보임

-min27604/baseball/#15

Co-authored-by: Sally Oh <[email protected]>
Co-authored-by: ink-0 <[email protected]>
HTMLhead pushed a commit that referenced this pull request May 19, 2021
* Update README.md

* chore: 개발 환경설정

* feat: 기본적인 라우팅 설정

- 절대경로 설정
- /game 과 / 라우팅 경로 설정

* style: gametitle css

* [#2] chore: home 화면 기본적인 파일 구성과 UI 설계

* Feat: useFetch 커스텀 훅 생성

* feat: Home UI Link and click event

* Style: header style 작성

* Style: hover scrollbar

* feat: fetchTeamData

* Update README.md

* Update README.md

* [#3]Style: gameUI header

* refactor: Span 공통 컴포넌트 인자 변경

* Style: Main Component 생성

-   height: -webkit-fill-available; 속성으로 header의 height 에 남은 height 만큼 꽉채우게 해놨습니다.
- StyldeMain 안에 children으로 screen 과 history가 들어가면됩니다.

* Style: StyldeMain height 조정

* feat: theme.js 추가로 provider를 사용

* Style: screen component 생성

* [ #19 ] style: screen  UI

- style: screen.jsx 생성
- style: background img 삽입

* refactor. headerLeft theme 설정 및 스타일 리팩토링

* chore: Span 컴포넌트 스타일 수정

* [# 16] chore: HeaderRight UI 적용

* [#16] refactor: css::after 불필요한 padding 제거

* stlye: screen field svg 추가

* [#20]Style: ScreenRound  component 만듬

* [#21]style: ballcount UI

* style: pitch 버튼 만듬

* chore: merge to dev/FE

* [#17, #18] chore: History UI 작성

기본적인 History 컴포넌트 UI 작성
History 내의 Board UI도 스타일과 함께 작성하였다.

* stlye:BallCount BSO -> type 으로 바꿈

* chore: 상태관리 상위 컴포넌트 Game에 정의

* Fix: screen Field height 값을 fit contents 로 바꿈

* Style: rotateAnimation 수정

* feat: ballcount

- ballCountReducer
- 버튼 이벤트 발생시 일정한 확률로 strikem, ball , out, hit action 발생.
- count + 1 되며 home 인지 away인지 에 따라서 pitcher 컴포넌트의 homeCount,awayCount 상태에 저장됨.

* style: button animation none

* feat: create popup components

* [#39] feat. 볼카운트 기능 구현

* refactor. 데이터를 page폴더에서 처리 후 하위 컴포넌트로 내려주었다.

* chore. 볼카운트 로직 수정

* style:PopUp refactor

* refactor. reducer 분리 및 action 추가

action.payload와 action.attackState를 통해 홈과 어웨이팀의 카운트를 관리해준다.
reducer파일은 reducers라는 폴더에 저장하였다.
변수폴더를 만들어서 변하지 않는 상수값들을 저장한다.

* feat. headerRight CurrentPlayer class로 투수 이름 변경

* feat. home, away currentplayer를 저장하였다.

headerRight 스타일도 조금 변경

* feat. pitch 클릭 시 history관련 이벤트 적용

* feat. 플레이어 put 요청

* feat: popup feature merge

* chore: put component

Co-authored-by: 노을 <[email protected]>
Co-authored-by: Seonkyu Kim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants