[iOS] XIB 사용해보기 (feat.체크박스)

Yujin·2021년 10월 27일
0

iOS

목록 보기
2/5
post-thumbnail

💡xib를 알아야 하는 이유

iOS의 UI를 구성하는데에는 대표적으로 세가지 방법이 있다고 한다.

  1. Storyboard
  2. xib
  3. code

세 가지의 장단점은 대략 요렇다구 한다 !

UI 구현방식

아무쪼록 스토리보드와 코드의 장점을 적절하게 가져와서 편리하게 재사용하려면 xib 쓰는 법을 알아야 할 듯 하다.

💡xib, nib, Storyboard 어떻게 다른가

그런데 일단 xib,nib,,,어려운이름...무엇이 다른지, 뭐가 뭔지 모르겠어서 조사하던 중 아주 이해가 잘 되는 정리가 잘 된 글을 발견 ! (출처)

XIB,NIB, Storyboard 어디에 사용되나요?

  • XIB, NIB, Storyboard는 파일형태로 되어있고, 화면을 구성할때 사용됩니다 MVC 디자인 패턴을 위해 뷰 코드와 컨트롤러를 분리하는 목적으로 만들어진 파일 입니다

NIB 파일은 무엇인가요?

  • Nextstep Interface Builder의 약자로, 화면을 구성하는 클래스들을 바이너리 형태의 압축 파일로 저장하고 있습니다

바이너리로 이뤄져있는 NIB파일 내부를 바라본 모습 🔽

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F2211edaf-c3ca-49a9-84cd-8c118eaf0079%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F2211edaf-c3ca-49a9-84cd-8c118eaf0079%2Fimage.png)

XIB 파일은 무엇인가요?

  • Xcode Interface Builder의 약자로, 화면을 구성하는 클래스들을 XML문법에 맞춰 저장되고 있습니다.

XIB파일은 왜 생기게 되었나요?

  • 바이너리로 저장하지 않고 XML 형태로 저장하기 때문에 수정된 부분을 알 수 있어서 파일 관리가 아닌 소스코드로 관리가 가능해졌습니다.

XML형태의 XIB파일을 변경 후 비교해본 모습 🔽

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F55ec7983-ca6c-4d60-99a9-1708b5e9d783%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F55ec7983-ca6c-4d60-99a9-1708b5e9d783%2Fimage.png)

  • 직접 수정하려면 XML문법을 맞춰서 수정해야되기 때문에 번거로울 수 있지만, Xcode에선 Interface Builder를 제공하여 XML 형태가 아닌 그래픽 형태로 수정할 수 있게 도와줍니다.

XIB파일을 Xcode의 Interface Builder로 본 모습 🔽

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fab15dee8-0306-4430-b405-74b99188e5f3%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fab15dee8-0306-4430-b405-74b99188e5f3%2Fimage.png)

프로그램이 뷰 정보를 읽어들이는 방법

  • 뷰 정보를 담고 있는 XIB파일을 빌드하게 되면, 접근하기 쉬운 바이너리 NIB파일로 컴파일 되고, 앱의 번들(앱 실행에 사용되는 파일이 저장된 폴더)로 복사된 후 실행파일에서 사용됩니다.

XIB를 컴파일하면 NIB가 만들어집니다 🔽

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F4fccccec-aea9-44ee-9d9f-1b2b71ebe86d%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F4fccccec-aea9-44ee-9d9f-1b2b71ebe86d%2Fimage.png)

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fc6e40de8-0a53-4fb1-b895-a77cc74e2a92%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fc6e40de8-0a53-4fb1-b895-a77cc74e2a92%2Fimage.png)

XIB파일이 빌드과정후 생성된 app 패키지안에 NIB파일로 저장된 모습 🔼

그렇다면 Storyboard는 무엇인가요?

  • 스토리 보드는 뷰 정보와 뷰와 뷰 사이의 관계에 대한 정보를 가지고 있는 파일 입니다. 그렇기 때문에 뷰 정보인 XIB의 내용과 뷰 관계정보를 포함하고 있어서 XML로 이뤄져 있습니다. 빌드를 하게 되면 컴파일된 storyboard파일로 .storyboardc라는 파일이 생성됩니다.
  • .storyboardc 파일은 패키지 파일로 되어있고 이 내부는 nib파일과 nib파일을 관리하는 plist파일이 존재합니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fbf403fff-dc46-483e-a846-f2248bdd0099%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fbf403fff-dc46-483e-a846-f2248bdd0099%2Fimage.png)

.storyboardc파일의 패키지 내부 모습 🔼

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fc41e3d63-6f45-405f-9275-a5bfd6e283f2%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fc41e3d63-6f45-405f-9275-a5bfd6e283f2%2Fimage.png)

Storyboard파일 내부 구조 🔼

이렇게 xib는 뷰를 나타낸 xml파일이고 nib는 xib를 컴파일하면 생성되는 바이너리 파일이라는 것으로 정리가 되었고 ! 이제 본격적으로 xib파일로 커스텀뷰를 만들어보자.

💡xib로 본격적으로 CheckBox 만들어보기

1. xib, swift 파일 만들기

아래 사진처럼 checkbox를 구현하기 위해 CheckBoxView.xib와 CheckBoxView.swift를 만들어 주겠습니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F547850ba-e5d1-4c1d-993e-b821e4767b8e%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F547850ba-e5d1-4c1d-993e-b821e4767b8e%2Fimage.png)

CheckBoxView.xib 만들기

xib파일을 만들 때는 사진처럼 User Interface의 View를 선택하여 만들어 줍니다!

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fa6df3d92-abe1-432c-b1e3-499221eac31e%2FUntitled.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fa6df3d92-abe1-432c-b1e3-499221eac31e%2FUntitled.png)

