Error Håndtering i Swift 2
15
Del
7
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Jeg har ennå å møte en programmerer som har feilhåndtering. Enten du liker det eller ikke, trenger en robust program for å håndtere feil på en slik måte at søknaden er fortsatt funksjonell og informerer brukeren når det er nødvendig. Som testing, er det en del av jobben.
1. Objective-C
I Objective-C, det var alt for lett å ignorere feilhåndtering. Ta en titt på følgende eksempel der jeg ignorere eventuelle feil som kan oppstå ved gjennomføring av en hente forespørsel
//Execute Fetch RequestNSArray * resultater = [managedObjectContext executeFetchRequest: fetchRequest error: null];. If (resultater) {//Prosess Resultater ...}
Eksempelet ovenfor viser at feilbehandling i Objective-C er noe utbygger må melde deg inn. Hvis du ønsker å vite hva som gikk galt hvis noe går haywire, så du fortelle dette til API ved å levere det en NSError pekeren. Eksemplet nedenfor viser hvordan dette fungerer i Objective-C
NSError * error = null; //Execute Fetch RequestNSArray * resultater =. [ManagedObjectContext executeFetchRequest: fetchRequest error: & error]; if (feil) {//Håndtak Feil ...} else {//Prosess resultater ...}
Mens tidligere versjoner av Swift kom ikke med en god løsning for feilbehandling, har Swift 2 gitt oss det vi har bedt om, og det var vel verdt ventetiden. I Swift 2, er feilhåndtering aktivert som standard. I motsetning til Objective-C, utviklere trenger å eksplisitt fortelle kompilatoren hvis de velger å ignorere feilhåndtering. Selv om dette ikke vil tvinge utviklere å omfavne feilhåndtering, det gjør beslutningen eksplisitt.
Hvis vi skulle oversette eksempelet ovenfor til Swift, vil vi ende opp med samme antall linjer. Mens mengden av koden du trenger å skrive forblir uendret, gjør det svært eksplisitt hva du prøver å gjøre syntaksen.
Gjøre {//Utfører Fetch Request la resultatene = prøve managedObjectContext.executeFetchRequest (fetchRequest) //Prosess resultater ...} catch {la fetchError = feil som NSError //Handle Feil ...}
På slutten av denne opplæringen, vil du forstå ovenfor kodebiten og vet alt du trenger å vite for å håndtere feil i Swift 2.
2. Kaster Funksjoner
kaster
Grunnlaget for feilbehandling i Swift er muligheten for funksjoner og metoder for å kaste feil. I Swift språkbruk, er en funksjon som kan kaste feil referert til som en kasting funksjon. Funksjonen definisjonen av en kaste funksjon er veldig klar denne evnen som vist i følgende eksempel
init (contentsOfURL url: NSURL, opsjoner readOptionsMask: NSDataReadingOptions). Kaster
Den kaster nøkkelord indikerer at init (contentsOfURL: alternativer :) kan kaste en feil hvis noe går galt. Hvis du starter en kaste funksjon, vil kompilatoren kaste en feil, snakker av ironi. Hvorfor er det
lar data = NSData? (ContentsOfURL: URL, opsjoner: [])
prøve
Skaperne av Swift har lagt mye oppmerksomhet i å gjøre språket uttrykksfulle og feilhåndtering er akkurat det, uttrykksfulle. Hvis du prøver å påkalle en funksjon som kan kaste en feil, må funksjonen samtalen skal innledes med prøve søkeordet. Try søkeord er ikke magisk. Alt den gjør, er å lage utvikleren klar over kaste evne til funksjonen.
Vent et sekund. Kompilatoren fortsetter å klage selv om vi har innledet funksjonen samtalen med prøve søkeordet. Hva er det vi mangler?
Kompilatoren ser at vi bruker den prøve søkeord, men det riktig påpeker at vi har ingen måte i stedet for å fange opp eventuelle feil som kan bli kastet. Å fange feil, bruker vi Swift splitter nye do-fangst uttalelse.
gjør-fangst
Hvis en kaste funksjon kaster en feil, vil feil automatisk forplante seg ut av dagens omfang før det er fanget. Dette ligner på unntak i Objective-C og andre språk. Tanken er at en feil må fanget og håndtert på enkelte punkt. Mer spesifikt, forplanter en feil før det er fanget av en fangst leddet i en do-fangst uttalelse
I den oppdaterte eksempelet nedenfor påberope vi init (contentsOfURL:. Alternativer :) metoder i en gjør-fangst statement . I do klausulen, vi påberope funksjon, ved hjelp av forsøk søkeord. I fangsten klausulen, vi håndtere eventuelle feil som ble kastet under utføring funksjonen. Dette er et mønster som er veldig vanlig i Swift 2.
do {la data = prøve NSData (contentsOfURL: URL, alternativer: [])} catch {print ("\\ (feil)")}
I fangsten klausulen, har du tilgang til feilen som ble kastet gjennom et lokalt konstant feil. Fangsten klausulen er mye kraftigere enn det som er vist i eksempelet ovenfor. Vi vil ta en titt på et mer interessant eksempel litt senere.
3. Kaster feil
I Objective-C, du vanligvis bruker NSError, definert i stiftelsen rammeverk, for feilbehandling. Fordi språket ikke definerer hvordan feilhåndtering skal gjennomføres, står du fritt til å definere din egen klasse eller struktur for å skape feil.
Dette er ikke sant i Swift. Mens en hvilken som helst klasse eller struktur kan fungere som en feil, må de i overensstemmelse med den ErrorType protokollen. Protokollen er imidlertid ganske enkelt å implementere siden det ikke erklære noen metoder eller egenskaper.
Oppramsinger er kraftige i Swift og de er en god løsning for feilbehandling. Enums er stor for mønstergjenkjenning funksjonaliteten av fangsten paragrafen i do-fangst uttalelse. Det er lettere å illustrere dette med et eksempel. La oss starte med å definere en enum som samsvarer med ErrorType protokollen
enum PrinterError. ErrorType {case NoToner tilfelle NoPaper tilfelle NotResponding tilfelle MaintenanceRequired}
Vi definerer en enum, PrinterError, som samsvarer med ErrorType protokollen. Den enum har fire medlem variabler. Vi kan nå definere en funksjon for å skrive ut et dokument. Vi passerer funksjonen en NSData forekomst og fortelle kompilatoren at det kan kaste feil ved å bruke kaster søkeord
func printDocumentWithData (data: NSData). Kaster {...}
For å skrive ut et dokument, vi påberope printDocumentWithData ( _ :). Som vi så tidligere, må vi bruke prøve søkeord og pakk funksjonskallet i en gjør-fangst uttalelse. I eksempelet nedenfor, vi håndtere eventuelle feil i fangsten klausulen.
Gjøre {prøve printDocumentWithData (data)} catch {//håndtere feil}
Vi kan forbedre eksempel ved å undersøke feilen som er kastet. En fangst klausul ligner på en bryter uttalelse i at det gir mulighet for mønstergjenkjenning. Ta en titt på den oppdaterte eksempelet nedenfor.
Gjøre {prøve printDocumentWithData (data)} fange PrinterError.NoToner {//Varsle User} fange PrinterError.NoPaper {//Varsle User} catch PrinterError.NotResponding {//Schedule nytt forsøk }
Det ser mye bedre. Men det er ett problem. Kompilatoren er varsle oss om at vi ikke håndterer alle mulige feil på printDocumentWithData (_ :) metoden kan kaste.
kompilatoren er riktig selvfølgelig. En fangst klausul ligner på en bryter uttalelse i at det er behov for å være uttømmende, det er behov for å håndtere alle mulige tilfelle. Vi kan legge til en annen fangst klausul for PrinterError.MaintenanceRequired eller vi kan legge til en catch-all klausul på slutten. Ved å legge til en standard fangst klausul, bør kompilatoren feilen forsvinner.
Gjøre {prøve printDocumentWithData (data)} fange PrinterError.NoToner {//Varsle User} fange PrinterError.NoPaper {//Varsle User} catch PrinterError.NotResponding {//Schedule nytt forsøk} catch {//Håndtak andre feil}
4. Rydde opp etter deg selv
Jo mer jeg lærer om Swift språk, jo mer jeg kommer til å sette pris på det. Den Utsett uttalelsen er en annen flott tillegg til språket. Navnet summerer det opp ganske pent, men la meg vise deg et eksempel for å forklare konseptet
func printDocumentWithData (data: NSData). Kaster {if canPrintData (data) {powerOnPrinter () prøver printData (data) utsette {powerOffPrinter ( )}}}
Eksempelet er litt contrived, men det illustrerer bruken av Utsett. Blokken av Utsett setningen utføres før henrettelsen avslutter omfang der Utsett uttalelsen vises. Det kan være lurt å lese den setningen igjen.
Det betyr at powerOffPrinter () -funksjonen aktiveres selv om printData (_ :) funksjon kaster en feil. Jeg er sikker på at du kan se at det fungerer veldig bra med Swifts feilbehandling.
Plasseringen av Utsett regnskapet innenfor hvis setningen er ikke viktig. Følgende oppdatert eksempel er identisk så langt som kompilatoren er opptatt
func printDocumentWithData (data: NSData). Kaster {if canPrintData (data) {utsette {powerOffPrinter ()} powerOnPrinter () prøver printData (data)}}
Du kan ha flere utsette uttalelser så lenge du huske på at de er utført i omvendt rekkefølge de vises.
5. Formering
Det er mulig at du ikke ønsker å håndtere en feil, men i stedet la det boble opp til et objekt som er i stand til eller er ansvarlig for håndtering av feil. Det er greit. Ikke alle prøver uttrykk trenger å bli pakket i en gjør-fangst uttalelse. Det er en betingelse skjønt, funksjon som kaller kaste funksjonen må være en kasting funksjonen selv. Ta en titt på de to neste eksemplene
func printTestDocument () {//Legg dokumentdata la dataForDocument = NSData (contentsOfFile: "pathtodocument") hvis la data = dataForDocument {prøve printDocumentWithData (data)}}. Func printTestDocument () kaster {//Legg dokumentdata la dataForDocument = NSData (contentsOfFile: "pathtodocument") hvis la data = dataForDocument {prøve printDocumentWithData (data)}}
Det første eksemplet resulterer i en kompilator feil, fordi vi ikke håndterer det feil som printDocumentWithData (_ :) kan kaste. Vi kan løse dette problemet i det andre eksemplet ved å markere printTestDocument () -funksjonen som kaster. Hvis printDocumentWithData (_ :) kaster en feil, da feilen er gått til den som ringer på printTestDocument () -funksjonen.
6. Omgåelsen Feilhåndtering
I begynnelsen av denne artikkelen, skrev jeg at Swift vil at du skal omfavne feilhåndtering ved å gjøre det enkelt og intuitivt. Det kan være ganger at du ikke ønsker eller trenger å håndtere feil som er kastet. Du bestemmer deg for å stoppe utbredelsen av feil. Det er mulig ved hjelp av en variant av forsøk søkeord, prøve !.
I Swift, et utropstegn alltid fungerer som en advarsel. Et utropstegn i utgangspunktet forteller utvikleren at Swift er ikke lenger ansvarlig hvis noe går galt. Og det er det prøve! ordet forteller deg. Hvis du starter et kaste funksjon samtale med forsøk! nøkkelord, også kjent som en tvungen-prøve uttrykk, er feilspredning deaktivert.
Selv om dette kan høres fantastisk for noen av dere, må jeg advare deg at dette er ikke hva du tror det er. Hvis en kaster funksjon kaster en feil og du har deaktivert feil forplantning, så vil du kjøre inn i en runtime error. Det betyr stort sett at søknaden din vil krasje. Du har blitt advart.
7. Objective-C API
Swift teamet hos Apple har lagt mye arbeid i å gjøre feilhåndtering så transparent som mulig for Objective-C APIer. For eksempel, har du lagt merke til at den første Swift eksempel på denne opplæringen er en Objective-C API. Til tross for API blir skrevet i Objective-C, ikke metoden ikke akseptere en NSError pekeren som sin siste argumentet. Til kompilatoren, er det en vanlig kastemetode. Dette er hva metodedefinisjon ser ut i Objective-C Anmeldelser - (NSArray *) executeFetchRequest: (NSFetchRequest *) forespørsel error: error (NSError **);
Og dette er hva metodedefinisjon ser ut i. . Swift
offentlig func executeFetchRequest (forespørsel: NSFetchRequest) kaster - > [AnyObject]
De feil som executeFetchRequest (forespørsel: NSFetchRequest) kaster er NSError tilfeller. Dette er bare mulig, fordi NSError i samsvar med ErrorType protokollen som nevnt tidligere. Ta en titt på Oppfyller kolonne under.
Les mer i vår Swift to Programmering Course
Swift 2 har en rekke nye funksjoner og muligheter. Ta vår kurs på Swift to utvikling for å komme deg opp til hastighet. Feilhåndtering er bare en liten del av mulighetene for Swift 2.
Konklusjon
Den takeaway budskapet i denne artikkelen er at feilhåndtering steiner i Swift. Hvis du har betalt oppmerksomhet, så du har også plukket opp at du må vedta feilbehandling hvis du velger å utvikle seg i Swift. Bruke prøve! søkeord vil ikke få deg ut av feilbehandling. Det er det motsatte, å bruke det for ofte vil få deg i trøbbel. Gi det en sjanse, og jeg er sikker på at du kommer til å elske det når du har gitt det litt tid.