관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 코드로 xib파일을 얻는 Protocol 정의 (StoryboardInstantiable) 본문

iOS 응용 (swift)

[iOS - swift] 코드로 xib파일을 얻는 Protocol 정의 (StoryboardInstantiable)

jake-kim 2021. 7. 11. 01:23

아이디어

  • 각 ViewController들은 해당 protocol들을 상속 받아서, Builder에서 해당 ViewController를 초기화 할때 정의된 함수 호출

StoryboardInstaiable 프로토콜 정의

public protocol StoryboardInstantiable {
    associatedtype ViewControllerType
    static var defaultFileName: String { get }
    static func instantiateViewController(_ bundle: Bundle?) -> ViewControllerType
}

default implementation

  • 클래스의 이름을 얻기 위해 NSStringFromClass() 사용

public extension StoryboardInstantiable where Self: UIViewController {
    static var defaultFileName: String {
        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
    }
}
  • xib 이름을 가지고 객체를 획득
    • storyboard 객체 획득
    • storyboard객체로 부터 ViewController를 얻어서 type casting
    • 주의: storyboard파일이름과 ViewController파일 이름이 같은 경우 사용
public extension StoryboardInstantiable where Self: UIViewController {
    static var defaultFileName: String {
        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
    }

    static func instantiateViewController(_ bundle: Bundle? = nil) -> Self {
        let fileName = defaultFileName
        let storyboard = UIStoryboard(name: fileName, bundle: bundle)
        guard let vc = storyboard.instantiateViewController(identifier: fileName) as? Self else {
            fatalError("Cannot instantiate initial view controller \(Self.self) from storyboard with name \(fileName)")
        }
        return vc
    }
}

사용방법

  • 화면 VC2 생성 (VC2.storyboard, VC2.swift)

  • VC2.swift에 StoryboardInstantiable conform
class VC2: UIViewController, StoryboardInstantiable {

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

}
  • VC2로의 화면전환
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {

            let vc2 = VC2.instantiateViewController(Bundle.main)
            self.present(vc2, animated: true, completion: nil)
        }
    }

}
Comments