-
[TIL w2d4] Swift CLI 숫자 야구게임 (Feat. 🛠️트러블 슈팅)iOS💖 2025. 3. 14. 11:31
[0] About CLI 숫자 야구게임
개발 기간: 3주차 (3월 10일 ~ 3월 13일)
https://github.com/hortenssiaa/SpartaCamp-iOS/blob/main/BaseBallGame_CLI/README.md
SpartaCamp-iOS/BaseBallGame_CLI/README.md at main · hortenssiaa/SpartaCamp-iOS
deep dive ❤️🔥 into iOS. Contribute to hortenssiaa/SpartaCamp-iOS development by creating an account on GitHub.
github.com
[1] 디자인 패턴:고민 & 선택하기
디자인 패턴? 프로젝트 성격에 따라 개발하는 설계원칙!
[MVC 패턴을 사용해볼까?]
- MVC : 컨트롤러가 일 젤 많이 하는 구조
- M : 데이터 상태 유지,조작 / Class, Struct
- V: 데이터 표시 / 사용자의 입력 -> C / 사용자 입력에 대한 출력 <- C
- C : 모델 & 뷰 간의 상호작용 / 뷰에게 받은 데이터, 모델에 전달 / 업데이트
- ➡️ 프로젝트 규모가 커질수록, 서로 독립성이 없고, 테스트 어렵고 재사용성이 떨어진다.
- MVC 의 단점을 보완하기 위한, 모델만은 독립성을 가진 CocoaMVC가 나왔다고 한다.
[고민]
처리 되어야 하는 로직은 제한 되어있고, 요청에 따라 해당 로직을 사용하는 작은 규모의 프로젝트이기 때문에,
MVC 패턴을 사용해도 될 것 같다고 생각했다. 그러나, 더 독립적인 코드 작성과, 컨트롤러의 부담을 조금이라도 줄여주기 위해,
MVVM 을 선택하게 되었다.
- MVVM
- Model: 데이터 update / 주기
- View/ViewController : 입출력만 / 데이터 표시
- ViewModel : 실제 구현 / 데이터 변환 처리
[2] MVVM + 커맨드 패턴
[ (행위패턴) 커맨드 패턴 ]
Invoker ➡️ <protocol> Commanding ⬅️ Command ➡️ Receiver현재 3가지의 명령 (1, 2, 3) 이 있지만, 후에 추가될 기능을 위한 유지보수성을 고려하여 커맨드 패턴을 사용하게 되었다.
커맨드 패턴의 핵심은 undo 기능인데, 그렇게 맞게 기능을 구현하지 않는다면, 커맨드 패턴은 사용할 필요성은 없어보인다.
그러나, 기능이 늘어날수록, 기능만 모듈로 추가 / 수정 / 삭제 할 수 있다는 장점 때문에 사용하게 되었다.
뷰컨트롤러와 뷰 모델 사이의 의존성을 느슨하게 하기 위해.
[3] 트러블 슈팅
- Thread 1: EXC_BAD_ACCESS 오류 발생 (미해결)
error detail; A bad access to memory terminated the process.- 의심되는 원인: (GameInvoker에서 GameViewModel을 선언할 때 순환 참조가 발생하는 것 같음
- 메모리 접근이 잘못되었을 때 발생하는 오류
- 상태: 미해결되어, Command Pattern 을 제외한 상태임
- 시도한 해결 방법:
- GameViewModel의 GameInvoker를 unowned var로 선언
- 추가 조사 필요:
- GameInvoker와 GameViewModel 간의 참조 구조 개선: unowned 참조로 변경한 상태로, GameViewModel에서 GameInvoker를 참조하는 방식도 개선해볼 것
- 강한 순환 참조 문제 해결 : GameViewModel과 GameInvoker가 서로를 강한 참조하여 순환 참조가 발생할 것을 대비하여, gameVM을 weak 으로도 선언해볼 것
- 의심되는 원인: (GameInvoker에서 GameViewModel을 선언할 때 순환 참조가 발생하는 것 같음
- Cannot use instance member 'gameInvoker' within property initializer 오류 발생 (미해결)
- 의심되는 원인: 프로퍼티 초기화 시 self가 아직 생성되지 않았기 때문
- 상태: 미해결되어, Command Pattern 을 제외한 상태임
- 시도한 해결 방법:
- lazy var를 사용하여 self가 완전히 초기화된 후 접근하도록 수정
- lazy var를 사용하여 self가 완전히 초기화된 후 접근하도록 수정
- 랜덤 값이 제대로 생성되지 않는 경우
- RandomAnswerGenerator의 makeAnswer 메서드에서 랜덤 값 생성 로직 확인
- 추후에 입력받는 자릿수의 숫자가 달라질 것을 대비하여, 자리수에 따라 10의 제곱근으로 랜덤 값을 생성했다.
- swift 에서 사용할 수 없는 ^ 연산자를 사용하여 값이 이상하게 나왔음
- 해결 방법: ^ 연산자 -> pow() 메소드로 변경
- 디버깅 방법: print()를 활용하여 입력값과 검증 과정을 출력해보며 문제를 찾기
- Command Pattern의 Invoker, Receiver 주체 설정
- 처음 공부하고 적용해보는 패턴이라서, Command Pattern의 Invoker, Receiver 주체를 설정하는 것 부터가 어려웠다.
- 결국에는, 사용하고자 했던 목적이 3가지 메뉴 (기능) 에 기능이 추가될 것을 생각하여 사용한 패턴이기 때문에, 메뉴에 보여지는 기능들이 Receiver, 그것을 명령하는 주체는 Game 자체 (사용자에 의한) 로 설정하게 되었다.
- Invoker, Receiver 주체와 사용방법 등 명확하지 않아 튜터님의 피드백을 기다리고 있다...
[4] 받은 코드리뷰: 적용 완료
클래스 / 파일 분리Set 으로 중복 제거enumerated() 사용!random -> .shuffled() 으로 사용해보기
[5] 참조
https://github.com/jeonyeohun/Design-Patterns-In-Swift
GitHub - jeonyeohun/Design-Patterns-In-Swift: 스위프트로 이해하는 디자인 패턴 👨🏻🎨
스위프트로 이해하는 디자인 패턴 👨🏻🎨. Contribute to jeonyeohun/Design-Patterns-In-Swift development by creating an account on GitHub.
github.com
https://jeonyeohun.tistory.com/389
[스위프트 디자인패턴] 커맨드 패턴(Command Pattern)
커맨드 패턴(Command Pattern) The command pattern encapsulate a request as an object, thereby letting you parameterize other objects different requests queue or log request and support undoable operation 커맨드 패턴은 어떤 객체로 보내는
jeonyeohun.tistory.com
[Swift 디자인 패턴] Command Pattern (커맨드) - 디자인 패턴 공부 15
안녕하세요 Pingu입니다.🐧 지난 글에서는 행동 패턴 중 하나인 Chain of Responsibility Pattern(책임 연쇄 패턴)에 대해 알아봤었는데요, 이번 글에서는 또 다른 행동 패턴인 Command Pattern(커맨드)에 대해
icksw.tistory.com
'iOS💖' 카테고리의 다른 글
[TIL w3d1] Swift 복습 (Optional, 중첩타입, 접근제어자, Protocol) (0) 2025.03.17 [TIL w2d5] Swift 복습 (Enum, Property 🌺) (0) 2025.03.17 [TIL w2d3] 알고리즘 Swift로 다시시작 / Swift 복습 (Struct) (0) 2025.03.13 [TIL w2d2] 알고리즘 특강 / 야구 게임 만들기 (Lv. 1~3 / 6) (0) 2025.03.11 [TIL w2d1] Swift 복습 (Tuple, Collection Type, Closure) (0) 2025.03.10 - MVC : 컨트롤러가 일 젤 많이 하는 구조