UIPickerView 委托未在子视图中调用

Posted

技术标签:

【中文标题】UIPickerView 委托未在子视图中调用【英文标题】:UIPickerView delegate not called in a subview 【发布时间】:2018-06-02 22:11:04 【问题描述】:

我有一个简单的 ios 应用程序,它使用 UISegmentedControl 在两个选项卡之间切换。

在 ViewController.swift 中:

import UIKit

class ViewController: UIViewController 

    @IBOutlet weak var segment: UISegmentedControl!
    @IBOutlet weak var viewContainer: UIView!
    var searchView: UIView!
    var favView: UIView!

override func viewDidLoad() 
    super.viewDidLoad()
    searchView = SearchViewController().view
    favView = FavoriteViewController().view
    viewContainer.addSubview(favView)
    viewContainer.addSubview(searchView)


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


@IBAction func segmentChange(_ sender: UISegmentedControl) 
    switch sender.selectedSegmentIndex
    case 0:
        viewContainer.bringSubview(toFront: searchView)
        break
    case 1:
        viewContainer.bringSubview(toFront: favView)
        break
    default:
        break
    


在第一个选项卡中,我有一个 UIPickerView 作为文本字段的输入。

import UIKit

class SearchViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource 

    @IBOutlet weak var keywordField: UITextField!
    @IBOutlet weak var categoryField: UITextField!
    @IBOutlet weak var distanceField: UITextField!
    @IBOutlet weak var locationField: UITextField!

    var cgpicker = UIPickerView()
    let categories = ["Default", "Airport", "Amusement Park", "Aquarium", "Art Gallery", "Bakery", "Bar"]

override func viewDidLoad() 
    super.viewDidLoad()
    cgpicker.delegate = self
    cgpicker.dataSource = self
    categoryField.inputView = cgpicker
    categoryField.text = categories[0]


func numberOfComponents(in pickerView: UIPickerView) -> Int 
    return 1


func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
    print("picker working")
    return categories.count


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 
    return categories[row]


func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 
    categoryField.text = categories[row]
    categoryField.resignFirstResponder()



但是,当我单击文本字段时,PickerView 不显示数据。事实上,委托和数据源没有被调用,因为“打印”从未被调用过。然而,相同的代码在一个简单的 UIView 应用程序中运行良好。我找不到与此问题相关的任何解决方案。

UIPickerView not showing data

【问题讨论】:

【参考方案1】:

问题在于您的ViewController 类的viewDidLoad

您没有正确创建容器视图控制器。阻止选择器工作的主要问题是当viewDidLoad 完成时您的SearchViewController 没有强引用它,因此SearchViewController 中的选择器变为nil

ViewController viewDidLoad 更新为如下内容:

override func viewDidLoad() 
    super.viewDidLoad()

    let searchVC = SearchViewController()
    searchView = searchVC.view
    addChildViewController(searchVC)
    // Should set searchView frame or constraints
    viewContainer.addSubview(searchView)
    searchVC.didMove(toParentViewController: self)

    let favVC = FavoriteViewController()
    favView = favVC.view
    addChildViewController(favVC)
    // Should set favView frame or constraints
    viewContainer.addSubview(favView)
    favVC.didMove(toParentViewController: self)

【讨论】:

你是救生员。 @adecentalien 很高兴为您提供帮助。请不要忘记通过接受最能解决您的问题的答案来表明您的问题已得到解决。 @rmaddy 这也可以动态完成(事先不知道子视图的数量,这意味着我不能像之前声明searchView 这样的变量)? ***.com/questions/65882928/…【参考方案2】:

这是因为你没有加载选择器

你应该参考SearchViewController而不是参考它的视图

视图控制器:

class ViewController: UIViewController 

    @IBOutlet weak var segment: UISegmentedControl!
    @IBOutlet weak var viewContainer: UIView!
    var searchController: SearchViewController!
    var favController: FavoriteViewController!

    override func viewDidLoad() 
        super.viewDidLoad()
        searchController = SearchViewController()
        favController = FavoriteViewController()
        viewContainer.addSubview(searchController.view)
        viewContainer.addSubview(favController.view)
        searchController.loadPickerView()
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
    


    @IBAction func segmentChange(_ sender: UISegmentedControl) 
        switch sender.selectedSegmentIndex
        case 0:
            viewContainer.bringSubview(toFront: searchController.view)
             searchController.loadPickerView()
            break
        case 1:
            viewContainer.bringSubview(toFront: favController.view)
            break
        default:
            break
        
    

将 loadPickerView func 添加到 SearchViewController

 func loadPickerView() 
        cgpicker.delegate = self
        cgpicker.dataSource = self
        self.textFieldUserName.inputView = cgpicker
        textFieldUserName.text = categories[0]
    

【讨论】:

不需要loadPickerView 方法。选择器视图已在SearchViewControllerviewDidLoad 中设置。 创建容器视图控制器不仅仅是添加子视图。 好的,我们强调了选择器未加载的问题。他可以根据这个做最佳实践解决方案

以上是关于UIPickerView 委托未在子视图中调用的主要内容,如果未能解决你的问题,请参考以下文章

UIPickerView 委托和数据源方法没有被调用

即使在 [[UIPickerView alloc] init] 之后设置了委托,也没有调用 UIPickerView 委托方法

未在委托上调用 CAAnimation 委托方法

UIPopoverController 委托未在解雇时被调用

即使我设置了数据源、委托,另一个视图的 UIPickerView 属性也没有显示

UIPickerView + TableViewCell + 委托和数据源