2017-11-17 1 views
1

TabBarController를 던지는 두 ViewController간에 데이터 전달을 원합니다. 첫 번째 ViewController 안에는 텍스트 필드와 버튼이 있습니다. 두 번째 레이블 안에 위치. textField 및 푸시 버튼에 텍스트를 쓸 때이 텍스트가 두 번째 ViewController의 Label에 나타날 것으로 예상됩니다. 그러나 아무 일도 일어나지 않습니다.TabBar 컨트롤러에 데이터 전달

그리고 내 코드 :

최초의 ViewController :

import UIKit 

class FirstViewController: UIViewController { 
    @IBOutlet weak var textField: UITextField! 

    @IBAction func enter(_ sender: Any) { 
     if textField.text != "" { 
      if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController, let second = tabBarController.viewControllers?.first as? SecondViewController { 
       second.label.text = textField.text 
       tabBarController.selectedIndex = 0 
      } 
     } 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


} 

두 번째의 ViewController :

import UIKit 

class SecondViewController: UIViewController { 

    @IBOutlet weak var label: UILabel! 
    var myString = String() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     label.text = myString 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


} 

enter image description here

답변

0

나는 문제가

,369에 생각
tabBarController.viewControllers?.first as? SecondViewController 

당신은 아마 대신이 작업을 수행 할 수 :

tabBarController.viewControllers?[1] as? SecondViewController 

그렇게 viewControllers?[1] 실제로 배열의 두 번째 요소를 반환, 배열은 0에서 색인 잊지 마세요.

+0

치명적인 오류 : 옵션 값 없음을 풀기 동안 예기치 않게 당신이 (가)'않고 직접 다른 속성과 viewDidAppear''에서 SecondVC에서 변경 label.text' 변경하지 마십시오 –

0

먼저 탭을 나타내는 사용자의보기 컨트롤러가 TabBarController에 연결된 탐색 컨트롤러에 포함되어야한다고 생각합니다.

두 번째로, 컨트롤러간에 데이터를 보내는 데 권장되는 방법은 프로토콜 (대리자)을 사용하는 것입니다. 다음은 단계별로 확인할 수있는 좋은 예입니다. https://medium.com/@jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef

그러나 솔루션의 빠른 수정을 원하는 경우 Bruno Phillipe의 답변에 어느 정도 도달했다고 생각되지만 그다지 중요하지 않습니다. 어떤 컨트롤러가 뷰 컨트롤러 목록의 어떤 인덱스에 있는지 확실히 알 수 없습니다. 자신

나는 그것을 시도하고 문제는 당신이 실제로 레이블 구성 요소가 초기화되지 않았다 때 label.text을 설정하려고했던 것입니다 :

@IBAction func enter(_ sender: Any) { 
    if textField.text != "" { 
     if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController { 

      //check if there are view controllers in the tabBarController 
      guard let vcList = tabBarController.viewControllers else { 

       return 
      } 

      for controller in vcList { 

       if let second = controller as? SecondViewController { 
        //this will be executed only when a controller is SeconfViewController 
        second.label.text = textField.text 
        tabBarController.selectedIndex = 0 
       } 
      } 

     } 
    } 
} 

편집 : 나는이 일을한다고 생각합니다. 난 당신이 단순히 (확실하지) 작동합니다 SecondViewController myString 변수에 textField 값을 저장하는 경우 생각합니다.

그러나 컨트롤러간에 데이터를 전송하는 올바른 방법 인 프로토콜 (대리자)을 사용하는 솔루션이 있습니다. 당신이 가질 수있는 질문을하십시오. 이 작업을해야합니다 :

FirstViewController :

import Foundation 
import UIKit 

protocol LabelChangeDelegate: class { 

    func changeLabelWithText(_ text: String?) 
} 

class FirstViewController: UIViewController { 

    weak var delegate: LabelChangeDelegate? 

    @IBOutlet weak var textField: UITextField! 

    @IBAction func enter(_ sender: UIButton) { 

     if textField.text != "" { 
      if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController { 

       //check if there are view controllers in the tabBarController 
       guard let vcList = tabBarController.viewControllers else { 

        return 
       } 

       for controller in vcList { 

        if let second = controller as? SecondViewController { 
         //this will be executed only when a controller is SeconfViewController 

         //set the delegate - who needs the data 
         delegate = second 
         //call the delegate function which will commmunicate with the delegate 
         delegate?.changeLabelWithText(textField.text!) 
         //don't know why you need this 
         tabBarController.selectedIndex = 0 
        } 
       } 

      } 
     } 
    } 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


} 

SecondViewController :

import Foundation 
import UIKit 

class SecondViewController: UIViewController, LabelChangeDelegate { 

    @IBOutlet weak var label: UILabel! 

    //lazy init 
    lazy var myString = String() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     //set label when the view loads, not in the first controller 
     label.text = myString 

     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    //delegate function 
    func changeLabelWithText(_ text: String?) { 
     guard let sentText = text else { 

      //no text sent 
      return 
     } 

     myString = sentText 
    } 

} 
+0

(= 작동하지 않는, 전무 발견 , 그 속성에서'label.text'을 만드십시오 – ahmed

+0

어쨌든, 고맙습니다. 어쨌든 고마워요 :) –

+0

Welcome @Kristian – ahmed

0

난 당신이 이런 식으로 할 것을 추천하고 있지 않다. 이것은 이해를위한 설명입니다.

  1. tabBarController의 viewController는 tabBarController을 알고 있습니다. self.tabBarController으로 액세스 할 수 있습니다.
  2. secondViewControllerviewControllers의 목록에서 두 번째이므로 let second = tabBarController.viewControllers?[1] as? SecondViewController입니다.
  3. secondViewController을 아직 방문하지 않은 경우 뷰가로드되지 않으므로 콘센트는 여전히 nil입니다. 보기를 강제로 _ = second.view과 함께로드 할 수 있습니다.
  4. 두 번째 탭으로 전환하려면 tabBarController.selectedIndex = 1을 사용해야합니다.
    @IBAction func enter(_ sender: Any) { 
        if textField.text != "" { 
         if let tabBarController = self.tabBarController as? UITabBarController, let second = tabBarController.viewControllers?[1] as? SecondViewController { 
          // make sure view has loaded 
          _ = second.view 
    
          second.label.text = textField.text 
    
          // change to second tab 
          tabBarController.selectedIndex = 1 
         } 
        } 
    } 
    

    더 좋은 방법


...

대신 직접 콘센트를 설정하는, 대신 SecondViewController의 속성에 문자열을 전달해야합니다

second.myString = textField.text ?? "" 

그리고 나서 assig n 해당 문자열을 label에 겹쳐서 지정합니다. viewWillAppear.

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    label.text = myString 
} 

viewWillAppear에서 설정하는 이유는보기가 표시되기 전에 viewWillAppear 때마다 실행하는 것입니다. viewDidLoad은보기를 처음로드 할 때 한 번만 실행됩니다. 기능이 여러 번 작동하기를 원하므로 viewWillAppear이 올 바릅니다.

관련 문제