class PlanetDetailViewController: UIViewController {
@IBOutlet weak var backgroundImageView: UIImageView!
var planet: Planet?
...
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let cell = sender as? UICollectionViewCell, let indexPath = planetCollectionView.indexPath(for: cell){
let selected = solarSystemPlanets[indexPath.item]
if let vc = segue.destination as? PlanetDetailViewController{
vc.planet = selected
}
}
}
- iOS 앱개발에서 prepareForSegue에서 Property Injection을 하는 방식은 꾸준히 사용되어오는 패턴이다.
- iOS13버전 이전에서 Property Injection이 아닌 Initialization Injection을 사용하려면 Segue를 사용하지 못하고 코드로 구현해야 한다.
뷰 컨트롤러를 만들고 화면을 전환하는 것까지 말이다. 왜냐하면, Segue는 destination vc를 자동으로 만드는데 원하는 생성자를 호출하거나 vc 생성자로 내가 원하는 파라미터를 전달하는 방법이 없기 때문이다.
- 이러한 문제 때문에 iOS13에서
Segue Action
이 도입되었다.
- 해당 방법을 통해 VC를 자동으로 생성하는 부분을 제어할 수 있게 되었다.
Segue Action
storyboard에서 연결
- segue를
ctrl+drag
하여 Segue Action을 추가 가능하다.
destination VC 생성자 추가
class PlanetDetailViewController: UIViewController {
@IBOutlet weak var backgroundImageView: UIImageView!
private let planet: Planet
init?(planet: Planet, coder: NSCoder){
self.planet = planet
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
let img = UIImage(named: planet.englishName.lowercased())
backgroundImageView.image = img
}
- 여기서 initializer을 추가할 때 required Initializer, failable Initializer 에러가 발생한다.
- vc의 init을 만들 때 반드시 required init? 생성자를 overrider 해야하며, 실제 init 추가시에도 이 형식에 맞춰
init?
으로 작성해야 하며, 반드시 인자에 codeR:NSCoder
을 포함해야 한다.
segueAction에서 destination VC init? 호출
class MainViewController: UIViewController {
@IBOutlet weak var planetCollectionView: UICollectionView!
@IBSegueAction func makeDetailVC(_ coder: NSCoder, sender: Any?) -> PlanetDetailViewController? {
guard let cell = sender as? UICollectionViewCell, let indexPath = planetCollectionView.indexPath(for: cell) else {
return nil
}
let selected = solarSystemPlanets[indexPath.item]
return PlanetDetailViewController(planet: selected, coder: coder)
}
NSCoder
는 스토리보드에서 VC를 만들 때 필요한 객체이다.
Property Injection과 차이
- PI가 이해가 쉽고 구현 코드 양이 적음
- PI가 iOS 13 이전과도 호환성이 좋음
- PI가 은닉성이 떨어짐
- 변수 속성이 선언하고 optional이 강제됨