2015-09-04 15 views
5

Nie mogę znaleźć połączenia, aby klasa zewnętrzna zarządzała widokiem w kontrolce ViewController. Jestem nowy na iOS i spędziłem sporo czasu szukając rozwiązania. Prosty przykład:Zarządzanie UIPickerView z klasy zewnętrznej - przy użyciu Swift

podklasa UIPickerView

utworzyć plik, który jest podklasą UIPickerView i mają być zgodne z delegata PickerView i źródła danych.

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

Widok główny regulator z wyjściem na PickerView

W moim MainViewController, tworzę zbytu dla moim zdaniem kompletowania. Ponadto w StoryBoard podłączam "klasę niestandardową" dla mojego widoku wyboru do MyPickerView powyżej.

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

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

Moje pytania:

  1. Jak mogę powiedzieć, że mój mój MainViewController podklasa "MyPickerView" zarządza pogląd kompletacji dla niego?

  2. Jak mogę włączyć komunikację między podklasą a kontrolerem widoku?

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

UPDATE: Ostateczne rozwiązanie Zawierające @ Oscara Odpowiedź

@ Oscara sugestia poniżej była świetna. Aby wyjaśnić, chciałem, aby moja podklasa PickerView była Delegatem UIPickerView, ponieważ selektor zawsze będzie miał ten sam interfejs użytkownika i istnieje wiele metod delegowania PickerView dla interfejsu użytkownika. (attributedTitleForRow, widthForComponent, rowHeightForComponent, itp.) Nie chcę wywoływać tych metod delegowania w każdym ViewController, który używa tego PickerView.

Teraz, gdy wywoływana jest funkcja "didSelectRow" PickerView, musimy powiadomić nasz ViewController i przekazać wybraną wartość. Aby to zadziałało, użyłem protokołu. (podsumowane poniżej) Temat ten trochę mnie nauczył, ale jest kluczowy, dlatego sugeruję spędzanie czasu z delegaturami, jeśli to nie ma sensu.

  1. Tworzenie protokół w PickerView z func, który będzie używany do rozmowy ViewControllers że przedstawienie tego PickerView:

    protocol MyPickerViewProtocol { 
        func myPickerDidSelectRow(selectedRowValue:Int?) 
    } 
    
  2. W ViewController prezentującej PickerView, odpowiadają swoim protokole PickerView. Robiąc tak, trzeba będzie umieścić myPickerDidSelectRow funkcjono gdzieś w ViewController:

    class MyViewController: MyPickerViewProtocol { 
        func myPickerDidSelectRow(selectedRowValue:Int?) { 
         //do stuff to update your ViewController 
        } 
    } 
    
  3. @ odpowiedź Oscara poniżej hookup pogląd kompletacji do kontrolera widoku, ale jest jedna rzecz. Aby PickerView mógł z powrotem rozmawiać, będziesz potrzebował właściwości w twoim PickerView, która jest odniesieniem do kontrolera widoku, w którym się znajduje.Oto klas PickeView i ViewController w perspektywie:

    //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. Teraz, gdy wiersz jest wybrany w naszym PickerView, niech powiedzieć ViewController za pomocą naszej własności: 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

Claudio, bardzo pomocne. Komentarz "// note: myPickerView jest gniazdem typu UIPickerView w twoim ViewController" był moim momentem "gotcha". Dzięki – Greg

Odpowiedz

7

Podklasa 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] 
    } 
} 

Widok główny regulator z wyjściem na 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

myślę, że może złapałem zły koniec kija!

Dlaczego chcesz zrobić selektorowi swojego własnego pełnomocnika? Punkt delegacji polega na tym, że może przekazać swojemu delegatowi to, co zostało wybrane, itp.

Sądzę, że powinieneś zrobić to, aby twój kontroler widoku był zgodny z UIPickerViewDelegate i sprawić, że będzie on delegatem selektora i logika tego, co ma się stać, gdy element zostanie wybrany w tych metodach delegatów. Nie widzę innego sposobu "mówienia" kontrolerowi widoku o selektorze.

Ponadto, jeśli odwołujesz się do selektora to weak, to chyba że będziesz trzymał odwołanie strong gdziekolwiek indziej, przez cały czas (np. Jest częścią hierarchii widoków), zostanie zwolniony.

+0

twoja odpowiedź uświadomiła mi, że nie wiedziałem nic o protokołach i delegacji. Dziękuję za to. Po spędzeniu trochę czasu z tymi rzeczami, znalazłem rozwiązanie i dodałem aktualizację do mojego pierwotnego opisu, aby wyjaśnić, co próbowałem zrobić. –

Powiązane problemy