2017-06-15 12 views
1

私はAPIから取得している5つのイベントをページビューコントローラに取り込みしようとしています。アイデアは、ユーザーが最新の上位5つのイベントを参照してイベントをクリックすることで、イベントの詳細を表示できることです。私が実行している問題は、イベントを取得すると、ページビューコントローラのビューコントローラをリロードしたいのですが、ビューコントローラを設定しようとするとエラーが発生します:fatal error: unexpectedly found nil while unwrapping an Optional value私は一連のイベントのプロパティーオブザーバーを設定して、一度設定されるとView Controllerをリロードします。これは私のクラスがどのように見えるかです:UIPageViewControllerでView Controllerを設定できないのはなぜですか?

class EventPageViewController: UIPageViewController { 

var eventViewControllers = [EventViewController]() 

var events: [Event] = []{ 
    didSet { 
     self.reloadViewControllers() 
    } 
} 


func reloadViewControllers(){ 

    self.dataSource = nil 
    self.dataSource = self 
    // Get top 5 events 
    let topFiveEvents = Array(events.prefix(5)) 
    print(self.events.count) 
    self.eventViewControllers.removeAll() 
    print(eventViewControllers.count) 

    // Set up view controllers 
    for event in topFiveEvents{ 
     if let controller = self.storyboard?.instantiateViewController(withIdentifier: "event") as? EventViewController{ 
      print(event.title) 
      // Just this line alone is what crashes the app 
      controller.eventTitle.text = event.title 
      self.eventViewControllers.append(controller) 
     } 
    } 

    if self.eventViewControllers.count != 0 { 
     let first = [self.eventViewControllers[0]] 
     self.setViewControllers(first, direction: .forward, animated: false, completion: nil) 

    } 


} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    let timeMin = GTLRDateTime(date: Date()).rfc3339String 
    let params = ["maxResults": "250", 
        "singleEvents": "true", 
        "timeMin": timeMin] 
    NetworkManager.events(forPark: .all, withParameters: params, query: nil) { (events, error) in 
     if error == nil { 
      DispatchQueue.main.async { 
       self.events = events 
      } 
     } 
    } 
} 

override func viewDidLayoutSubviews() { 
    for subView in self.view.subviews { 
     if subView is UIScrollView { 
      subView.frame = self.view.bounds 
     } else if subView is UIPageControl { 
      let pageControl = subView as! UIPageControl 
      pageControl.currentPageIndicatorTintColor = UIColor(red:0.00, green:0.15, blue:0.29, alpha:1.0) 
      pageControl.pageIndicatorTintColor = UIColor(red:0.00, green:0.15, blue:0.29, alpha:0.30) 
      self.view.bringSubview(toFront: subView) 


     } 
    } 
    super.viewDidLayoutSubviews() 
} 



} 

私はビューコントローラには何も設定しない場合、私はページビューコントローラは、静的な情報でView Controllerを表示するために取得します。私は何が間違っているのか分かりません。

答えて

0

あなたのページビューコントローラがその子ビューコントローラのビューを直接操作しようとしているように見えます。それをしないでください。

このライン:

controller.eventTitle.text = event.title 

eventTitleがアウトレットであると仮定すると、原因である可能性があり。

の代わりにあなたの子ビューコントローラに文字列プロパティを追加することをやって:

public var eventTitleString: String 

そして代わりにすることを設定します。

controller.eventTitleString = event.title 

そして、あなたの子ビューコントローラでは、コピーするコードを追加しますあなたのフィールドにその値:

func viewWillAppear(_: animated: Bool) { 
    super.viewWillAppear(animated) 
    eventTitle.text = eventTitleString 
} 

@MrSaturnはを呼び出す示唆します、あなたのクラッシュを修正する可能性がありますが、それは悪い習慣です。ビューコントローラのビューをプライベートとして扱い、外部から操作することは決してしないでください。代わりに、ビューコントローラのビューを直接更新するパブリックプロパティまたは関数を追加します。

+0

ありがとうございます、私は子ビューコントローラのビューを操作することは悪い習慣でしたが、あなたの解決策が働いたことは分かりませんでした。 – CornWhip

+0

「カプセル化」の原則は、オブジェクト指向設計の基本的なものです。オブジェクトを設計するときに、オブジェクトが他のオブジェクトに提供するサービスに対するパブリック "契約"について考えてみてください。その部分は公開され、他のオブジェクトが使用できるようにする必要があります。それ以外はプライベートなもので、オブジェクト自体の外には限界があります。このようにして、オブジェクトは他のオブジェクトの実装の詳細に敏感ではありません。パブリックインターフェイスが安定している限り、内部は大きくても小さくても変更でき、すべてが引き続き機能します。 –

+0

ユーザからの入力を収集して別のView Controllerに報告するビューコントローラを作成する場合、そのView Controllerは、自由に異なるタイプのコントロールを使用するか、ユーザに情報を表示する必要があります。同じプロパティとメソッドを持つことだけが必要です。別のオブジェクトがView Controllerのビューを直接操作すると、View Controllerを常に同じ方法で実装するようにロックします。 –

関連する問題