Swift 中带有“外部”数据源和委托的 UIPickerView

Posted

技术标签:

【中文标题】Swift 中带有“外部”数据源和委托的 UIPickerView【英文标题】:UIPickerView with "external" DataSource and Delegate in Swift 【发布时间】:2015-01-09 17:05:04 【问题描述】:

我的视图中有两个不同的 UIPickerView。当我通过情节提要将数据源和委托设置为它们所在的视图时,它们工作得很好,但是当我尝试通过如下所述的代码执行此操作时,它不起作用。

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

我尝试创建自己的类来实现 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'ish 方法并将不同的控制器连接到每个选择器。这不可能吗?

【问题讨论】:

【参考方案1】:

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()
    

【讨论】:

很好的回应!开箱即用!非常感谢!!!然而,我没有得到的是:在 Java 中,您可以执行我上面编写的代码,并且 GC 不会收集具有“弱”引用的对象,因为它们现在被 PickerView 引用。 swift 如何处理这种不同? 好吧。为此,您需要了解自动引用计数 (ARC)。我建议你阅读苹果的文档。 developer.apple.com/library/ios/documentation/Swift/Conceptual/… 惊人的答案。我快疯了。谢谢一百万! 让我免于痛苦!谢谢

以上是关于Swift 中带有“外部”数据源和委托的 UIPickerView的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中带有自定义 TableViewCell 的核心数据图像

Swift 4.2 中带有 JSON 数据的 Tableview

Swift 中带有过滤器的高级 Firebase 查询

UITableView Swift中带有布尔值的切换按钮

Swift 中带有 CollectionView 和 TableView 的 UIView

Swift中带有按钮的UITableViewCell [重复]