2014-06-13 12 views
11

Załóżmy, że mam niestandardowy interfejs UIView, nazwijmy go MyCustomView. Wewnątrz tego widoku znajduje się właściwość UITextField. Załóżmy, że moim celem jest móc utworzyć instancję MyCustomView i dodać ją do jakiegoś kontrolera widoku, i chcę, aby ten kontroler widoku był w stanie obsłużyć działania podjęte w tym polu tekstowym. Na przykład, jeśli uderzę „powrót” na klawiaturze w polu tekstowym, może chcę zrobić jakąś akcję - niech mi dać przykład, co mam Przewidując z pewną objective-c psuedo kodu:iOS Swift Pass Closure jako właściwość?

MyCustomView *myView = [[MyCustomView alloc] initWithFrame:CGRectMake(10,10,100,100)]; 
myView.textField.actionBlock = { /* do stuff here! */ } 
[self.view addSubview:myView]; 

A potem wewnątrz klasy MyCustomView chciałbym zrobić coś takiego:

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
    self.actionBlock(); 
    return NO; 
} 

chciałbym CustomView być UITextFieldDelegate tak, że za każdym razem robię to nie będę musiał dodać wszystkie metody przekazać zobacz kontrolerów, do których go dodam, ale raczej mają jedną implementację, która ma tylko niezależnie od tego, Przechodzę do tego ... Jak można to zrobić w szybkim tempie?

Odpowiedz

35

Oczywiście, możesz to zrobić. Swift ma funkcje pierwszej klasy, więc możesz wykonywać takie czynności, jak bezpośrednie przekazywanie funkcji wokół zmiennych. Pamiętaj, że same funkcje są w rzeczywistości zamknięciami za kulisami. Oto podstawowy przykład:

class MyClass { 
    var theClosure: (() ->())? 

    init() { 
     self.theClosure = aMethod 
    } 

    func aMethod() ->() { 
     println("I'm here!!!") 
    } 
} 


let instance = MyClass() 
if let theClosure = instance.theClosure { 
    theClosure() 
} 

instance.theClosure = { 
    println("Woo!") 
} 
instance.theClosure!() 

I tutaj jest ten sam przykład przy użyciu zamknięć, które mogą przyjmować parametr String.

class MyClass { 
    var theClosure: ((someString: String) ->())? 

    init() { 
     self.theClosure = aMethod 
    } 

    func aMethod(aString: String) ->() { 
     println(aString) 
    } 
} 

let instance = MyClass() 
if let theClosure = instance.theClosure { 
    theClosure(someString: "I'm the first cool string") 
} 

instance.theClosure = {(theVerySameString: String) ->() in 
    println(theVerySameString) 
    someThingReturningBool() 
} 
instance.theClosure!(someString: "I'm a cool string!") 
+0

Doskonale, dzięki za informacje! Nadal używam opcji rozpakowywania i takich, więc zastanawiam się, co się stanie, jeśli chcę, aby zamknięcie było opcjonalne? Korzystanie z tego kodu, jeśli nie ma zamknięcia, powoduje awarię. – Mike

+0

@Mike tak, przepraszam za to. Uwzględniłem rozpakowanie w mojej edycji. –

+0

Również inne dziwactwo jest częściowo powiązane. Powiedzmy, że chcę wywołać funkcję wewnątrz zamknięcia, która robi coś i zwraca Bool, ale nie dbam o wynik ... Wydaje się, że muszę zrobić coś takiego {var unusedResult = self.doSomethingThatAlsoReturnsBool()} w przeciwnym razie pojawia się komunikat "Nie można przekonwertować typu wyrażeń"() "na błąd" Bool ". W jaki sposób mogę uniknąć tworzenia i przypisywania nieużywanego rekordu? – Mike

Powiązane problemy