Av Payal Gupta

Kopiering av et objekt har alltid vært en viktig del i kodingsparadigmet. Enten Det er I Swift, Objective-C, JAVA eller et annet språk, må vi alltid kopiere et objekt for bruk i forskjellige sammenhenger.

I denne artikkelen vil vi diskutere i detalj hvordan du kopierer ulike datatyper I Swift og hvordan de oppfører seg i ulike situasjoner.

Verdi-og Referansetyper

alle datatypene I Swift faller stort sett inn i to kategorier, nemlig verdityper og referansetyper.

  • Verditype — Hver forekomst beholder en unik kopi av dataene. Datatyper som faller inn i denne kategorien inkluderer – all the basic data types, struct, enum, array, tuples.
  • Referansetype — forekomster deler en enkelt kopi av dataene, og typen er vanligvis definert som en class.

det mest karakteristiske trekk ved begge typene ligger i deres kopieringsadferd.

Hva Er Dyp og Grunne kopier?

en forekomst, enten det er en verditype eller en referansetype, kan kopieres på en av følgende måter:

Deep copy — Dupliserer alt

  • med en dyp kopi kopieres ethvert objekt som pekes til av kilden, og kopien pekes til av destinasjonen. Så to helt separate objekter vil bli opprettet.
  • Samlinger – en dyp kopi av en samling er to samlinger med alle elementene i den opprinnelige samlingen duplisert.
  • Mindre utsatt for raseforhold og fungerer bra i et flertrådet miljø-endringer i ett objekt vil ikke ha noen effekt på et annet objekt.
  • Verdityper kopieres dypt.

i koden ovenfor,

  • Linje 1: arr1 – matrise (en verditype) Av Strenger
  • Linje 2: arr1 er tilordnet arr2. Dette vil skape en dyp kopi av arr1 og deretter tilordne den kopien til arr2
  • Linjer 7 til 11: eventuelle endringer gjort i arr2 gjenspeiler ikke i arr1.

dette er hva deep copy er-helt separate forekomster. Det samme konseptet fungerer med alle verdityper.

i noen scenarier, det vil si når en verditype inneholder nestede referansetyper, viser deep copy en annen type oppførsel. Vi ser det i kommende seksjoner.

Shallow copy — Duplikater så lite som mulig

  • med en shallow copy, er ethvert objekt som er pekt på av kilden også pekt på av destinasjonen. Så bare ett objekt vil bli opprettet i minnet.
  • Samlinger-en grunne kopi av en samling er en kopi av samlingsstrukturen, ikke elementene. Med en grunne kopi deler to samlinger nå de enkelte elementene.
  • Raskere-bare referansen kopieres.
  • Kopieringsreferansetyper oppretter en grunne kopi.

i koden ovenfor,

  • Linje 1 til 8: Address klasse type
  • Linje 10: a1 – en forekomst av Address type
  • Linje 11: a1 er tilordnet a2. Dette vil skape en grunne kopi av a1 og deretter tilordne den kopien til a2, det er bare referansen som kopieres til a2.
  • Linjene 16 til 19: eventuelle endringer gjort i a2 vil sikkert reflektere i a1.

i illustrasjonen ovenfor kan vi se at både a1 og a2 peker på samme minneadresse.

Kopierer Referansetyper Dypt

Fra nå av vet vi at når vi prøver å kopiere en referansetype, kopieres bare referansen til objektet. Ingen nye objekter er opprettet. Hva om vi ønsker å skape et helt eget objekt?

vi kan lage en dyp kopi av referansetypen ved hjelp av metoden copy(). Ifølge dokumentasjonen Returnerer

copy() — objektet returnert av copy(with:).

Dette er en bekvemmelighetsmetode for klasser som tar i bruk NSCopying – protokollen. Et unntak er hevet hvis det ikke er noen implementering for copy(with:).

la oss omstrukturere Address class vi opprettet I Kodebit 2 for å overholde NSCopying – protokollen.

i koden ovenfor,

  • Linjer 1 til 14: Address klassetype samsvarer med NSCopying og implementerer copy(with:) metode
  • Linje 16: a1 – en forekomst av Address type
  • Linje 17: a1 er tilordnet a2 ved hjelp av copy() – metoden. Dette vil skape en dyp kopi av a1 og deretter tilordne den kopien til a2, det vil si et helt nytt objekt vil bli opprettet.
  • Linjer 22 til 25: eventuelle endringer gjort i a2 vil ikke gjenspeile i a1.

som det fremgår av illustrasjonen ovenfor, peker både a1 og a2 på forskjellige minnesteder.

La oss se på et annet eksempel. Denne gangen ser vi hvordan det fungerer med nestede referansetyper — en referansetype som inneholder en annen referansetype.

i koden ovenfor,

  • Linje 22: en dyp kopi av p1 er tilordnet p2 ved hjelp av copy() – metoden. Dette innebærer at enhver endring i en av dem ikke må ha noen effekt på den andre.
  • Linjene 27 til 28: p2's name og city verdiene endres. Disse må ikke gjenspeile i p1.
  • Linje 30: p1's name er som forventet, men det er city? Det burde være "Mumbai" burde det ikke? Men vi kan ikke se at det skjer. "Bangalore" var bare for p2 ikke sant? Yup … akkurat.?

dyp kopi…!? Det var ikke forventet av deg. Du sa du ville kopiere alt. Og nå oppfører du deg slik. Hvorfor oh hvorfor..?! Hva gjør jeg nå? ☠ ️

