programing

Swift에서 UIViewController 하위 클래스의 사용자 지정 이니셜라이저를 만드는 방법은 무엇입니까?

megabox 2023. 11. 5. 11:09
반응형

Swift에서 UIViewController 하위 클래스의 사용자 지정 이니셜라이저를 만드는 방법은 무엇입니까?

이전에 질문을 받은 적이 있다면 죄송합니다. 주변을 많이 찾아봤는데 상황이 달랐던 이전 스위프트 베타에서 나온 답변이 많습니다.확실한 답을 찾을 수가 없는 것 같습니다.

서브클래스 하고싶습니다.UIViewController코드로 쉽게 설정할 수 있도록 맞춤형 이니셜라이저를 가지고 있습니다.스위프트에서 이 일을 하는데 어려움을 겪고 있습니다.

나는.init()내가 특정한 것을 통과하는데 사용할 수 있는 함수.NSURL그러면 뷰 컨트롤러와 함께 사용하겠습니다.내 마음속에 그것은 어떤것처럼 보입니다.init(withImageURL: NSURL). 만약 내가 그 함수를 추가하면 그것은 나에게 그 함수를 추가하라고 요구합니다.init(coder: NSCoder)기능.

슈퍼클래스에 표시되어 있기 때문이라고 생각합니다.required키워드?그럼 서브클래스에서 해야 되는 건가요?추가합니다.

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

자 이제는 뭐죠?내 특별한 이니셜라이저는convenience하나? 지정된 거?슈퍼 이니셜라이저를 불러야 하나요?같은 반의 이니셜라이저?

특수 이니셜라이저를 어떻게 추가할 수 있습니까?UIViewController서브클래스?

class ViewController: UIViewController {
        
    var imageURL: NSURL?
    
    // this is a convenient way to create this view controller without a imageURL
    convenience init() {
        self.init(imageURL: nil)
    }
    
    init(imageURL: NSURL?) {
        self.imageURL = imageURL
        super.init(nibName: nil, bundle: nil)
    }
    
    // if this view controller is loaded from a storyboard, imageURL will be nil
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

UI를 코드로 작성하시는 분들께

class Your_ViewController : UIViewController {

    let your_property : String

    init(your_property: String) {
        self.your_property = your_property
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) is not supported")
    }
}

이것은 다른 대답들과 매우 비슷하지만 약간의 설명이 있습니다.승인된 답변은 해당 속성이 선택 사항이며 귀하의 답변에 대한 사실을 노출하지 않기 때문에 오해의 소지가 있습니다.init?(coder: NSCoder)각각의 속성을 초기화해야 하며 이에 대한 유일한 해결책은fatalError(). 궁극적으로 속성을 옵션으로 설정하면 벗어날 수 있지만 OP의 질문에 제대로 답하지는 못합니다.

// Think more of a OnlyNibOrProgrammatic_NOTStoryboardViewController
class ViewController: UIViewController {

    let name: String

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

    // I don't have a nib. It's all through my code.
    init(name: String) {
        self.name = name

        super.init(nibName: nil, bundle: nil)
    }

    // I have a nib. I'd like to use my nib and also initialze the `name` property
    init(name: String, nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle? ) {
        self.name = name
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")
    // The SYSTEM will never call this!
    // it wants to call the required initializer!

    init?(name: String, coder aDecoder: NSCoder) {
        self.name = "name"
        super.init(coder: aDecoder)
    }

    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")
    // The SYSTEM WILL call this!
    // because this is its required initializer!
    // but what are you going to do for your `name` property?!
    // are you just going to do `self.name = "default Name" just to make it compile?!
    // Since you can't do anything then it's just best to leave it as `fatalError()`
    required init?(coder aDecoder: NSCoder) {
        fatalError("I WILL NEVER instantiate through storyboard! It's impossible to initialize super.init?(coder aDecoder: NSCoder) with any other parameter")
    }
}

기본적으로 스토리보드에서 로드하는 것을 포기해야 합니다. 왜죠?

왜냐하면 뷰컨트롤러를 호출할 때storyboard.instantiateViewController(withIdentifier: "viewController")그러면 UIKit이 그 일을 하고 전화를 할 것입니다.

required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
}

해당 호출을 다른 init 메서드로 리디렉션할 수 없습니다.

문서:

이 메서드를 사용하여 프로그래밍 방식으로 표시할 뷰 컨트롤러 개체를 만듭니다.이 메서드를 호출할 때마다 다음을 사용하여 뷰 컨트롤러의 새 인스턴스를 만듭니다.init(coder:)방법.

그러나 프로그래밍 방식으로 작성된 viewController 또는 nib으로 작성된 viewController의 경우 위와 같이 해당 호출을 리디렉션할 수 있습니다.

편의 이니셜라이저는 보조적인 것으로 클래스의 이니셜라이저를 지원합니다.지정된 이니셜라이저의 일부 매개변수가 기본값으로 설정된 상태에서 편의 이니셜라이저와 동일한 클래스에서 지정된 이니셜라이저를 호출하도록 편의 이니셜라이저를 정의할 수 있습니다.편의 이니셜라이저를 정의하여 특정 사용 사례 또는 입력 값 유형에 대해 해당 클래스의 인스턴스를 생성할 수도 있습니다.

여기에 문서화되어 있습니다.

예를 들어 팝오버에 사용자 지정 init가 필요한 경우 다음 방법을 사용할 수 있습니다.

nibName 및 번들과 함께 super init을 사용하는 사용자 지정 init를 만든 후 뷰 속성에 액세스하여 뷰 계층의 로드를 강제로 수행합니다.

그런 다음 viewDidLoad 기능에서 초기화 시 전달된 파라미터로 뷰를 구성할 수 있습니다.

import UIKit

struct Player {
    let name: String
    let age: Int
}

class VC: UIViewController {


@IBOutlet weak var playerName: UILabel!

let player: Player

init(player: Player) {
    self.player = player
    super.init(nibName: "VC", bundle: Bundle.main)
    if let view = view, view.isHidden {}
}

override func viewDidLoad() {
    super.viewDidLoad()
    configure()
}

func configure() {
    playerName.text = player.name + "\(player.age)"
}
}

func showPlayerVC() {
    let foo = Player(name: "bar", age: 666)
    let vc = VC(player: foo)
    present(vc, animated: true, completion: nil)
}

언급URL : https://stackoverflow.com/questions/26923003/how-do-i-make-a-custom-initializer-for-a-uiviewcontroller-subclass-in-swift

반응형