프로젝트를 하다보면 무조건써야하는 함수인데 이름을 각자 정의해서 쓰는 함수들이있다.
대표적으로 setUI() 누구는 configuration()이렇게 쓰는 사람도 있었고 setLayout()이렇게 쓰는 사람도 있었다. 사실뭐 딱히 문제가 발생하지는 않았지만 통일하는게 깔끔해 보이긴 한다.
그래서 아주 예전(아무것도모르던 시절)에는
우리 setUI로 통일합시다!
라는 말도 했을정도였다 그런데 사실 이런게 필요가 없었다.
프로젝트를 하다보면 프로젝트 환경을 설정하는 과정에서 BaseViewController라는걸 만들어서 틀에맞게끔 팀원모두가 코딩을 한다
rxswift를 쓸때는 cancelBag를 선언해놓으니까 굳이 내가 viewcontroller를 쓸때마다 선언을 안해줘도 된다.
사실 프로젝트에 들어가서 내가 맡은 view를 만들다보면 viewcontroller를 5~6개를 만들어야하는데 그때마다 layout잡는 코드들을 선언해주기 번거롭기도 하고 문제는 내가 처음엔 setUI를 썼는데 나중에보면 어떤 VC에는 configuration을 쓰고 하여튼 코드가 일관성이 없어보인다.
이걸 해결할 수 있는 좋은방법으로는 BaseViewController를 만들어서 상속받으면된다
내가만든 예시 BaseViewController를 보자
import UIKit
import SnapKit
import Then
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
setUI()
setConstraints()
}
func setUI() {}
func setConstraints() {}
}
우선 이건 BaseViewController(이하 BVC)를 다른 분들은 어떻게 사용하시나 구글링하다가 알게된건데 패키지를 매번 선언하지 않아도 되는 편리함도 존재했다.
보통 나는 snapkit은 무조건 사용한다. 그래서 VC를 만들때마다 import Snapkit을 타이핑해왔는데 BVC에다가 저렇게 import SnapKit이나 import Then을 선언해놓으면 VC에서는 저걸 안써줘도 된다고한다
실제로도 써보니 import를 안해도 되는걸보고 이거 참 편리하다는 생각을 했다
그리고 보통 프로젝트를 진행하면 배경화면색은 정해져있는 경우가 많다 그래서 BVC에서 배경화면색을 정해놓으면 매번 VC에서 선언을하지 않아도 된다.
그리고 코드의 통일성을 줄수있는 setUI나 setConstraints에 관한내용인데 프로젝트팀원에게 BVC를 한번만 설명해주고 주석만 달아두면 다들 잘 맞춰서 사용한다. 예를들어서 setUI에는 addSubView를 하고 autoLayout을 잡는 snapkit코드는 setConstraints에 적어달라고 하면 그렇게 맞게 적고 다른사람을 코드를 볼때 한결 수월해진다
아래 코드는 BVC를 사용한 VC코드다
import UIKit
class ViewController: BaseViewController {
private var testLabel: UILabel = UILabel().then {
$0.text = "testLabel"
$0.font = .systemFont(ofSize: 15)
$0.tintColor = .blue
$0.textAlignment = .center
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func setUI() {
view.addSubview(testLabel)
}
override func setConstraints() {
testLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
make.size.equalTo(100)
}
}
}
우선 보면 snapkit이랑 then이 import가 안되어있는데 snp랑 then을 사용한걸 볼 수 있고 setUI와 setConstraints를 재정의해서 사용할 수 있다.
예를 들어 uibutton 이나 uilabel을 사용할때 나는 아래와같이 사용한다
private var myLabel: UILabel = {
let label = UILabel()
label.text = "myLabel"
label.font = .systemFont(ofSize: 15)
label.tintColor = .blue
label.textAlignment = .center
return label
}()
이런식으로 클로저에서 ()를 통해서 실행해서 label을 리턴하는방식으로 사용을 했는데 이게 계속 같은걸 반복하다보면 꽤 귀찮다. 나는 코드가 이쁜게 좋아서 label을 계속 쓰는데(자동완성도 되니까)근데 저런 작업을 계속 반복하면 정말 번거롭기는하다 그래서 다른 팀원들 코드를 보면
private var yourLabel: UILabel = {
let v = UILabel()
v.text = "myLabel"
v.font = .systemFont(ofSize: 15)
v.tintColor = .blue
v.textAlignment = .center
return v
}()
이렇게 쓰는 사람들도 많았다. 나는 초반에 저 위의 코드를 써왔기때문에 팀원들한테 왜 v로해서쓰냐고 물어봤었던기억이 나는데 의미없으니까?라는 답변을 들었던 기억이 난다.
근데 조금 번거롭기는해도 어쩔수없지라고 생각하고 첫번째 코드스타일을 사용해왔는데 then이라는 라이브러리를 알게되었다. 이 라이브러리를 사용하면 코드가 간결해진다
private var testLabel: UILabel = UILabel().then {
$0.text = "testLabel"
$0.font = .systemFont(ofSize: 15)
$0.tintColor = .blue
$0.textAlignment = .center
}
이걸 사용하려하는데 자꾸 자동완성이 안돼서 한 2시간을 삽질했다... $0.이러면 보통 uilabel관련 메서드들이 떠야하는데 계속 안떠서 업데이트도해보고 꺼켰도 해보고 아주 별의별 짓을 다해봤는데 변수를선언할때 타입을 선언해주니까 자동완성이 됐다...
물론 확실히 기존코드에서 처럼 클로저실행을 위해 ()도 필요없고 return도 필요없어서 나쁘지 않은거같은데 $0를 매번 써줘야하는게 번거로워서 이건 스니팻으로 만들었다 fir만 쳐도 $0가 나올수있게 설정해놨다.
간단한 문법이긴한데 프로토콜이 AnyObject를 상속했다면 이 프로토콜은 클래스만 채택할수있게된다
protocol TableViewCellReuseProtocol: AnyObject {
static func register(tableView: UITableView)
// MARK: - 여기서 Self는 타입인데 protocol을 채택하는 타입을 이야기함(확장성을 고려할수있게됨)
static func dequeueReusableCell(tableView: UITableView) -> Self
static var reuseIdentifier: String { get }
}
예전에는 class라는 키워드를 사용했었는데 사용해보니
class를 AnyObject로 바꾸라는 제안을 해준다