Enten du prøver å finne ut hvorfor din matrise har 3 objekter i stedet for 5 eller hvorfor spillet ditt spilles bakover siden den nye fyren startet, er feilsøking en viktig del av utviklingsprosessen. På slutten av denne artikkelen har du en forståelse av de viktigste feilsøkingsfasilitetene som er tilgjengelige for deg og hvordan du bruker dem til å hjelpe deg med å knuse dine feil på kort tid.
Vi skal dekke hvordan:
Den lille svarte boksen nederst på Xcode skal være din beste venn når det gjelder feilsøking. Den sender ut loggmeldinger, feilmeldinger og alle andre nyttige ting som kan hjelpe deg med å spore feil. I tillegg til å lese produksjon direkte fra loggen, kan vi også stoppe ved et gitt punkt i vårt program og inspisere ulike deler av vår søknad.
Jeg kommer til å anta at du vet hvordan breakpoints fungerer (og hvis du ikke gjør det, ikke bekymre deg, vil du plukke den opp på slutten av dette!). Breakpoints er uvurderlige for å se hvor applikasjonen vår er på et gitt tidspunkt, men det kan være vondt å gå gjennom en loop eller rekursiv funksjon etter å ha utløst et brytepunkt til vårt objekt er lik en viss verdi. Angi betingede bruddpunkter!
Betingede bruddpunkter er breakpoints som bare bryter når en viss tilstand er oppfylt. Tenk deg at vi bare vil bryte når et objekt er i en bestemt tilstand, eller på den nte iterasjonen av en løkke. Legg til et bruddpunkt i koden ved å klikke på "ruten" i Xcode-editoren, høyreklikk på brytpunktet, og velg deretter "rediger brytepunkt" for å angi spesielle forhold.
Du kan gi en tilstand (f.eks. I == 12) eller antall ganger pausepunktet bør ignoreres. Du kan også legge til handlinger som skjer automatisk ved pause, for eksempel en debugger-kommando som skriver ut en verdi.
Tips: Tastaturgenveien for å legge til / fjerne et pausepunkt er kommando + \Et annet viktig bruddpunkttrick å implementere er å legge til "unntakspauspunktet". Noe lagt merke til at 99% av tiden når vi treffer et unntak, tar Xcode oss til autorelease-bassenget i vår hovedmetode?
Ved å sette et unntakspunkt, kan du gå til den eksakte koden som forårsaket unntaket med et pausepunkt. For å gjøre dette, åpne unntakspunktet pause (kommando + 6). Nederst til venstre i vinduet er det en "+" -knapp. Velg dette for å legge til et "unntakspauspunkt". Nå når Xcode møter et unntak, vil det bryte hvor i koden det skjedde.
Hvis vi har brutt på et bestemt punkt i vår app generelt, er det fordi vi vil se hvilken tilstand våre objekter er i. Xcode gir oss "variabellevisningen" som er den visningen nederst på Xcode ved siden av konsollen. I teorien viser den nåværende tilstanden til alle verdiene som er relevante i den nåværende konteksten. I praksis viser dette noen ganger å være en liten buggy. Noen ganger vil det ikke oppgi verdier eller ikke oppdatere dem når du går gjennom.
Heldigvis kan vi inspisere bestemte objekter selv ved å bruke noen svært nyttige konsollkommandoer. Ved å skrive 'po' inn i konsollen kan vi få øyeblikkelig detalj om et gitt objekt (når vi arbeider med skalarverdier bruker vi 'p').
Dette kan være nyttig for å se om et objekt allerede eksisterer (dette vil skrive ut nil hvis det ikke gjør det), bestemme verdien av et objekt, finne ut hva en matrise / ordbok inneholder i kjøretid, og til og med sammenligne to objekter. Fordi denne kommandoen skriver ut minnesadressen til det aktuelle objektet, kan du skrive ut to objekter som du tror skal være det samme og se om de har samme minnesadresse for å være sikker.
En annen nyttig, men skjult kommando som du kan bruke til å enkelt inspisere dine synspunkter er recursiveDescription kommando. Ring dette på en visning for å få en utskrift av visningshierarkiet.
Det er visse tider når feilsøking av programmet vårt vil vi logge en bestemt melding til konsollen. NSLog-funksjonen tillater oss å skrive ut hvilken produksjon vi ønsker til konsollen. Dette kan være viktig hvis vi vil følge visse veier gjennom vår søknad eller teste hva en verdi er lik uten å eksplisitt plassere bruddpunkter på hver mulig linje. NSLog følger samme format som [NSString StringWithFormat] metode (som du kan se i snarveien nedenfor).
Tips: Nytt for formatering av strenger i Objective-C? Sjekk ut Apples String Programmerings GuideMens NSLog er nyttig, må vi være kloge på hvordan vi implementerer den. Alt som er skrevet ut fra NSLog, går inn i produksjonskode, og er derfor synlig for alle. Hvis noen skulle koble enheten til arrangøren og se på konsollen, kunne de se hver eneste loggmelding. Som du kan forestille deg, kan det ha noen alvorlige implikasjoner! Tenk deg om du har skrevet ut noen hemmelig algoritmlogikk eller brukerens passord til konsollen! På grunn av dette blir apper noen ganger avvist hvis Apple oppdager for mye utgang til konsollen i en produksjonsbygg.
Heldigvis er det en bedre måte å gjøre logging på. Avhengig av hvor mye innsats du vil legge inn, er det flere måter å gå om dette. Kanskje den enkleste måten er å bruke en makro som bare inkluderer NSLog i feilsøking. Inkludert dette i en globalt tilgjengelig headerfil betyr at du kan sette så mange logger som du vil i koden din, eller ingen av det vil gå inn i produksjonen (forutsatt at du ikke endrer standard forprosessorens makroverdier, og hvis du ikke vet hva de er, ikke bekymre deg).
#ifdef DEBUG #define DMLog (...) NSLog (@ "% s% @", __PRETTY_FUNCTION__, [NSString stringWithFormat: __ VA_ARGS__]) #else #define DMLog (...) gjør mens (0)
Nå hvis du bruker DMLog (eller hva du velger å ringe din), vil den bare skrive ut dette under en feilsøking. Enhver produksjon bygger ikke vil gjøre noe. __PRETTY_FUNCTION__ Hjelper også med å skrive ut navnet på funksjonen som loggen kommer fra.
Mens NSLog er flott, har den en rekke begrensninger:
For de som ønsker å få hardcore om logging, er det rammer der ute som overvinne noen eller alle disse begrensningene avhengig av hvor mye innsats du vil sette inn. Jeg vil anbefale å se på følgende verktøy:
Selv om introduksjonen av Automatic Reference Counting (ARC) har sørget for at minnehåndtering ikke er den massive tidsvampyren det pleide å være, er det fortsatt viktig å spore viktige hendelser i livets sykluser i objektet. Tross alt eliminerer ikke ARC muligheten for hukommelse lekkasjer eller prøver å få tilgang til en utgitt gjenstand (det gjør det bare vanskeligere å gjøre). For dette formål kan vi implementere en rekke prosesser og verktøy for å hjelpe oss å holde øye med hva våre objekter gjør.
De to viktigste metodene i et Objective-C-objekts livssyklus er i det og dealloc metoder. Det er en god ide å logge disse hendelsene til konsollen din, slik at du kan se når objektene dine kommer til livs, og enda viktigere, sørg for at de går bort når de skal.
- (id) init self = [super init]; hvis (selv) NSLog (@ "% @:% @", NSStringFromSelector (_cmd), selv); returner selv; - (void) dealloc NSLog (@ "% @:% @", NSStringFromSelector (_cmd), selv);
Mens du skriver denne koden, kan det virke kjedelig å starte, finnes det måter å automatisere prosessen og gjøre det lettere. Jeg kan garantere at det kommer til nytte når søknaden oppfører seg på måter det ikke skal. Du kan også bruke noen få triks du lærte i loggingsseksjonen, slik at dette ikke skrives ut i en produksjonsbygging (eller enda bedre, lag en makro for det selv!).
Det finnes to verktøy som følger med Xcode som vi kan bruke til å rydde opp koden vår og gjøre koden mindre feilaktig. Static Analyzer-verktøyet er en grei måte for Xcode å anbefale forbedringer av vår kode, fra ubrukt objekter til potensielt under eller over utgitte objekter (fortsatt et problem på ARC for Core Foundation-objekter). For å se disse anbefalingene, gå til Produkt og velg 'Anlayze'.
Inspektøren er et kraftig verktøy som gjør det mulig for oss å nøye "inspisere" ulike aspekter av applikasjonen vår å gjøre med minnebruk, aktivitet på filsystemet, og det gir selv måter å automatisere brukerinteraksjon. For å "inspisere" søknaden din, velg "Profil" i rullegardinmenyen "Produkt".
Dette åpner vinduet Instrumenter hvor du kan velge en profilmal som skal kjøres. De vanligste å kjøre er zombier (vi diskuterer dette senere), aktivitetsmonitor og lekkasjer. Lekkasjer er kanskje den mest nyttige malken som skal løpe for å jakte på eventuelle minnelekkasjer som kan være tilstede i søknaden din.
Selv om det er mye vanskeligere å løpe inn i den fryktede EXC_BAD_ACCESS-feilen nå da ARC er på plass, kan det fortsatt skje under visse omstendigheter. Når vi arbeider med UIPopoverController eller kjernevirksomhetsobjekter, kan vi fortsatt forsøke å få tilgang til et overlatt objekt. Normalt, når vi slipper et objekt i minnet, er det borte for alltid. Men når Zombies er aktivert, blir objektet bare merket som utgitt, men forblir i minnet. På den måten når vi får tilgang til et Zombie-objekt, kan Xcode fortelle oss at du prøvde å få tilgang til et objekt som normalt ikke ville være der. Fordi det fortsatt vet hva det er, kan det fortelle deg hvor og når det skjedde.
Du kan jakte på zombier ved hjelp av to metoder. Enten ved å bruke inspektøren og kjøre en Zombie profilmal, eller ved å aktivere den som et diagnostisk alternativ i alternativet "Kjør" bygge. Rett ved siden av stoppknappen klikker du på skjemanavnet, deretter klikker du på "Rediger skjema" og under løp klikker du på diagnostikkfanen og velger "Aktiver Zombie Objects". Vær oppmerksom på at feilsøking i Zombie-modus bare er tilgjengelig når feilsøking i simulatoren, du kan ikke gjøre det på en faktisk enhet.
Forhåpentligvis ga ovennevnte deg noen få innblikk i hvordan du kan feilsøke applikasjonene dine mer effektivt. Det handler om å finne måter å redusere tidsbesparende feilretting, slik at vi kan bruke mer tid på å gjøre det som er viktig, bygge gode apps!
Dette er på ingen måte en omfattende liste. Det er mange andre teknikker som ikke har blitt diskutert her, for eksempel feilsøkingsproblemer i produksjon, fjernbullrapportering, krasjrapportering og mer. Har du en teknikk du vil dele? Kanskje har du et spørsmål relatert til ett av de ovennevnte punktene? Legg det under i kommentarene!
Glad programmering!