# 2조 1주차 피어세션
> 🧑⚖️ 진행자 S026_신재웅
> ✍️ 서기 S051_전여훈
- 참여자
- S008 김민지
- S009 김민창
- S026 신재웅
- S030 오창민
- S036 이나정
- S038 이세은
- S050 이하원
- S051 전여훈
## 진행방법
1. 챌린지때 처럼 자기 코드 이야기 하고 피드백 받고 싶은 부분 받기
2. 미션 주제에 맞게 차례대로 같이 살펴보며 이야기 해보기 (edwith 한명이 공유해서 보면 좋을 듯)
+ 미션에 나와있던 질문들
## 법정 쉬는시간
- 2:20 ~ 2:30
- 3:36 ~ 3:46
- 4:20 ~ 4:30
## 발표 순서
희망하는 사람 ✋
## Timeline
|Mission|Time|TOC|
|:-|:-|:-:|
|1. 앱 프로젝트|13:30~13:50|[바로가기](#앱-프로젝트)|
|2. IBOutlet과 IBAction|13:50~14:10|[바로가기](#IBOutlet과-IBAction)|
|3. Scene과 Segue|14:10~|[바로가기](#Scene과-Segue)|
|4. 캐릭터 선택 화면|불꽃|[바로가기](#캐릭터-선택-화면)|
|5. 게임 뷰 컨트롤러 추가하기|토론|[바로가기](#게임-뷰-컨트롤러-추가하기)|
|6. 내비게이션 컨트롤러|길잃음|[바로가기](#내비게이션-컨트롤러)|
|7. 과일 카드 타입|15:30~15:50|[바로가기](#과일-카드-타입)|
|8. 카드덱과 테스트|15:50~|[바로가기](#카드덱과-테스트)|
|9. 카드 게임 로직과 테스트|~16:30|[바로가기](#카드-게임-로직과-테스트)|
## 앱 프로젝트
- Tab Bar를 다른 프로젝트 하기 전에 삭제하셨는지
- 뒤에 게임과 설정 tab bar로 활용
- UITabBar와 UITabBarController의 차이점은 무엇인가?
- UITabBar는 UITabBarController의 view
- 콜백함수를 사용하는 용도
- 컨트롤러가 언제 사용되고 나타나고 사라지는지 확인하기 위한 용도
## IBOutlet과 IBAction
- storyboard 에서 설정할 수 없는 부분은 전부 코드로 짜야하나요?
- UIView를 extension하고 @IBInspectable 을 정의하면 스토리보드에 원하는 속성이 나옵니다.
```swift
extension UIView {
@IBInspectable var borderWidth: CGFloat {
set { layer.borderWidth = newValue }
get { return layer.borderWidth }
}
@IBInspectable var cornerRadius: CGFloat {
set { layer.cornerRadius = newValue }
get { return layer.cornerRadius }
}
@IBInspectable var borderColor: UIColor? {
set {
guard let uiColor = newValue else { return }
layer.borderColor = uiColor.cgColor
}
get {
guard let color = layer.borderColor else { return nil }
return UIColor(cgColor: color)
}
}
}
```
- IBAction 을 여러개의 버튼에 연결할 수 있을까요?
- 해보니까 됩니다..!
```swift
@IBAction func updateImage(_ sender: Any) {
guard let button = sender as? UIButton else {
return
}
guard let buttonName = button.titleLabel?.text else {
return
}
self.characterImageView.image = UIImage(named: buttonName)
}
```
- 저는 이렇게 이미지 고르는 버튼을 하나의 IBAction에 다 연결시켜서 이미지 뷰의 이미지를 바꿔주었습니다.
## Scene과 Segue
- 세그라고 안읽고 세그웨이라고 읽어야합니다...
- Partial Curl 효과가 적용이 안되는데 이유가 뭘까요?
- Partial Curl이 뭐죠...
- 종이 넘기듯이 넘어가는 효과입니다!
- 앞 페이지 사이즈가 full screen이 아니어서 그런 것 같습니다..
- 궁금증 해결!
- 스큐어모피즘(?) (현실과 비슷하게 디자인하는거) 때문에 잘 안쓰는게 아닌지
- 일반적인 앱에서는 잘 안쓰고 E-Book 같은 곳에서 쓸 것 같다.
- 이건 옆으로 안넘어가고 위로 넘어가는데 커스텀해서 쓰고 있는게 아닐까..?
## 캐릭터 선택화면
- 다들 레이아웃 constraint 주셨나요? 아직은 요구되지 않는 것 같아서 적용을 안했는데, 그럼 이미지가 깨져서 이미지에만 적용했는데 다른 분들은 어떻게 하셨나요? UIImageView 사이즈가 이상해서..뷰 크기가 고정이 안되고 커지는 경우가 있었습니다...
- 저는 그냥 이미지 넣으니까 잘 나왔습니다..
- IB에서 ImageView contents mode 뭐로 되어있으신가요?
- Aspect fit으로 되어 있네요.
- 그럼 이 문제는 아닌 것 같습니다.
- 저는 뷰 사이즈를 정해줬습니다!
- 뷰 크기를 저는 300*300으로 고정을 시켰습니다.
- x,y 도 고정을 시켜버렸어요.
- Horizontal Stack View 쓸 때 텍스트 필드 길이가 가변으로 계속 늘어나서 다른 요소들을 잡아먹던데 이런경험 있으신가요? 좌우에 constraint를 줬는데 이건 안먹더라구요.
- constraint로 가로 길이를 주면 될 것 같습니다.
- Horizontal Stack View에서 내부 요소들의 비율을 정할 수 있나요?
- 코드로는 있는데, IB에서 fill paretly, evenly 같은 옵션을 적용할 수 있습니다.
- 중간에 있는 우선순위를 높이고 스택 뷰의 양쪽에 constraint를 주면 조절이 가능하지 않을까요?
- Vertical Stack View 사용하면 constraint을 다 주지 않아도 쉽게 정리할 수 있을 것 같습니다.
- 라인에서 Stack View를 사용하는 것에 대한 좋은 글을 올린적이 있는데...찾으면 공유하겠습니다.
- 정규식 적용할 때 NSPredicate(foramt: :"SELF MATCHES %@", regex)에서 "SELF MATCHES %@"를 왜 쓸까요?
- 저희는 다른 NSRegularExpression을 사용해서 쓸 일이 없었습니다.
## 게임 뷰컨트롤러 추가하기
- UIAlertController를 Action 외부로 빼면 에러가 생기던데 왜이럴까요?
- action 버튼 누르면 UIAlertController 인스턴스가 해제되는게 아닐까요?
- static으로 해도 안되고..
- UIAlertController에 deinit을 걸어서 언제 해제되는지 보려고 했는데, deinit을 못쓴다.. 오ㅓㅐ?
- ✨ 마스터 클래스때 물어봅시다!
- 리셋버튼 눌렀을 때 게임 캐릭터 선택화면으로 하고 싶은데 어떻게 하셨나요?
- 저는 내비게이션을 앞으로 빼서 리셋눌렀을 때 pop 시키는 방식으로 했습니다.
- 내비게이션 푸쉬 하는 법
1. 스토리 보드 아이디로 인스턴스 만든다.
2. NavigationController push로 새로운 뷰 올린다.
```swift
let pushVC = self.storyboard?.instantiateViewController(withIdentifier: "test")
self.navigationController?.pushViewController(pushVC!, animated: true)
```
## 내비게이션 컨트롤러
- push로 웹페이지를 올렸을 때 Done 버튼을 누르면 왜 아무 반응이 없을까요?
- done은 pop의 역할이 없는게 아닐까요?
- 계층 구조상으로 버튼이 가려져 있는게 아닐까요?
- 디버거로 봤을 때 기다란 바 같은게 있다.
- SFSafariView / _UISizeTrackingView
## 과일 카드 타입
- CaseIterable에서 allCases vs. AllCases
- [참고](https://appleceo.github.io/2019/09/15/CaseIterable/)
## 카드덱과 테스트
- 카드덱을 구조체로 만들면 새로 카드를 변경시킬때마다 구조체 전체를 복사하고 붙여넣는 것으로 알고 있는데, 이런 경우에 구조체를 쓰면 오버헤드가 크지 않을까요?
- 잘 모르겠다..
- 공식 문서에서는 객체를 트래킹하는 상황이 아니면 구조체를 사용하라고 권장합니다. 프로퍼티에 대한 내용이 없는걸로 보아서 괜찮지 않을까요?
- shuffle 테스트 어떻게 하셨나요?
- 어차피 shuffle은 Foundation의 내부함수이니 상관없지 않을까요?
- 40전체를 removeOne 해서 비교하는 방식을 사용했습니다.-> removeOne에 대한 의존성이 있어서 좋은 단위 테스트는 아닌 것 같습니다.
- 단위 테스트가 되려면 시나리오대로 안되더라도 함수단위로 쪼개는게 좋다고 생각됩니다.
- 시나리오테스트도 하고 유닛테스트도 하는게 가장 좋지 않을까요?
- remove만 하는 테스트, 셔플 후 remove 테스트 등
## 카드 게임 로직과 테스트
- 플레이 모드에 대한 테스트를 할 때 중복된 코드가 많이 발생해서 저는 파라미터로 모드를 받아줬는데 이렇게 하면 리셋을 계속 해줘야하고 다른 메소드를 실행해야하는 상황이 생기는데 다들 어떻게 하셨나요?
- 저는 한 테스트 안에서 모드만 바꿔가면서 한 테스트 안에서 모든 테스트를 다 수행하도록 했습니다.
- 단위 테스트는 다른 함수와 종속성이 없어야할 것 같습니다.
- 플레이 모드 테스트는 어떻게 하셨나요?
- 남은 카드 개수로 테스트했습니다!
- 재웅님의 디버거 화면 사용법
- debug -> debug flow -> view memory 에서 메모리 주소를 넣으면 메모리에 있는 데이터를 볼 수 있습니다.