2015-09-04 59 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

你的迴應讓我意識到我對協議和授權一無所知。所以謝謝你。花了一些時間與這些東西后,我找到了一個解決方案,並添加了更新到我的原始描述,以幫助澄清我正在嘗試做什麼。 –