iOS의 UI를 구성하는데에는 대표적으로 세가지 방법이 있다고 한다.
세 가지의 장단점은 대략 요렇다구 한다 !
아무쪼록 스토리보드와 코드의 장점을 적절하게 가져와서 편리하게 재사용하려면 xib 쓰는 법을 알아야 할 듯 하다.
그런데 일단 xib,nib,,,어려운이름...무엇이 다른지, 뭐가 뭔지 모르겠어서 조사하던 중 아주 이해가 잘 되는 정리가 잘 된 글을 발견 ! (출처)
XIB,NIB, Storyboard 어디에 사용되나요?
NIB 파일은 무엇인가요?
바이너리로 이뤄져있는 NIB파일 내부를 바라본 모습 🔽
XIB 파일은 무엇인가요?
XIB파일은 왜 생기게 되었나요?
XML형태의 XIB파일을 변경 후 비교해본 모습 🔽
XIB파일을 Xcode의 Interface Builder로 본 모습 🔽
프로그램이 뷰 정보를 읽어들이는 방법
XIB를 컴파일하면 NIB가 만들어집니다 🔽
XIB파일이 빌드과정후 생성된 app 패키지안에 NIB파일로 저장된 모습 🔼
그렇다면 Storyboard는 무엇인가요?
.storyboardc파일의 패키지 내부 모습 🔼
Storyboard파일 내부 구조 🔼
이렇게 xib는 뷰를 나타낸 xml파일이고 nib는 xib를 컴파일하면 생성되는 바이너리 파일이라는 것으로 정리가 되었고 ! 이제 본격적으로 xib파일로 커스텀뷰를 만들어보자.
아래 사진처럼 checkbox를 구현하기 위해 CheckBoxView.xib와 CheckBoxView.swift를 만들어 주겠습니다.
xib파일을 만들 때는 사진처럼 User Interface의 View를 선택하여 만들어 줍니다!
그 다음으로는 뷰를 관리하기 위해 UIView를 상속받는 클래스를 만들어줍니다.
.xib, .swift 파일을 생성했으니 이제 두 파일을 연결할 차례입니다.
두 파일을 연결해주면 UILabel이나 UIButton과 같이 UIView를 상속하는 나만의 CustomView로 사용할 수 있습니다.
.xib 파일을 열고 Placeholders 아래에 있는 File's Owner를 클릭하고 Attributes Inspector 탭에 File's Owner의 Class를 지정하는 곳이 있는데 여기에 CustomView를 입력해주면 화면과 소스가 연결 됩니다.
아래는 용어 설명 참고,,,
Placeholders: 의미 그대로 UIView처럼 보여지는 주요 요소가 아닌, 빠져있는 것을 대신하여 연결해주는 역할을 의미
File's Owner : nib 파일을 앱코드와 연결시켜주는 객체 (nib파일의 내용을 책임지는 컨트롤러)
First Responder 객체: Responder 객체가 이벤트를 받으면 이를 처리하거나 다른 Responder객체에게 처리할 수 있도록 넘겨야할 의무가 존재, UIKit은 적절한 Responder를 지정해서 이벤트를 넘겨서 처리하는데, 처음으로 이벤트를 받는 Responder를 First Responder로 지칭
(Responder Chain 공부 필요..)
우리가 만들어준 view의 size를 Freeform으로 설정하여 화면의 크기를 자유자재로 바꿀 수 있게 해줍니다.
safe area를 체크해제 안하면 auto layout에서 버그가 생기는 경우가 존재하므로 채크해제를 해줍니다.
정사각형의 뷰를 만들 것이기 때문에 width와 height를 1:1 비율로 설정해 줍니다.
버튼 테두리를 위한 UIView를 추가하고 그 안에 Text가 ✓인 UILabel을 추가하고 Constraints를 지정해줍니다.
checkBoxView는 우리가 만들어준 View이기 때문에 직접 초기화를 해줘야 합니다.
일단 아까 만들어준 view를 모두 @IBOutlet 해줍니다.
checkBoxView는 xib 루트 뷰이고
나머지 둘은 우리가 추가해 준 UI object들입니다.
여기서 초기화를 위한 함수로 commonInit()이라는 함수를 만들고
override init(frame:)과 required init?(coder:)에 각각 넣어줬는데
전자는 코드로 초기화 할 때 필요한 함수이고 후자는 스토리보드로 초기화 할때 필요한 함수라고 합니다. (둘의 차이는 더 공부를 해봐야 할 듯)
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit(){
let bundle = Bundle(for: CheckBoxView.self)
//nib 파일을 이름으로 찾아서 메모리에 로드하여, nib파일 내의 top-level 객체들을 [Any]? 타입으로 반환
bundle.loadNibNamed("CheckBoxView", owner: self, options: nil)
addSubview(checkBoxView)
//초기 UI상태 설정 (비어있는 회색테두리의 체크박스)
checkBoxUIView.layer.borderColor = UIColor.gray.cgColor
checkBoxUIView.layer.borderWidth = 1.0
checkBoxUIView.layer.cornerRadius = 5
checkLabel.isHidden = true
//self(checkBoxview)와 눌렀을 때 실행할 함수checkBoxClicked()를 인자로 넣어 생성한
//UITapGestureRecognizer을 추가해준다.
self.checkBoxView.addGestureRecognizer(UITapGestureRecognizer(target: self,action: #selector(self.checkBoxClicked(_:))))
//만들어준 뷰가 제스처를 인식 할 수 있도록 설정
self.checkBoxView.isUserInteractionEnabled = true
}
checkBox를 눌렀을 때 실행될 checkBoxHighLight() 함수는 delegate로 만들어 viewcontroller에서 구현 되도록 할 것 입니다.
따라서 CheckBoxDelegate프로토콜을 만들어 checkBoxHighLight()를 선언해 놓습니다. CheckBoxViewDelegate.swift 파일을 따로 만들어 주면 좋지만 귀찮아서 그냥 CheckBoxView.swift 맨위에 넣어주었습니다.
protocol CheckBoxDelegate: class {
func checkBoxHighlight(cb: CheckBoxView)
}
CheckBoxView class 안에 delegate 변수를 추가 해줍니다
var delegate: CheckBoxDelegate?
제스처가 생겼을 때 호출 될 함수 안에 델리게이트 함수를 넣어준다.
@objc func checkBoxClicked(_ sender: Any) {
// CheckBoxDelegate 함수 호출
delegate?.checkBoxHighlight(cb: self)
}
UIView를 추가해주고 Class 이름을 CheckBoxView로 지정해줍니다.
delegate를 지정해주고 checkBoxHighlight()를 구현합니다.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var checkBoxView: CheckBoxView!
override func viewDidLoad() {
super.viewDidLoad()
//delegate지정
self.checkBoxView.delegate = self
}
}
//delegate 함수 구현
extension ViewController: CheckBoxDelegate{
func checkBoxHighlight(cb: CheckBoxView) {
//비밀번호 표시 체크 해제 할때
if cb.checkLabel.isHidden == false {
cb.checkLabel.isHidden = true
cb.checkBoxUIView.layer.borderColor = UIColor.gray.cgColor
cb.checkBoxUIView.layer.borderWidth = 1
cb.checkBoxUIView.backgroundColor = UIColor.white
} else{// 비밀번호 표시 체크 할 때
cb.checkLabel.isHidden = false
cb.checkLabel.textColor = UIColor.white
cb.checkBoxUIView.layer.borderWidth = 0
cb.checkBoxUIView.layer.cornerRadius = 5
cb.checkBoxUIView.backgroundColor = UIColor(red: 66/255, green: 133/255, blue: 244/255, alpha: 1)
}
}
}
참고한 블로그