2015-04-09 13 views
6

Używam opcjonalnych zamknięć, ale nie mogę znaleźć sposobu na przekazanie parametru. Przeszukuje się wszędzie, wypróbował wszystkie sugestie, ale nie może go uruchomić.Parametry z opcjonalnymi zamknięciami w Swift

Mój kod:

func DoAlert(title: String 
    , message: String 
    , actions: String 
    , sender: AnyObject? 
    , Ctlr : UIViewController 
    , SegueString: String? 
    , YesClosure:()->() = {} 
    , NoClosure:()->() = {} 
    , StartClosure:()->() = {} 
    , EndClosure:()->() = {} 
    ) { 

if (actions.rangeOfString("Ok") != nil { 
     alert.addAction(UIAlertAction(title: "OK", style: .Default) { action -> Void in 
      EndClosure() 
      })} 
} // end function 

chcę dodać zamknięcie do Ok, gdzie potrzebna jest parametr „ja”.

Coś jak poniżej:

// add to func doAlert: 
    , OkClosure: (AnyObject)->() = {} 


      // add to action Ok (before the EndClosure: 
      OkClosure(sender!) 

Uzyskiwanie błąd na pierwszej linii: AnyObject nie jest podtypem()

Gdybym opuścić AnyObject z pierwszej linii, Uzyskiwanie błąd: nie można przekształcić wyrażenie na wpisz "AnyObject", aby wpisać "() =>()"

Wszystkie inne próby dają mi podobne błędy "Tuple". Jak kodować przekazywanie parametrów w opcjonalnych zamknięciach w moim kodzie?

+1

Trochę ładniej: "YesClosure: (() ->())? = nil', a następnie użyj go w ten sposób: 'YesClosure?()' (działa tylko wtedy, gdy jest ustawiony). Użyj także lowerCaseCamelCasing dla parametrów, zmiennych i instancji. – vrwim

+1

'DoAlert' * może * mieć zbyt wiele argumentów. Nie ma możliwości napisania czystego kodu, gdy masz metodę, która przyjmuje 10 argumentów, co pogorszyło się przez fakt, że cztery z nich są zamknięciami. – nhgrif

+0

nhgrif. Widzę twój widok. DoAlert jednak tworzy czysty kod wszędzie tam, gdzie chcę symulować "skrzynkę wiadomości" VB. – ReneMusters

Odpowiedz

17

Po pierwsze, używać zamknięć jako argument dla funkcji, należy zadeklarować je tak:

func myFunc(closure: (Int) -> Void) { 
    // Now I can call closure like so: 
    let myInt = 10 
    closure(myInt) 
} 

(Jak podkreślił @Airspeed Velocity, nawias wokół Int nie są ściśle wymagane, ponieważ istnieje tylko jeden argument Niezależnie od tego czy należą one tylko osobiste preferencje)

drugie można zmodyfikować poprzednią funkcję zawierać opcjonalny zamknięcie, co następuje:. (N Uwaga nawias wokół zamknięcia ? i wskazują, że zamknięcie jest opcjonalny, nie typ zwracany)

func myFunc(closure: ((Int) -> Void)?) { 
    // Now when calling the closure you need to make sure it's not nil. 
    // For example: 
    closure?(10) 
} 

trzecie,, aby dodać domyślną wartość zerowa, czyli to, co wygląda na to, że próbujesz zrobić z = {} na koniec YesClosure:()->() = {}, można zrobić:

func myFunc(closure: ((Int) -> Void)? = nil) { 
    // Still need to make sure it's not nil. 
    if let c = closure { 
     c(10) 
    } 
} 

Wreszcie jak notatki, można ustawić nazwy argumentów zamknięcia, które mogą ułatwić zidentyfikowanie co ty' ponowne przejście do zamknięcia podczas jego wywoływania. Na przykład:

(Uwaga - w tym nawiasie są wymagane wokół value: Int)

func myFunc(closure: ((value: Int) -> Void)) { 
    closure(value: 10) 
} 

Jeszcze wreszcie można użyć typealias. Zgodnie z dokumentacją:

A type alias declaration introduces a named alias of an existing type into your program.

Oto przykład, w jaki sposób używać go z zamknięciem:

typealias MyClosureType =() -> Void 

func myFunc(closure: MyClosureType) { 
    closure() 
} 

nadzieję, że pomoże!

+0

Dobra odpowiedź! Ale jedna rzecz, kiedy mówisz "Kiedy używasz zamknięć jako argumentów funkcji, musisz upewnić się, że zamykasz je w nawiasach", naprawdę nie musisz tego robić (IMHO to po prostu dodaje bałaganu), chyba że chcesz zrobić coś takiego jak znak Całe zamknięcie jest opcjonalne –

+0

To fajne, nie zdawałem sobie sprawy, że możesz to zrobić! Zgadzam się, nie mając dodatkowego nawiasu usuwającego bałagan.Zmierzę odpowiednio moją odpowiedź – ABakerSmith

+0

Możesz również odrzucić nawiasy wokół pojedynczych argumentów (np. Int -> Void' zamiast '(Int) -> Void') choć jest to bardziej osobista cecha preferencji (wolę to) –

0

Myślę, że znalazłem.Nie mogę używać parametrów w zamknięciu, gdy zadzwonię do func. W samej funkcji muszę zdefiniować używane parametry (zamknięcie: (sender: AnyObject) -> Void), upewnić się, że zmienne są zdefiniowane (lub podane jako oddzielny parametr) i dodać je do wywołania zamknięcia.

@IBAction func buttonPressed(sender: AnyObject) { 
    myFunc (sender, doClosure) 
} 

func myFunc(sender: AnyObject, closure: (sender: AnyObject) -> Void) { 
    // Now I can call closure like so: 
    closure (sender: sender) 
} 

func doClosure(sender: AnyObject) { 
    println("sender = \(sender)") 
} 
Powiązane problemy