CheckBoxView.swift 만들기

그 다음으로는 뷰를 관리하기 위해 UIView를 상속받는 클래스를 만들어줍니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F61d36391-448d-448d-b234-19cde6aa8db1%2FUntitled%201.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F61d36391-448d-448d-b234-19cde6aa8db1%2FUntitled%201.png)

2. xib 파일의 File's Owner의 Class 설정

.xib, .swift 파일을 생성했으니 이제 두 파일을 연결할 차례입니다.

두 파일을 연결해주면 UILabel이나 UIButton과 같이 UIView를 상속하는 나만의 CustomView로 사용할 수 있습니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F04beacb6-2396-423a-8c7c-a9bfcde8bac6%2FUntitled%202.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F04beacb6-2396-423a-8c7c-a9bfcde8bac6%2FUntitled%202.png)

.xib 파일을 열고 Placeholders 아래에 있는 File's Owner를 클릭하고 Attributes Inspector 탭에 File's Owner의 Class를 지정하는 곳이 있는데 여기에 CustomView를 입력해주면 화면과 소스가 연결 됩니다.

아래는 용어 설명 참고,,,

Placeholders: 의미 그대로 UIView처럼 보여지는 주요 요소가 아닌, 빠져있는 것을 대신하여 연결해주는 역할을 의미

File's Owner : nib 파일을 앱코드와 연결시켜주는 객체 (nib파일의 내용을 책임지는 컨트롤러)

  • nib파일(customView생성 시 .xib파일)을 로드할 때 File's Owner객체를 보고 지정한 대체 객체를 생성하여 nib파일에서 해당 객체들을 참조 할 수 있도록 하는 개념
  • File's Owner객체에서 nib파일에 저장된 top-level 객체의 참조를 유지하기 위해서 사용하는 것이 @IBOutlet

First Responder 객체: Responder 객체가 이벤트를 받으면 이를 처리하거나 다른 Responder객체에게 처리할 수 있도록 넘겨야할 의무가 존재, UIKit은 적절한 Responder를 지정해서 이벤트를 넘겨서 처리하는데, 처음으로 이벤트를 받는 Responder를 First Responder로 지칭
(Responder Chain 공부 필요..)

3. 뷰 그리기

View의 size와 AutoLayout 설정

우리가 만들어준 view의 size를 Freeform으로 설정하여 화면의 크기를 자유자재로 바꿀 수 있게 해줍니다.
safe area를 체크해제 안하면 auto layout에서 버그가 생기는 경우가 존재하므로 채크해제를 해줍니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F22899f50-2cc8-4b7b-ac73-681c2a1fe46f%2FUntitled%205.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F22899f50-2cc8-4b7b-ac73-681c2a1fe46f%2FUntitled%205.png)

정사각형의 뷰를 만들 것이기 때문에 width와 height를 1:1 비율로 설정해 줍니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F7bddbcf9-9097-43c0-9b8c-295258753fa9%2FUntitled%206.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F7bddbcf9-9097-43c0-9b8c-295258753fa9%2FUntitled%206.png)

UIView와 UILabel 추가해주기

버튼 테두리를 위한 UIView를 추가하고 그 안에 Text가 ✓인 UILabel을 추가하고 Constraints를 지정해줍니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F480e2547-af77-412d-934e-b77178792e84%2FUntitled%207.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F480e2547-af77-412d-934e-b77178792e84%2FUntitled%207.png)

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fe9599e33-414e-4651-8355-66e14b9d5bfb%2FUntitled%208.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fe9599e33-414e-4651-8355-66e14b9d5bfb%2FUntitled%208.png)

4. CustomView 초기화

checkBoxView는 우리가 만들어준 View이기 때문에 직접 초기화를 해줘야 합니다.

일단 아까 만들어준 view를 모두 @IBOutlet 해줍니다.
checkBoxView는 xib 루트 뷰이고
나머지 둘은 우리가 추가해 준 UI object들입니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2Fff29ae45-8ee8-46c8-a1c9-276dbee2e683%2FUntitled%209.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2Fff29ae45-8ee8-46c8-a1c9-276dbee2e683%2FUntitled%209.png)

여기서 초기화를 위한 함수로 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

    }

5. CheckBoxView.swift 코드

checkBox를 눌렀을 때 실행될 checkBoxHighLight() 함수는 delegate로 만들어 viewcontroller에서 구현 되도록 할 것 입니다.
따라서 CheckBoxDelegate프로토콜을 만들어 checkBoxHighLight()를 선언해 놓습니다. CheckBoxViewDelegate.swift 파일을 따로 만들어 주면 좋지만 귀찮아서 그냥 CheckBoxView.swift 맨위에 넣어주었습니다.

protocol CheckBoxDelegate: class {
    func checkBoxHighlight(cb: CheckBoxView)
}

CheckBoxView class 안에 delegate 변수를 추가 해줍니다

var delegate: CheckBoxDelegate?

checkBoxClicked() 함수

제스처가 생겼을 때 호출 될 함수 안에 델리게이트 함수를 넣어준다.

@objc func checkBoxClicked(_ sender: Any) {
            // CheckBoxDelegate 함수 호출
            delegate?.checkBoxHighlight(cb: self)
        }

6. Main.storyboard에 뷰 추가

UIView를 추가해주고 Class 이름을 CheckBoxView로 지정해줍니다.

![https://velog.velcdn.com/images%2Ffocusonmx%2Fpost%2F58d65c58-5b42-421d-9070-20257ee52f0b%2Fimage.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Ffocusonmx%2Fpost%2F58d65c58-5b42-421d-9070-20257ee52f0b%2Fimage.png)

7. ViewController 코드

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)

        }
    }
}

참고한 블로그

profile
하나하나 알아가는 하루하루

0개의 댓글