ikke få panikk. La oss se på hvilke minneadresser som har å si i dette.

fra illustrasjonen ovenfor kan vi se at

  • p1 og p2 peker på forskjellige minnesteder som forventet.
  • men deres address variabler peker fortsatt på samme sted. Dette betyr at selv etter å ha kopiert dem dypt, kopieres bare referansene-det vil si en grunne kopi selvfølgelig.

vær oppmerksom: hver gang vi kopierer en referansetype, opprettes en grunne kopi som standard til vi eksplisitt angir at den skal kopieres dypt.

func copy(with zone: NSZone? = nil) -> Any{ let person = Person(self.name, self.address) return person}

i ovennevnte metode implementerte vi tidligere for Person – klassen, vi har opprettet en ny forekomst ved å kopiere adressen med self.address . Dette vil bare kopiere referansen til adresseobjektet. Dette er grunnen til at både p1 og p2's address peker på samme sted.

så kopiering av objektet ved hjelp av metoden copy() vil ikke skape en ekte dyp kopi av objektet.

slik dupliserer du et referanseobjekt helt: referansetypen sammen med alle nestede referansetyper må kopieres med copy() – metoden.

let person = Person(self.name, self.address.copy() as? Address)

Ved å Bruke koden ovenfor i func copy(with zone: NSZone? = nil) -> Vil enhver metode få alt til å fungere. Du kan se det fra illustrasjonen nedenfor.

True Deep Copy-Referanse-Og Verdityper

Vi har allerede sett hvordan vi kan lage en dyp kopi av referansetypene. Selvfølgelig kan vi gjøre det med alle nestede referansetyper.

men hva med den nestede referansetypen i en verditype, det vil si en rekke objekter, eller en referansetypevariabel i en struktur eller kanskje en tuple? Kan vi løse det ved å bruke copy() også? Nei vi kan ikke, faktisk. copy() – metoden krever implementering av NSCopying – protokollen som bare fungerer for NSObject – underklasser. Verdityper støtter ikke arv, så vi kan ikke bruke copy() sammen med dem.

i linje 2 er bare strukturen til arr1 dypt kopiert, men Address – objektene i den er fortsatt grunne kopiert. Du kan se det fra under minnekartet.

elementene i både arr1 og arr2 peker begge til de samme minneplassene. Dette er på grunn av samme grunn — referansetyper er grunne kopiert som standard.

Serialisering og deretter de-serialisering av et objekt oppretter alltid et helt nytt objekt. Den er gyldig for både verdityper og referansetyper.

her er Noen Apier som vi kan bruke til å serialisere og de-serialisere data:

  1. NSCoding-en protokoll som gjør det mulig for et objekt å bli kodet og dekodet for arkivering og distribusjon. Det vil bare fungere med class type objekter som det krever arve fra NSObject.
  2. Codable — Gjør datatypene kodbare og dekodbare for kompatibilitet med eksterne representasjoner som JSON. Det vil fungere for begge verdityper – struct, array, tuple, basic data types samt referansetyper – class.

La oss omstrukturere Address – klassen litt lenger for å overholde Codable – protokollen og fjerne all NSCopying – koden som vi la til tidligere I Kodebit 3.

i koden ovenfor vil linjene 11-13 skape en ekte dyp kopi av arr1. Nedenfor er illustrasjonen som gir et klart bilde av minneplasseringene.

Kopier På Skriv

Kopier på skriv er en optimaliseringsteknikk som bidrar til å øke ytelsen når du kopierer verdityper.

La oss si at vi kopierer en Enkelt Streng Eller Int eller kanskje en annen verditype-vi vil ikke møte noen viktige ytelsesproblemer i det tilfellet. Men hva med når vi kopierer en rekke tusenvis av elementer? Vil det fortsatt ikke skape noen ytelsesproblemer? Hva om vi bare kopierer det og ikke gjør noen endringer i den kopien? Er ikke det ekstra minnet vi brukte bare bortkastet i det tilfellet?

Her kommer Begrepet Kopi I Skriv – når du kopierer, peker hver referanse til samme minneadresse. Det er først når en av referansene endrer de underliggende dataene At Swift faktisk kopierer den opprinnelige forekomsten og gjør endringen.

det vil si om det er dyp kopi eller grunne kopier, vil en ny kopi ikke bli opprettet før vi gjør en endring i et av objektene.

i koden ovenfor,

  • Linje 2: en dyp kopi av arr1 er tilordnet arr2
  • Linjer 4 Og 5: arr1 ogarr2 peker fortsatt på samme minneadresse
  • Linje 7: endringer i arr2
  • Linjer 9 og 10: arr1 ogarr2 peker nå på forskjellige minnesteder

nå vet du mer om dype og grunne kopier og hvordan de oppfører seg i forskjellige scenarier med forskjellige datatyper. Du kan prøve dem med ditt eget sett med eksempler og se hvilke resultater du får.

Videre lesing

ikke glem å lese mine andre artikler:

  1. Alt Om Kodbart I Swift 4
  2. Alt du alltid har ønsket å vite om varsler i iOS
  3. Farg DET MED GRADIENTER — iOS
  4. Koding for iOS 11: hvordan dra & slipp inn samlinger & tabeller
  5. Alt du trenger å vite Om Dagens Utvidelser (Widget) i ios 10
  6. Uicollectionviewcell Utvalg Gjort Enkelt..!!

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.