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() 사용
- class 타입을 받아서 그 클래스의 이름을 string으로 return
- Self.self는 해당 type을 return (Self와 self의 개념 참고)

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)
}
}
}