Swift – Xcode 6 Beta 5

Pozdě, ale přece 🙂 Minulý týden Apple vydal další betu Xcode a ta nám opět přináší změny ve Swiftu. Tak se na ně pojďme mrknout. Komplet všechny změny najdete v release notes. Zmíním jenom ty zajímavější.

Optionals

Optionals se můžou porovnávat s nil  pomocí operátorů ==  a != . A to i v případě, že použitý typ neimplementuje protokol Equatable .

Optionals už by default neimplementují protokol BooleanType  (dříve LogicValue ). Toto už neprojde …

var someOptional: Int?

if someOptional {
}

… a je potřeba to zapsat takto …

var someOptional: Int?

if someOptional != nil {
}

… hlavním důvodem je nepřehlednost u Bool? .

Další novinka se týká operátoru !  (unwrapping). Podporuje přiřazování. Následující příklad nebyl dříve přeložitelný.

var i: Int! = 0
i! = 2
i!++
i! // == 3

To samé platí i pro vnořené typy.

var people = [ "monks" : [ "robert", "jiri" ] ]
people[ "monks" ]!.append( "filemon" )

Dá se použít i ?  (optional chaining).

var people = [ "monks" : [ "robert", "jiri" ] ]

// do "monks" prida "filemon"
people[ "monks" ]?.append( "filemon" )

// neudela nic, protoze "GMC" neni ve slovniku
people[ "GMC" ]?.append( "bousak" )

Byl přidán nový operátor ??  (nil coalescing operator). Funguje to následovně:

  • pokud má optional nějakou hodnotu, je vrácena jeho hodnota, která už není optional,
  • pokud nemá hodnotu, je vrácen výsledek z pravé strany operátoru (také není optional),
  • práva strana se vyhodnocuje pouze v případě, že je to nutné (lazy), jinak ne.

Příklad …

public func ?? <T> ( optional: T?, defaultValue: @autoclosure () -> T ) -> T {
  switch optional {
    case .Some( let value ):
      return value
    case .None:
      return defaultValue()
  }
}

var name: String?
print( name ?? "unnamed" ) // "unnamed" (String, ne String?)

name = "Robert"
print( name ?? "unnamed" ) // "Robert" (String, ne String?)

Modifikátor dynamic

Je možné aplikovat u metod, properties, subscriptů nebo inicializátorů. A garantuje to, že volání se vždy provádí dynamicky a nikdy se například neinlajnuje. Neboli daná metoda se může za běhu změnit (ObjC swizzling). Příklad …

class BaseClass {}

class MyClass: BaseClass {
  // Ke getteru/setteru se pristupuje vzdy pomoci objc_msgSend, tj. muze
  // se klidne provest swizzling, apod.
  dynamic var x: Int

  // Viditelne pro ObjC, pristup take pres objc_msgSend, ALE
  // muze se pouzit efektivnejsi lookup ze Swiftu
  @objc var y: Int

  // Viditelne pro ObjC pouze pokud je BaseClass ObjC trida a nebo
  // BaseClass dedi z nejake ObjC tridy
  var z: Int

  override init() {
    x = 0
    y = 0
    z = 0
    super.init()
  }
}

… pokud se použije modifikátor dynamic , tak je možné z ObjC použí KVO, proxy a další advanced fičury z Cocoa. dynamic  není závislý na @objc , ale protože jeho implementace je závislá na běhovém prostředí ObjC, dynamic  se může aplikovat pouze na ObjC kompatibilní typy.

Atributy, operátory

  • @auto_closure  přejmenován na @autoclosure
  • @assignment  odstraněn
  • z atributů @prefix , @infix  a @postfix  jsou modifikátory, takže se zapisují bez @
  • u deklarace operátorů bylo přehozeno pořadí z operator prefix –  na prefix operator –
  • @class_protocol  atribut odstraněn, už stačí zápis protocol P: class { … }

Operátor +=  aplikovaný na pole neumožňuje přidávat jednotlivé elementy, ale pouze spojovat pole. Tohle už neprojde …

var a = [ "a", "b" ]
a += "c"

… ale toto ano …

var a = [ "a", "b" ]
a += [ "c" ]

Potom se nám Swift opět trochu zrychlil, pár změn v oblasti rozsahů, … Je toho více, jak jsem psal na začátku, projděte si release notes. Zmiňuju jen to, co mě zaujalo.