2017-12-02 1 views
1

私のiOSアプリケーションでは、複数の親のViewControllersに共通のモーダルViewController(それをGetDataと呼ぶことができます)が必要です。 GetDataを設定する必要があります(hide/showのようにViews)。 GetDataは、ViewControllerという呼び出しにデータを返すことができるはずです。ここでReuseable&Configurable ViewControllerの実装

は、私がウェブ上のSOおよび他のソース上の私の読書に基づいて、それを実装しようとしている仕組みを簡略化したものです:

// ViewController.swift 

import UIKit 

class ViewController: UIViewController, GetDataDelegate { 

    // This shows the data received from GetData 
    @IBOutlet weak var textviewResult: UITextView! 

    // Call GetData with only mandatory and without optional views 
    @IBAction func onClickGetData(_ sender: Any) { 
     let getData = GetData(caller: self) 
     getData.display(delegate: self) 
    } 

    // Call GetData with both mandatory and optional data views 
    @IBAction func onClickGetDataWithOptional(_ sender: Any) { 
     let getData = GetData(caller: self, hasOptional: true) 
     getData.display(delegate: self) 
    } 

    // Delegate function to received data sent by GetData 
    func gotData(data1: String, data2: String!) { 
     textviewResult.text = "Mandatory: \(data1)" 
       + (data2 != nil ? "\nOptional: \(data2!)" : "") 
    } 
} 

// GetData.swift 

import UIKit 

protocol GetDataDelegate { 
    func gotData(data1: String, data2: String!) 
} 

class GetData: UIViewController { 

    @IBOutlet weak var textfieldMandatory: UITextField! 
    @IBOutlet weak var textfieldOptional: UITextField! 
    // View with the optional views 
    @IBOutlet weak var stackViewOptional: UIStackView! 

    var delegate:GetDataDelegate? 
    var caller:UIViewController? 
    var hasOptional:Bool? 

    init(caller: UIViewController, hasOptional: Bool? = false) { 
     super.init(nibName: "GetData", bundle: nil) 

     self.caller = caller 
     self.hasOptional = hasOptional 
    } 

    func display(delegate:GetDataDelegate) { 
     self.delegate = delegate 

     let viewController = UIStoryboard(name: "GetData", bundle: nil).instantiateViewController(withIdentifier: "GetData") 
     viewController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext 
     viewController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve 

     caller?.present(viewController, animated: true, completion: nil) 
    } 

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

    @IBAction func onSubmit(_ sender: Any) { 
     self.dismiss(animated: true, completion: nil) 
     delegate?.gotData(data1: textfieldMandatory.text!, data2: hasOptional! ? textfieldOptional.text! : nil) 
    } 

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

     // Configure GetData (hide/show views) 
     // But hasOptional is nil! 
     //stackViewOptional?.isHidden = !hasOptional! 
    } 
} 

私が直面しています次の問題:

  1. delegateGetDataで呼び出されていません。
  2. GetDataviewsfuncviewWillAppear)に変更できません。

上記の両方が(funcviewWillAppear中)(funconSubmitで)membersdelegatehasOptionalも初期化後nilあるためと思われます。

修正する必要があるか、別の方法を採用する必要がありますか?

注::上記は簡略化されています。私の実際の使用例では、の有無にかかわらず、GetDataを呼び出す複数のView Controllerがあります。

+0

正しいアプローチであります同じクラスの別のインスタンス( 'instantiateViewController')を後で作成するクラス' GetData'の呼び出し元( 'caller:')ですか? – vadian

答えて

0

私は最終的にそれは私の要件に従って作業しました:

// ViewController.swift 

import UIKit 

class ViewController: UIViewController, GetDataDelegate { 

    // This shows the data received from GetData 
    @IBOutlet weak var textviewResult: UITextView! 

    // Call GetData with only mandatory and without optional views 
    @IBAction func onClickGetData(_ sender: Any) { 
     GetData.generate(caller: self) 
    } 

    // Call GetData with both mandatory and optional data views 
    @IBAction func onClickGetDataWithOptional(_ sender: Any) { 
     GetData.generate(caller: self, hasOptional: true) 
    } 

    // Delegate function to received data sent by GetData 
    func gotData(data1: String, data2: String!) { 
     textviewResult.text = "Mandatory: \(data1)" 
       + (data2 != nil ? "\nOptional: \(data2!)" : "") 
    } 
} 

// GetData.swift 

import UIKit 

protocol GetDataDelegate { 
    func gotData(data1: String, data2: String!) 
} 

class GetData: UIViewController { 

    @IBOutlet weak var textfieldMandatory: UITextField! 
    @IBOutlet weak var textfieldOptional: UITextField! 
    // View with the optional views 
    @IBOutlet weak var stackViewOptional: UIStackView! 

    var delegate:GetDataDelegate? 
    var hasOptional:Bool? 

    static func generate(caller: UIViewController, hasOptional: Bool? = false) { 
     let getData = UIStoryboard(name: "GetData", bundle: nil).instantiateViewController(withIdentifier: "GetData") as! GetData 
     getData.delegate = caller as? GetDataDelegate 
     getData.hasOptional = hasOptional 
     caller.present(getData, animated: true, completion: nil) 
    } 

    @IBAction func onSubmit(_ sender: Any) { 
     self.dismiss(animated: true, completion: nil) 
     delegate?.gotData(data1: textfieldMandatory.text!, data2: hasOptional! ? textfieldOptional.text! : nil) 
    } 

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

     // Configure GetData (hide/show views) 
     stackViewOptional?.isHidden = !hasOptional! 
    } 
} 

希望これは...( `INITインスタンスを作成する目的は何

0

私はこれがコンテナでよりうまく実装できると思います.1つの画面に複数のView Controllerを持つことができます。 Dave DeLongはこのアプローチについてgreat articlesを書きました。

関連する問題