I 2008 kunngjorde Apple og ga ut iPhone SDK 2.0. Denne hendelsen startet en ny revolusjon innen programvareutvikling, og dermed ble en ny generasjon utviklere født, som nå er anerkjent som iOS-utviklere .
Mange av disse utviklerne hadde aldri brukt Objective-C før, og det var den første utfordringen Apple hadde for dem. Til tross for ukjent syntaks og manuell minneadministrasjon, var det utrolig vellykket og hjalp befolkningen i App Store med titusenvis av applikasjoner. Apple forbedret kontinuerlig Objective-C med hver nye utgivelse, og tilføyde blokker og bokstaver ( bokstavelige ), og legger til forenklet minnehåndtering med automatisk referansetelling og mange andre funksjoner som indikerer et moderne programmeringsspråk.
Og etter seks år med å jobbe og forbedre Objective-C bestemte Apple seg for å utfordre utviklere igjen. Nok en gang må iOS-utviklere lære et nytt programmeringsspråk: Fort . Swift fjerner usikker pekeradministrasjon og introduserer kraftløse nye funksjoner, samtidig som det opprettholder interaksjon med både Objective-C og C.
Swift 1.0 er en sterk og stabil utviklingsplattform, som helt sikkert vil utvikle seg på interessante måter de neste årene. Det er det perfekte tidspunktet å begynne å utforske dette nye språket, da det åpenbart er fremtiden for iOS-utvikling.
Hensikten med denne opplæringen er å gi til Objective-C-utviklere en rask oversikt over nye funksjoner på Swift-språket, slik at du kan ta neste steg og begynne å omfavne Swift i det daglige arbeidet ditt. Jeg kommer ikke til å bruke mye tid på å forklare Objective-C, jeg kommer til å anta at du er kjent med iOS-utvikling.
For å begynne å utforske Swift hva du trenger er last ned XCode 6 fra App Store og lage et lekeområde å eksperimentere med. Alle eksemplene nevnt i denne artikkelen ble laget på denne måten.
Apple Swift-nettsted er den beste referansen for å lære om Swift-programmering. Du vil se at det er veldig verdifullt, og til du er det fullt oppdatert med Swift-utviklingen Jeg tror du vil komme tilbake hit ofte.
For å erklære en variabel i Swift, bruk nøkkelordet var
.
var x = 1 var s = 'Hello'
Du vil merke at de to variablene s
og x
de er av forskjellige typer. x
er et heltall, mens 's' er en streng av tegn. Swift er en slags språksikker og vil trekke variabeltyper fra den tildelte verdien. Hvis du vil at koden skal være mer lesbar, kan du eventuelt kommentere variabeltypen:
var y: Int y = 2
Konstanter er like, men blir deklarert ved hjelp av let
i stedet for var
. Du trenger ikke å vite verdien av en konstant ved kompileringstid, men du må tildele den en verdi nøyaktig en gang.
let c1 = 1 // Constante conocida al momento de la compilación var v = arc4random() let c2 = v // Constante conocida solo en momento de ejecución
Som navnet antyder, er de uforanderlige, så følgende kode vil forårsake en feil ved kompileringstidspunktet.
let c = 1 c = 3 // error
Andre typer kan også deklareres som konstanter. For eksempel erklærer følgende kode en matrise som en konstant, og hvis du prøver å endre noen av elementene, rapporterer Swift-kompilatoren en feil:
var arr2 = [4, 5, 6] arr2[0] = 8 print (arr2) // [8, 5, 6] let arr = [1, 2, 3] a[0] = 5 // error
Konstanter må initialiseres når de blir deklarert, akkurat som variabler må initialiseres før de brukes. Så hvor er ekvivalent nil
av Objective-C? Swift introduserer valgfrie verdier . Valgfrie verdier kan ha en verdi eller være nil
. Hvis du ser på følgende kode, vil du legge merke til at x
ble tildelt som verdi Opcional
av 2014
. Dette betyr at Swift-kompilatoren visste at x
kan være nil
.
var s = '2014' var x = s.toInt() print(x) // Optional(2014)
Hvis du endrer denne koden og tildeler verdien 'abc'
til s
, som ikke kan konverteres til et helt tall, vil du legge merke til at x
er nå en nil
.
var s = 'abc' var x = s.toInt() print(x) // nil
Gjør returtypen til toInt()
er Int?
, som er en Valgfri int . La oss prøve å kalle en standardfunksjon på x
:
var x = '2014'.toInt() print(x.successor()) // error
Kompilatoren rapporterer om en feil siden x
er en valgfritt og kan potensielt være null . Vi burde prøve x
først, og sørg for at sucessor
påkalles på et reelt tall, og ikke på en nil
verdi:
var x = '2014'.toInt() if x != nil { print(x!.successor()) // 2015 }
Husk at vi må pakke ut x
legge til et utropstegn (!) . Når vi sørger for at x
inneholder en verdi, kan vi få tilgang til den. Ellers får vi en kjøretidsfeil. Vi kan også gjøre det Swift kaller valgfri binding , og konverterer dermed det valgfrie til en ikke-valgfri variabel
let x = '123'.toInt() if let y = x { print(y) }
Koden for if
den vil bare bli utført hvis x
har en verdi, og er tildelt y
. Merk at vi ikke trenger å pakke ut y
, dens ikke-valgfrie type, siden vi vet at x
er ikke nil
.
Ta en titt på Apples Swift-opplæring der du kan lese i detalj om valgfrie og interessante funksjoner som f.eks valgfri kjetting
I Objective-C gjøres en formateringsstreng vanligvis med stringWithFormat:
metoden:
NSString *user = @'Gabriel'; int days = 3; NSString *s = [NSString stringWithFormat:@'posted by %@ (%d days ago)', user, days];
Swift har en funksjon som heter Strenginterpolasjon som gjør det samme, men er mer kompakt og lettere å lese:
let user = 'Gabriel' let days = 3 let s = 'posted by (user) (days) ago'
Du kan også bruke uttrykk:
let width = 2 let height = 3 let s = 'Area for square with sides (width) and (height) is (width*height)'
For å lære mer om Swift strenginterpolering, gå til her .
Definisjonen av Funksjon i Swift er forskjellig fra C. En eksempelfunksjonsdefinisjon er følgende:
func someFunction(s:String, i: Int) -> Bool { ... // code }
Swift-funksjoner er førsteklasses typer . Dette betyr at du kan tilordne funksjoner til variabler, sende dem som parametere til funksjoner, eller få dem til å returnere typer:
func stringLength(s:String) -> Int { return countElements(s) } func stringValue(s:String) -> Int { if let x = s.toInt() { return x } return 0 } func doSomething(f:String -> Int, s:String) -> Int { return f(s).successor() } let f1 = stringLength let f2 = stringValue doSomething(f1, '123') // 4 doSomething(f2, '123') // 124
Igjen angir Swift typene f1
og f2
(String
-> Int
), selv om vi kunne ha definert dem eksplisitt:
let f1:String -> Int = stringLength
Funksjoner kan også returnere andre funksjoner:
func compareGreaterThan(a: Int, b: Int) -> Bool { return a > b } func compareLessThan(a: Int, b: Int) -> Bool { return a (Int, Int) -> Bool { if greaterThan { return compareGreaterThan } else { return compareLessThan } } let f = comparator(true) println(f(5, 9))
En guide til funksjoner i Swift finnes her .
Enums i Swift er mye kraftigere enn i Objective-C. Når Swift strukturer det, kan de ha metoder og sendes som verdier:
enum MobileDevice : String { case iPhone = 'iPhone', Android = 'Android', WP8 = 'Windows Phone8', BB = 'BlackBerry' func name() -> String { return self.toRaw() } } let m = MobileDevice.Android print(m.name()) // 'Android'
I motsetning til Objective-C, kan Swift enums tilordne strenger, tegn eller flyter som verdier for hvert medlem, annet enn heltall. Den praktiske metoden toRaw()
returnerer verdien tildelt hvert medlem.
Oppføringer kan også parametriseres:
enum Location { case Address(street:String, city:String) case LatLon(lat:Float, lon:Float) func description() -> String { switch self { case let .Address(street, city): return street + ', ' + city case let .LatLon(lat, lon): return '((lat), (lon))' } } } let loc1 = Location.Address(street: '2070 Fell St', city: 'San Francisco') let loc2 = Location.LatLon(lat: 23.117, lon: 45.899) print(loc1.description()) // '2070 Fell St, San Francisco' print(loc2.description()) // '(23.117, 45.988)'
Du kan finne mer informasjon om oppføringer her .
Tuples grupperer flere verdier i en enkelt sammensatt verdi. Verdier i en tupel kan være av hvilken som helst type og trenger ikke å være av samme type som hverandre.
let person = ('Gabriel', 'Kirkpatrick') print(person.0) // Gabriel
Du kan også navngi individuelle tupelelementer:
let person = (first: 'Gabriel', last: 'Kirkpatrick') print(person.first)
Tupler er ekstremt praktiske som returtyper for funksjoner som trenger å returnere mer enn en verdi:
func intDivision(a: Int, b: Int) -> (quotient: Int, remainder: Int) { return (a/b, a%b) } print(intDivision(11, 3)) // (3, 2) let result = intDivision(15, 4) print(result.remainder) // 3
I motsetning til Objective-C støtter Swift å finne mønstre i saksuttalelse eller byttesak:
let complex = (2.0, 1.1) // real and imaginary parts switch complex { case (0, 0): println('Number is zero') case (_, 0): println('Number is real') default: println('Number is imaginary') }
I det andre tilfellet bryr vi oss ikke om den sanne delen av tallet, så vi bruker et _
slik at den kan matche hva som helst. Du kan også sjekke om det er tilleggsvilkår i hvert tilfelle. For dette er det nødvendig å bli med i mønsterverdiene:
let complex = (2.0, 1.1) switch complex { case (0, 0): println('Number is zero') case (let a, 0) where a > 0: println('Number is real and positive') case (let a, 0) where a <0: println('Number is real and negative') case (0, let b) where b != 0: println('Number has only imaginary part') case let (a, b): println('Number is imaginary with distance (a*a + b*b)') }
Legg merke til hvordan vi bare må matche verdiene vi skal bruke i sammenligningen eller i bryterveske .
Du kan lese mer om Tuples her .
I motsetning til Objective-C krever Swift ikke at du oppretter separate grensesnitt- og implementeringsdokumenter for tilpassede klasser og strukturer. Når du lærer om Swift, lærer du hvordan du definerer en klasse eller struktur i et enkelt dokument, og det eksterne grensesnittet for den klassen eller strukturen blir automatisk gjort tilgjengelig for bruk av annen kode.
Klassedefinisjonene er veldig enkle:
class Bottle { var volume: Int = 1000 func description() -> String { return 'This bottle has (volume) ml' } } let b = Bottle() print(b.description())
Som du kan se, erklæring og implementering er i samme dokument . Swift bruker ikke lenger en overskrift eller implementeringsdokumenter. La oss legge til en merke i eksemplet vårt:
class Bottle { var volume: Int = 1000 var label:String func description() -> String { return 'This bottle of (label) has (volume) ml' } }
Kompilatoren vil klage, siden etiketten er en variabel som ikke er valgfri, og den vil ikke ha en verdi når en flaske blir instantiert. Vi må legge til en initialisering:
class Bottle { var volume: Int = 1000 var label:String init(label:String) { self.label = label } func description() -> String { return 'This bottle of (label) has (volume) ml' } }
Eller vi kan bruke type Opcional
for en eiendom som ikke trenger å initialiseres. I det følgende eksemplet konverterer vi til volumen
a Número entero Opcional
:
class Bottle { var volume: Int? var label:String init(label:String) { self.label = label } func description() -> String { if self.volume != nil { return 'This bottle of (label) has (volume!) ml' } else { return 'A bootle of (label)' } } }
Swift-språket har også structs
, men de er mye mer fleksible enn Objective-C. Følgende kodeopplæring definerer a struct
:
struct Seat { var row: Int var letter:String init (row: Int, letter:String) { self.row = row self.letter = letter } func description() -> String { return '(row)-(letter)' } }
I likhet med klasser i Swift, kan strukturer ha metoder, egenskaper, initialiserere og være i samsvar med protokoller. Hovedforskjellen mellom klasser og strukturer er at klassene blir gitt ved referanse, mens strukturer blir gitt etter verdi .
Dette eksemplet viser bestått klassene med referanse:
let b = Bottle() print(b.description()) // 'b' bottle has 1000 ml var b2 = b b.volume = 750 print(b2.description()) // 'b' and 'b2' bottles have 750 ml
Hvis vi prøver å gjøre noe lignende med struct
, vil du legge merke til at variabler sendes med verdier:
var s1 = Seat(row: 14, letter:'A') var s2 = s1 s1.letter = 'B' print(s1.description()) // 14-B print(s2.description()) // 14-A
Når skal vi bruke struct
og når bruker vi class
? Som i Objective-C og C, bruk strenger når du trenger å gruppere noen verdier og forvent at de skal kopieres i stedet for refererte eller RGB-farger.
Forekomsten av en klasse er tradisjonelt kjent som et objekt. Imidlertid er Swift-klasser og strukturer mye nærmere i funksjonalitet enn på andre språk, og mye funksjonalitet kan brukes på forekomster av typestruktur eller klasse. Av denne grunn er den mest generelle betegnelsen brukt med henvisning til Swift instancia
, som gjelder en av disse to.
Lær det grunnleggende om Swift-klasser og strukturer her .
Som vi så tidligere, blir eiendommer i Swift erklært med nøkkelordet var
innenfor definisjonen av en klasse eller struktur. Vi kan også erklære med let
instruksjonen.
struct FixedPointNumber { var digits: Int let decimals: Int } var n = FixedPointNumber(digits: 12345, decimals: 2) n.digits = 4567 // ok n.decimals = 3 // error, decimals is a constant
Vær også oppmerksom på at klasseegenskapene er sterkt referert, med mindre du bruker prefikset weak
som nøkkelord. Imidlertid er det noen godbiter med ikke-valgfrie egenskaper som svake, så les Kapittel Automatisk referanseregnskap i Apples Swift Guide ..
Beregnede egenskaper lagrer ikke en verdi. Snarere gir de en getter og en valgfri setter for å hente og sette andre egenskaper og verdier indirekte.
Følgende kode gir et eksempel på en beregnet verdi sign
:
enum Sign { case Positive case Negative } struct SomeNumber { var number:Int var sign:Sign { get { if number <0 { return Sign.Negative } else { return Sign.Positive } } set (newSign) { if (newSign == Sign.Negative) { self.number = -abs(self.number) } else { self.number = abs(self.number) } } } }
Vi kan også definere skrivebeskyttede egenskaper bare ved å implementere en getter:
struct SomeNumber { var number:Int var isEven:Bool { get { return number % 2 == 0 } } }
I Objective-C støttes egenskaper vanligvis av en forekomstvariabel, eksplisitt erklært eller automatisk opprettet av kompilatoren. På den annen side, i Swift, en eiendom har ikke en tilsvarende forekomstvariabel . Det vil si at det ikke er direkte tilgang til en butikk for en eiendom. Anta at vi har dette i mål-C:
// .h @interface OnlyInitialString : NSObject @property(strong) NSString *string; @end // .m @implementation OnlyInitialString - (void)setString:(NSString *newString) { if (newString.length > 0) { _string = [newString substringToIndex:1]; } else { _string = @''; } } @end
Siden i beregninger av Swift ikke har en backing-butikk, trenger vi noe sånt:
class OnlyInitialString { var initial:String = '' var string:String { set (newString) { if countElements(newString) > 0 { self.initial = newString.substringToIndex(advance(newString.startIndex, 1)) } else { self.initial = '' } } get { return self.initial } } }
Eiendommene er nærmere forklart her
Det er mange flere viktige og nye ting å lære i Swift som generisk programmering, interaksjon med Objective-C-biblioteker, nedleggelser, valgfri kjetting og overbelastning av operatøren. En enkelt opplæring kan ikke fullt ut beskrive et nytt språk, men jeg er ikke i tvil om at mye mer vil bli skrevet om Swift-programmering. Imidlertid tror jeg dette Rask lesing vil hjelpe mange Objective-C-utviklere, som ikke har funnet tiden, og heller ikke lære detaljer om Swift-språket, komme i gang og la Swift-fuglen ta deg til nye høyder.