2015-09-04 65 views
5

我似乎无法找到连接让外部类在ViewController中管理视图。我是iOS新手,并花费了大量的时间寻找解决方案。简单的例子:从外部类管理UIPickerView - 使用Swift

UIPickerView

的子类我创建了一个文件,该文件是UIPickerView的子类,并将它符合PickerView委托和数据源。

class MyPickerView: UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource { 
    //In here I conform to all the required methods...no problems there 
} 

主视图控制器与出口的PickerView

在我MainViewController,我创造了我的选择器视图的出口。另外,在StoryBoard中,我将Picker View的“自定义类”连接到上面的MyPickerView。

class MainViewController: UIViewController { 
    @IBOutlet weak var myPickerView: UIPickerView! 

    override func viewDidLoad() { 
     //how do I hookup my picker view class 
    } 
} 

我的问题:

  1. 我怎么告诉我的MainViewController,我的子类 “MyPickerView” 是管理它的选择器视图?

  2. 我是如何启用子类和视图控制器之间的通信的?

---------------------

更新:最终的解决方案包含@奥斯卡的答案

@奥斯卡下面的建议很棒。为了澄清,我希望我的PickerView子类是UIPickerView委托,因为Picker将始终具有相同的UI,并且UI有很多PickerView委托方法。 (归于TitleForRow,widthForComponent,rowHeightForComponent等)我不想在每个使用此PickerView的ViewController中调用这些委托方法。

现在,当PickerView“didSelectRow”被调用时,我们需要通知我们的ViewController并传递所选的值。为了得到这个工作,我使用了一个协议。 (总结如下)这个主题花了我一段时间来学习,但是很重要,所以我建议花费时间与协议&代表团,如果这没有意义。

  1. 与将用于交谈呈递本PickerView ViewControllers一个功能建立在PickerView协议:

    protocol MyPickerViewProtocol { 
        func myPickerDidSelectRow(selectedRowValue:Int?) 
    } 
    
  2. 在视图控制器呈现PickerView,符合你的PickerView协议。通过这样做,你就必须从某个地方放置FUNC myPickerDidSelectRow在你的ViewController:

    class MyViewController: MyPickerViewProtocol { 
        func myPickerDidSelectRow(selectedRowValue:Int?) { 
         //do stuff to update your ViewController 
        } 
    } 
    
  3. @奥斯卡的回答下面将联播选择器视图到您的视图控制器,但还有最后一两件事。为了使PickerView能够回话,你需要在你的PickerView中有一个属性,它是对它所包含的视图控制器的引用。这里的PickeView和ViewController类透视:

    //PickerView Subclass ------------------ 
    protocol MyPickerViewProtocol { 
        func myPickerDidSelectRow(selectedRowValue:Int?) 
    } 
    
    class MyPickerView: UIPickerView { 
        //Note: this var is of type your Picker protocol above. Because the ViewController will conform to the protocol, this var will be the reference (or the pointer) to the protocol func you implement in your ViewController...which is myPickerDidSelectRow 
        var propertyThatReferencesThisViewController:MyPickerViewProtocol? 
    }   
    
    //ViewController Class ---------------- 
    myPicker = MyPickerView() 
    myPickerView.dataSource = myPicker //note: myPickerView is the outlet of type UIPickerView in your ViewController 
    myPickerView.delegate = myPicker 
    //HERE'S THE PROPERTY from our PickerView subclass that will point to this ViewController's protocol methods that we implemented. From the MyPickerViewProtocol 
    myPicker.propertyThatReferencesThisViewController = self 
    
  4. 现在,当排在我们PickerView选择,让我们用我们的财产告诉视图控制器:propertyThatReferencesThisViewController

    class MyPickerView: UIPickerView { 
        //This Property points to the ViewController conforming to the protocol. This property will only be able to access the stuff you put in the protocol. It won't access everything in your ViewController 
        var propertyThatReferencesThisViewController:MyPickerViewProtocol? 
    
        //didSelectRow UIPickerView Delegate method that apple gives us 
        func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
         //get your picker values that you need 
         let theRowValue = someArray[row] 
         propertyThatReferencesThisViewController?.myPickerDidSelectRow(theRowValue) 
    
         //the ViewController func will be called passing the row value along 
        } 
    } 
    
+0

克劳迪奥,非常有帮助。注释“//注意:myPickerView是在您的ViewController中类型UIPickerView的出口”是我的“陷阱”时刻。谢谢 – Greg

回答

7

子类Pickerview

class MyPickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate { 

    var oficinas = ["oficina 1", "Oficinas 2", "Oficina 3"] 

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     return oficinas.count 
    } 

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

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { 
     return oficinas[row] 
    } 
} 

主视图控制器与出口的PickerView

class MainViewController: UIViewController { 
    @IBOutlet weak var myPickerView: UIPickerView! 

    var pickerOficinas: MyPickerView! 

    override func viewDidLoad() { 
     //how do I hookup my picker view class 
     pickerOficinas = MyPickerView() 
     myPickerView.delegate = pickerOficinas 
     myPickerView.dataSource = pickerOficinas 
    } 
} 
1

我认为你可能已经掌握了棒的错误结局!

为什么你想让选取器自己的代表?代表的一点是,它可以告诉代表什么已被选中等。

我会认为你应该做的是让你的视图控制器符合UIPickerViewDelegate并使其成为代表的选择和放置当在这些委托方法中选择一个项目时想要发生的任何逻辑。我看不到任何其他方式'告诉'你的视图控制器关于选择器。另外,如果你引用你的选择器是weak,那么除非你在其他地方持有一个strong引用,否则在任何时候(例如它是视图层次结构的一部分)它都会被释放。

+0

你的回应让我意识到我对协议和授权一无所知。所以谢谢你。花了一些时间与这些东西后,我找到了一个解决方案,并添加了更新到我的原始描述,以帮助澄清我正在尝试做什么。 –