App maken: ook jij kunt het leren!

 

de iOS Academie Forums

Forums - Producten van de iOS Academie - Het eBook: Apps bouwen met Swift: 16.3 Waar zijn die closures goed voor? - voorbeeld in boek geeft foutm

Disco  Op de eerste vier stappen van zijn/haar studiekaart scoort Harry 53%. Klokje06 dec 2016, 21:38
Avatar
Avatar
Berichten:8


Beste Roelf,

In het eBook (versie 3.02 november 2016) in hoofdstuk 16.3 staat een voorbeeld wat niet werkt. Ik vermoed dat dit stukje nog niet is aangepast aan de laatse versie van Swift. Ik heb de bijbehorende playground gedownload en die werkt wel. Dat komt omdat daar de code niet overeenkomt met wat in het boek staat.

Het voorbeeld waarbij een closure in de praktijk wordt gebruikt om de inhoud van een array te sorteren geeft een foutmelding in de Playground.

Op de regel:

   onzeArray = onzeArray.sort( { print("$0) of $(1): ")

Geeft de foutmelding: 'sort 'has been renamed to sorted(by:)

 

In de playground staat echter het volgende code snippet:

  onzeArray = onzeArray.sorted() {

Dit geeft geen foutmelding en werkt.

 

Met vriendelijke groet,

Harry

Reageer


Noki  Op de eerste vier stappen van zijn/haar studiekaart scoort Nico 36%. Klokje30 dec 2016, 10:45
Avatar
Avatar
Berichten:20


Hoi Harry/Roelf, 

ik wilde inderdaad vandaag hezelfde zeggen :-) sort is in Swift 3.0 vervangen door sorted. 

@Roelf (of anderen), 

wat ik me alleen wel afvraag is het volgende: 

Je kunt nu dus de code "onzeArray.sorted(by: <#T##(String, String) -> Bool#>)" gebruiken met daar in de closusure uit het boek, maar via de "sorted help" zag ik dat je het ook zonder closure kunt doen dus:

print(students.sorted())
// Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
print(students.sorted(by: <))
// Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"

De vraag is, kon je dit met "sort" in het verleden ook doen (ik snap dat het voorbeeld juist gebruikt werdt om closures uit te leggen) of is sorted niet alleen hernoemt maar ook slimmer geworden waardoor je nu niet meer hoeft te vertellen hoe hij moet sorteren?

Update: 

Ik heb nog iets gevonden waarvan ik niet zeker weet of het fout in het boek staat:

de code in 16.5 (animate groene box naar geel in playground) werkte bij mij ook niet, hij toont simpelweg niets in de assistent editor. Na wat google zoek acties kwam ik er achter dat als je asynchrone calls doet (bijvoorbeeld een network call) dat de playground dit simpelweg nooit uitvoerd omdat hij als hij aan het einde van de code komt de 'applicatie' stopt. 

De oplossing die wordt gegeven is om de regel "PlaygroundPage.current.needsIndefiniteExecution = true" toe te voegen, hierdoor blijft de playground app "draaien". Als ik dat in dit voorbeeld doe dan werkt de animatie wel in de playground voor mij. 

Edit: Dit laatste lijkt meer een playground bug want nu kan ik wel zonder de bovengenoemde regel de oorspronkelijke code uitvoeren

 

Groeten, 

Nico...

Reageer


Admin Roelf  Klokje30 dec 2016, 13:57
Avatar


Nico en Harry,

De bewuste tekst in het boek is inderdaad onjuist: bij de editie (3.03) die later vandaag kan worden gedownload, is dit verbeterd. Dank voor het melden en meedenken!

 

Reageer


PageMaker  Op de eerste vier stappen van zijn/haar studiekaart scoort Jan H. 45%. Klokje16 jan 2017, 19:37
Avatar
Avatar
Berichten:29


Beste Roelf,

In het eBook (versie 3.02 november 2016) in hoofdstuk 16.3 staat een voorbeeld wat niet werkt. Ik vermoed dat dit stukje nog niet is aange ...

Harry,

Even door op je vraag waar closures goed voor zijn.

Stel je hebt gedeclareerd en geinitialiseerd als volgt:

enum Operation {

  ...

  case BinaryOperation((Double, Double) -> Double)

}

var operationTable: Dictionary<String, Operation> = [

  ...

  "x": Operation.BinaryOperation(mutiply)

  "+": Operation.BinaryOperation(plus)

  "-": Operation.BinaryOperation(minus)

  "/": Operation.BinaryOperation(divide)

]

Dan heb je een functie multiply nodig als:

func multiply(op1: Double, op2: Double) -> Double {

  return op1 * op2

}

Maar dat heb je ook voor optellen, aftrekken en delen. Dat kan in Swift met een clossure anders.

Neem dit stuk van de functie:

(op1: Double, op2: Double) -> Double { return op1 * op2 }

en zet de eerste { vooraan; en zet 'in' op de plaats waar het vandaan komt

{ (op1: Double, op2: Double) -> Double  in return op1 * op2 }

Je hebt nu een closure.

Zet deze in de operationTable als volgt:

  "x": Operation.BinaryOperation({ (op1: Double, op2: Double) -> Double  in return op1 * op2 })

Swift 'kent' het type van BinaryOperation, namelijk: ((Double, Double) -> Double). Dat is redundant dus kun je ook schrijven:

  "x": Operation.BinaryOperation({ (op1, op2) in return op1 * op2 })

Voor op1 en op2 kun je default argumenten gebruiken

  "x": Operation.BinaryOperation({ ($0, $1) in return $0 * $1 })

Swift 'weet' ook dat $0 en $1 van type Double zijn; die heb je dan ook niet allemaal nodig:

  "x": Operation.BinaryOperation({ return $0 * $1 })

Omdat ook de return waarde van het type Double is, kun je de 'return' ook nog weglaten en reduceert het hele verhaal tot:

  "x": Operation.BinaryOperation({ $0 * $1 })

En nu kun je voor de overige binaire operaties schrijven:

  "+": Operation.BinaryOperation({ return $0 + $1 })

  "-": Operation.BinaryOperation({ return $0 - $1 })

  "/": Operation.BinaryOperation({ return $0 / $1 })

Ik zou er nooit op gekomen zijn als iemand me dat niet had voorgedaan, waarvoor dank!

De kracht en de macht van closures is hiermee vermoed ik gedemonstreerd.

 

 

 

 

 

 

 

 

Reageer