iOS) 커스텀 뷰 Xib 연결하기

3 minute read

두가지 방법을 통해서 커스텀 뷰 클래스를 Xib 와 연결해서 만들어보자!

그리고 좀 더 고민해볼 점까지 같이 알아봐요!

🧙‍♀️ 방법1 : File’s Owner 에서 Custom Class 설정

File's Owner : File’s Owner 객체를 사용해서 nib 파일의 top-level 객체들을 참조할 수 있도록 한다. 우리가 IBAction, IBOutlet 에 해당하는 것을 연결할 수 있게 해주는 것은 이 참조가 가능하기 때문이다.

1

해당 뷰를 가져오기 위해서 UIView 클래스에서 nib 형태로 가져와야 합니다.

이때! 두가지 방법으로 가져올 수 있어요!

// CustomNavigationBar.siwft
// 역할 : 커스텀 네비게이션 바

class CustomNavigationBar: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        customInit()
        //alternativeCustomInit()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        customInit()
        //alternativeCustomInit()
    }
    
    //방법 1: loadNibNamed(_:owner:options:) 사용
    func customInit() {
        if let view = Bundle.main.loadNibNamed("CustomNavigationBar", owner: self, options: nil)?.first as? UIView {
            view.frame = self.bounds
            addSubview(view)
        }
    }
    
    //방법 2: UINib 생성 후 instantiate
    func alternativeCustomInit() {
        if let view = UINib(nibName: "CustomNavigationBar", bundle: nil).instantiate(withOwner: self, options: nil).first as? UIView {
            view.frame = self.bounds
            addSubview(view)
        }
    }
}

📌 loadNibNamed(_:owner:options:)

receiver’s bundle 에 위치하는 nib 파일의 컨텐츠를 언아카이브 한다.

(Xib 파일이 저장되면 Xib 파일을 아카이브하는데 아카이브한 데이터로부터 객체를 다시 만드는 것이 언아카이브이다.)

  • name : nib 파일의 이름
  • owner : nib 의 Files’s Owner 객체로 할당할 객체
  • options : nib 파일을 열 때 사용할 옵션이 포함된 dictionary.

📌 init(nibName:bundle:)

특정 번들의 nib 파일로부터 nib 객체를 반환한다.

  • nibName : nib 파일의 이름.
  • bundle : nil 설정시 main bundle 에서 nib 파일을 찾는다.

📌 instantiate(withOwner:options:)

nib 객체의 nib 파일에 있는 메모리내 컨텐츠를 언아카이브하고 고유한 객체 트리와 top-level 객체 집합을 만든다. (부모 객체를 가지지 않는 것들. 윈도우, 메뉴 바, 커스텀 컨트롤러 객체)

  • withOwner : nib 파일의 owner 로 사용할 객체.
  • options : nib 파일을 열 때 사용할 옵션이 포함된 dictionary.

❗️ Xib 에서 설정한 Custom Class 는 소유할 클래스의 타입을 설정한 것이고(이것으로 IBAction, IBOutlet 등 연결가능.) 위의 코드로 owner 의 instance 를 설정한다.


📌 .first

3

위의 메서드들은 반환값이 [Any] 즉, 배열입니다! Xib 가 위에처럼 여러개의 View 를 가질 수 있기 때문에 배열로 리턴을 해주죠! 그래서 우린 첫번째 View 를 가져올 것이기 때문에 .first 를 사용합니다.

(✨ 첫번째가 아닌 원하는 타입의 객체를 가져오기 위해서 is 연산자로 찾을 수 있다.)

스토리보드에서 커스텀뷰를 설정해주면 끝!

2

⁉️ 초기화 함수 init 를 호출하지 않았는데 어떻게 load 된 것일까요?

스토리보드에서 커스텀 클래스를 설정했기 때문에 nib 파일을 unarchive 하고 커스텀 뷰의 init(coder: NSCoder) 를 호출한다고 해요! 그러면 customInit() 메서드가 실행되겠죠?

🧙‍♀️ 방법2 : View 에서 Custom Class 설정

4

View 의 Custom Class 로만 변경하고 실행했을 때는 앱이 갑작스럽게 죽게 됩니다..!

5

customInit()init(coder:) 의 반복으로 앱이 죽게되었는데요. 과정을 살펴봅시다!

1.뷰컨트롤러가 로딩된 후 커스텀 뷰의 init(coder: NSCoder) 호출

2.커스텀뷰의 customInit() 호출

  1. loadNibName 으로 Xib 로드

4.Xib 의 first View 의 Custom Class 는 커스텀뷰로 설정된 상태. 커스텀뷰의 init(coder: NSCoder 재호출.

5.2번으로 간다.

이렇게 무한루프를 돌면서 앱이 죽게됩니다! 🥲

해결

init 메서드에서 같은 클래스의 Xib 를 로드하지 마세요!

그렇다면 어디서 하면 될까요? 부모클래스나 뷰컨트롤러에서 Xib 를 로드하면 됩니다.

// ViewController.swift

@IBOutlet weak var customNavigationBar: UIView!

// ...

override func viewDidLoad() {
        super.viewDidLoad()
        // ...

        // ✅ 이번에는 nib 파일 이름을 String(describing:) 으로 가져와봤어요!
        guard let loadedNib = Bundle.main.loadNibNamed(String(describing: CustomNavigationBar.self), owner: self, options: nil) else { return }
        guard let navigationBar = loadedNib.first as? CustomNavigationBar else { return }
        navigationBar.frame = CGRect(x: 0, y: 0, width: customNavigationBar.frame.width, height: customNavigationBar.frame.height)
        customNavigationBar.addSubview(navigationBar)
}

이렇게 되면 스토리보드에서 커스텀뷰를 설정해주는 단계는 건너뛰어도 되겠죠?

출처:

[iOS - swift] nib, xib, Placeholders, Files’s Owner, First Responder, Responder Chain 개념

[Swift] 커스텀 뷰 xib 연결하기 : File’s Owner vs Custom Class

고민해볼 점이 있어요! 바로..!

UIView 는 File’s Owner 가 될 수 없다…?

커스텀뷰를 Xib 로 만드는 방법을 찾아보다가 아래 출처의 글을 읽어보게 되었는데요!

요약해보자면

  • 애플개발자 문서에서는 File’s Owner 에 대한 설명으로 nib 파일의 top-level 객체를 참조한다고 하는데! UIView 는 top-levle 의 조건을 만족하지 못한다!
  • Xib 는 다양한 UIView 객체를 가질 수 있게 만들어졌다. 근데 File’s Owner 는 하나만 을 가질 수 있다. 그러면 다양한 UIView 객체를 Xib 가 가질 때 File’s Owner 는 한개의 UIView 클래스이면서 다수의 UIView 클래스 타입이라는 말인가? 아이디어가 모순적이다!

라는 내용을 가지고 있는데요! 충분히 저희가 생각해볼만 한 것 같아요! 더 자세한 내용은 출처를 참고해주세요!

출처 :

UIView 는 File’s Owner 가 될 수 없어요

Categories:

Updated: