일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 코드스타터캠프
- 부트캠프
- 애플디벨로퍼
- IT동아리 면접
- 스위프트
- ios-커리어-스타터-캠프
- 넥스터즈 후기
- 야곰캠프
- 야곰아카데미
- IT동아리
- 야곰 아카데미
- 오세요
- 커리어스타터캠프
- 스타터 캠프
- 야곰닷넷
- 강추
- 기획자
- 기획자의 여행법
- iOS개발자
- Swift
- 오늘도 개발자가 안 된다고 말했다
- 커리어 스타터 캠프
- 야곰
- 테크캐스트
- 넥스터즈
- ios커리어스타터
- GraphQL
- 넥스터즈 면접
- ios
- 코드 스타터 캠프
- Today
- Total
iOS Ellen
[iOS] 반복적인 뷰 추상화하기 본문
회원가입 화면을 열심히 구현했는데 갑자기 기획자가 이메일과 비밀번호 사이에 닉네임 필드를 넣어달라고 요청했다.
하..... 진작 말해주지... 오토레이아웃이랑...언제 다 수정하지 ^^.... 라고 생각하지 말고!!
처음부터 필드가 확장성있게 구현하지 못한 개발자 잘못이다🥲
뷰의 공통적인 부분을 추상화해보자!
하나의 필드에서 타이틀 레이블, 텍스트필드가 들어간다는 공통점이 있다.
하지만 추상화할때 고민되는 부분은 각 레이블과 텍스트필드의 플레이스 홀더가 달라져야한다는 점이다.
그렇다면 이 세가지 뷰를 추상화하고 초기화되는 시점에 레이블과 텍스트필드의 플레이스 홀더를 주입받으면 되지 않을까?
// 코드 요약본
class SignUpContentsView: UIView {
private lazy var titleLabel: UILabel = {
...
}()
private lazy var textFieldBackground: UIView = {
...
}()
private lazy var textField: UITextField = {
...
}()
convenience init(title: String, placeholder: String) {
self.init(frame: .zero)
titleLabel.text = title
textField.placeholder = placeHolder
}
}
위와 같이 타이틀과 플레이스 홀더를 초기화 시점에 주입받을 수 있게 구현했다.
class SignUpView: UIView {
private var signUpContentsViews: [UIView] = [] // 공통적인 뷰를 가지고있는 배열
private lazy var stackView: UIStackView = { // stackView 생성
...
}()
init(_ views: [UIView]) {
self.signUpContentsViews = views
super.init(frame: .zero)
signUpContentsViews.forEach { // 스택뷰에 각 View들을 추가하는 작업
stackView.addArrangedSubview($0)
}
}
signUpContentsViews에서 추상화한 뷰의 배열을 가지고있고
초기화하는 시점에 stackView에 각 뷰들을 추가하는 작업을 하면되는데.....
private var signUpContentsViews: [UIView] = []
init(_ views: [UIView])
모든 UIView 타입을 기대하는 방식으로 구현하면 모든 뷰가 이 배열안에 들어갈 수 있으므로 조심해야한다.
protocol을 사용하여 SignUpViewable라는 타입으로 추상화해보자!
protocol SignUpViewable: UIView {} // 추상화
class SignUpView: UIView {
private var signUpContentsViews: [SignUpViewable] = [] // SignUpViewable
private lazy var stackView: UIStackView = {
...
}()
init(_ views: [SignUpViewable]) { // SignUpViewable
self.signUpContentsViews = views
super.init(frame: .zero)
signUpContentsViews.forEach {
stackView.addArrangedSubview($0)
}
}
이렇게만 바꿔주면 될까? 공통적인 뷰를 구현한 SignUpContentsView를 SignUpViewable을 채택하도록 하자
class SignUpContentsView: UIView, SignUpViewable { // SignUpViewable 채택
private lazy var titleLabel: UILabel = {
...
}()
private lazy var textFieldBackground: UIView = {
...
}()
private lazy var textField: UITextField = {
...
}()
convenience init(title: String, placeholder: String) {
self.init(frame: .zero)
titleLabel.text = title
textField.placeholder = placeHolder
}
}
자 이런식으로하면 SignUpViewable로 추상화했다. 구현 예시와같이 텍스트필드로 이루어진 뷰가 아니라
성별을 정하는 세그먼트뷰 같은 것도 SignUpViewable을 채택하면 뷰 스택에 추가될 수 있다.
즉 SignUpViewable을 채택한 UIView는 모두 추가될 수 있다!
class SignUpViewController: UIViewController {
private lazy var signUpView: SignUpView = SignUpView(SignUpContentsView(title: "이메일",
placeHolder: "ex)jcrescent61@google.com")
SignUpContentsView(title: "패스워드",
placeHolder: "대,소,특수문자 최소 1회 포함")
SignUpContentsView(title: "패스워드 확인",
placeHolder: "동일한 비밀번호를 입력해주세요"))
}
override func viewDidLoad() {
super.viewDidLoad()
view = signUpView
}
}
자 이런식으로 SignUpView(이메일뷰, 비밀번호뷰, 비밀번호확인뷰) 이런식으로 추가하면 위와 같이 편하게 뷰를 구현 가능하다!
뷰의 순서를 바꿔야하는 경우에도 배열의 순서만 바꾸면 그대로 반영된다🥳
예시코드 깃허브 바로가기
https://github.com/jcrescent61/EllenTalk
아래의 코드는 세세한것들까지 추상화했으므로 현재 글과 코드가 조금 다른 점 유의하시길 바랍니다!
직접 프로젝트를 열고 뷰를 추가해보면서 실험하면 좋은 경험이 될 것 같습니다 ㅎㅎ
'Personal > 개발일지' 카테고리의 다른 글
[iOS] Apple Login 구현 중 막혔던 포인트들 (0) | 2022.04.24 |
---|---|
[Pot 개발일지] CollectionView로 할까? TableView로 할까? (0) | 2022.04.19 |