UIPickerView with" external" Swift中的DataSource和Delegate

时间:2015-01-09 17:05:05

标签: ios swift uipickerview uipickerviewdatasource uipickerviewdelegate

我的视图中有两个不同的UIPickerView。当我将dataSource和委托设置为通过故事板托管的View时,它们工作得很好,但当我尝试通过如下所述的代码执行此操作时,它不起作用。

两个选择者都应该有不同的数据来显示(甚至可能是代表的不同行为)。因此,我想以编程方式将它们连接到不同的数据源。

我尝试创建自己的类,实现UIPickerViewDataSource-和UIPickerViewDelegate-Protocols,并将该类的对象连接到我的PickerViews,但它不起作用。在运行时terminating with uncaught exception of type NSException抛出异常,说明这一点:

2015-01-09 17:50:05.333 Pet Stats[4953:244338] -[NSConcreteMapTable numberOfComponentsInPickerView:]: unrecognized selector sent to instance 0x7b4616d0
2015-01-09 17:50:05.338 Pet Stats[4953:244338] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMapTable numberOfComponentsInPickerView:]: unrecognized selector sent to instance 0x7b4616d0'

我怎样才能让它发挥作用?我错过了什么?这是我的代码:

WeightWheelController.swift

import UIKit

class WeightWheelController: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
    let ElementCount: Int!

    init(pickerInterval: Int) {
        ElementCount = pickerInterval
    }

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return ElementCount
    }

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        return String(row + 1)
    }

    func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
    {
        println("External Controller:" + String(row + 1))
    }
}

WeightWheelInputViewController.swift

import UIKit

class WeightWheelInputViewController: UIViewController {
    @IBOutlet weak var picker1: UIPickerView!        
    @IBOutlet weak var picker2: UIPickerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        //picker attached to c1 should show number from 1 to 150
        let c1 = WeightWheelController(pickerInterval: 150)

        //picker attached to c1 should show number from 1 to 10
        let c2 = WeightWheelController(pickerInterval: 10)

        picker1.dataSource = c1
        picker1.delegate = c1

        picker2.dataSource = c2
        picker2.delegate = c2
    }

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

简要更新:

在这个问题中,我发现您可以为不同的选择器视图使用不同的标签。这将是一种选择;但是,我不喜欢它。我想宁愿遵循MVC'的方法,并将不同的控制器连接到每个选择器。这有可能吗?

1 个答案:

答案 0 :(得分:14)

delegatedatasource都是无主参考。这意味着一旦您超出范围,c1c2就会被释放。尝试将c1c2声明为该类的属性。

无主引用不会对引用的对象产生强烈保持(例如,它们不会增加保留计数以防止ARC释放引用的对象)。

还要确保从界面构建器中删除选择器视图的委托和数据源属性。

class WeightWheelInputViewController: UIViewController {
    @IBOutlet weak var picker1: UIPickerView!        
    @IBOutlet weak var picker2: UIPickerView!

    var c1 : WeightWheelController!
    var c2 : WeightWheelController!

    override func viewDidLoad() {
        super.viewDidLoad()

        c1 = WeightWheelController(pickerInterval: 150)

        c2 = WeightWheelController(pickerInterval: 10)

        picker1.dataSource = c1
        picker1.delegate = c1

        picker2.dataSource = c2
        picker2.delegate = c2
    }

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