# 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 에서 메모리 주소를 넣으면 메모리에 있는 데이터를 볼 수 있습니다.