Allir vs. AnyObject í Swift 3.0

Þegar ég rakst á þessar tvær tegundir samheiti meðan ég var að greina JSON gögn í fyrsta skipti hafði ég enga hugmynd um hvernig ég ætti að greina eða útfæra þau á réttan hátt. Svo, hvað eru þeir? Any og AnyObject eru tvær sérstakar gerðir í Swift sem eru notaðar til að vinna með ósértækar gerðir.

Samkvæmt Swift skjölum Apple,

  • Allir geta táknað dæmi af hvaða gerð sem er, þar á meðal aðgerðir og valfrjálsar gerðir.
  • AnyObject getur táknað dæmi af hvaða tegund tegund sem er.

Allt í lagi, einfalt - Einhver er notuð fyrir allar gerðir, AnyObject er notað fyrir tegundir, ekki satt?

Til að skilja hvernig þeir virkilega hegða sér í kóða ákvað ég að leika með þeim á leikvellinum.

Hvaða dæmi sem er

Allir leyfðu mér að vinna með blöndu af mismunandi gerðum, þar með talið aðgerðum og tegundum án flokka eins og Int, String og Bool. Samkvæmt skjölunum eru þættirnir í þessu fylki mannvirki sem eru gildistegundir, þannig að fræðilega séð ætti AnyObject ekki að virka í þessum tilvikum.

Til að sannreyna þetta reyndi ég að setja strengi og innskot, sem eru gildistegundir í Swift, með AnyObject.

AnyObjectArray Villa þegar talið er upp mannvirki

Eins og búist var við henti þýðandinn mér villu við að segja að þættirnir væru ekki í samræmi við gerðina AnyObject í fylkingunni. Gotcha!

Síðan gerðist þetta undarlega þegar ég reyndi að fylgja tillögum þýðandans:

Frumefni sem varpað er til AnyObject

Hvað var að gerast?! Hvernig gat ég notað AnyObject á ints og strengi með því að varpa hlutunum sérstaklega út til AnyObject?

Ég prentaði síðan anyObjectArray í hugga.

Prentun á hvaða hlut sem er

Þátturinn Hæ leit augljóslega út eins og strengur fyrir mig, en það var ekki með tilvitnanir í kringum sig eins og venjulegt strenggildi í Swift!

Næst prentaði ég hvern þátt með for-í lykkju til að athuga raunverulega gerð þess frekar en steypta gerð AnyObject.

Í fyrsta lagi notaði ég stjórnandann til að sjá hvort þættirnir eru Swift Struct-gerðir eða ekki.

Athugað gerðir af frumefnum í hvaða hlut sem er

Það er af gerðinni String! Hvernig gat það þá verið varpað á AnyObject? Aftur, Strengir í Swift eru mannvirki, ekki tegundir. Fræðilega séð ætti ég ekki að geta varpað þeim sem AnyObject.

Hvað?

Ég var algjörlega ruglaður og ákvað að gera nokkrar fleiri tilraunir með það. Að þessu sinni notaði ég NSNumber og NSString, sem eru Objective-C gerðir, til að athuga tegund hvers frumefnis.

Athugað gerðir af frumefnum í hvaðaObjectArray 2

Bíddu, hæ er líka NSString og tölustafir eru NSNumber! Og ... þær eru tilvísunargerðir í Objective-C! Var þetta ástæðan fyrir því að Hæ var ekki með tilvitnanir í það í hugga? Ég skrifaði meiri kóða eins og hér að neðan til að sjá hvort forsenda mín væri rétt.

Prentun NSString Array og String ArrayHæ með engar tilvitnanir í vélinni sem NSString

Staðfest! Þeir þættir sem varpað eru á AnyObject í fylkinu eru nú tegundir Objective-C: NSString og NSNumber.

Svo ... Hvað er eiginlega að gerast undir hettunni? Ég hélt áfram að grafa mig inn í þetta efni og fann trúverðugasta svarið úr skjalinu Using Swift with Cocoa and Objective-C (Swift 3.0.1).

Sem hluti af rekstrarsamhæfi sínu við Objective-C býður Swift upp á þægilegar og skilvirkar leiðir til að vinna með kakóarammar. Swift breytir sjálfkrafa sumum Objective-C gerðum í Swift gerðir og sumar Swift gerðir í Objective-C gerðir. Tegundir sem hægt er að umbreyta á milli Objective-C og Swift er vísað til sem brúar gerða.
Hvar sem þú getur notað brúaðan Ob Object-C tilvísunargerð geturðu notað Swift gildi tegund í staðinn. Þetta gerir þér kleift að nýta þér þá virkni sem er til staðar við framkvæmd tilvísunargerðarinnar á náttúrulegan hátt í Swift kóða. Af þessum sökum ættir þú næstum aldrei að þurfa að nota brúaða tilvísunargerð beint í eigin kóða. Reyndar, þegar Swift kóða flytur inn Objekt-C API, kemur innflytjandinn í stað Objective-C tilvísunargerða fyrir samsvarandi gildi þeirra. Sömuleiðis, þegar Objekt-C kóða flytur inn Swift API, flytur innflytjandinn einnig Swift gildi tegundir með samsvarandi Ob Object-C viðmiðunartegundum. “

Með öðrum orðum, þýðandinn gerir sitt besta til að vera sveigjanlegur í meðhöndlun slíkra tegunda með sjálfvirkum umbreytingum og brúargerð en kemur í veg fyrir að forritið okkar geti hrunið auðveldlega. Ljómandi!

Svo hvenær notum við í raun AnyObject? Eins og fram kemur í skjölum Apple er hægt að nota AnyObject til að vinna með hluti sem eiga uppruna sinn í flokki en eiga ekki sameiginlegan rótaröð.

En er algerlega nauðsynlegt að nota það í kóðanum okkar?

Svar mitt við þessari spurningu er: Nei.

Apple segir:

Í Swift 3 kortar ID-tegundin í Objective-C nú hvers kyns gerð í Swift, sem lýsir gildi hvers konar, hvort sem er tegund, enum, struct eða einhverri annarri Swift gerð. Þessi breyting gerir API-skjöl Objekt-C sveigjanlegri í Swift, vegna þess að hægt er að færa Swift-skilgreindar gildistegundir yfir í Objective-C API og draga þær út sem Swift-gerðir og útrýma þörfinni fyrir handvirkar „kassategundir“.
Þessi ávinningur nær einnig til safna: Objective-C safnategundir NSArray, NSDictionary og NSSet, sem áður aðeins samþykktu þætti AnyObject, geta nú haft þætti af hvaða gerð sem er. Fyrir gáma ílát, svo sem Orðabók og Set, er til ný tegund AnyHashable sem getur geymt gildi hvers konar sem er í samræmi við Swift Hashable siðareglur.

Svo virðist sem Allir einir og einn virki fullkomlega vel við að brúa þessi tvö tungumál í Swift 3 án þess að nota AnyObject!

Svo hver var endanleg rök fyrir þessum breytingum?

Að eigin sögn útskýrir Apple:

Swift 3 tengi við Objekt-C API á öflugri hátt en fyrri útgáfur. Til dæmis kortlagði Swift 2 kóðategundina í Objective-C við AnyObject gerðina í Swift, sem venjulega getur aðeins innihaldið tegundir tegundar. Swift 2 lagði einnig fram óbeina viðskipti til AnyObject fyrir nokkrar brúaðar gildistegundir, svo sem String, Array, Dictionary, Set, og nokkrar tölur, til þæginda svo að hægt væri að nota innfæddar tegundir Swift auðveldlega með kakó-API sem bjóst við NSString, NSArray, eða aðrir gámaflokkar frá Foundation. Þessi viðskipti voru í ósamræmi við restina af tungumálinu, sem gerði það erfitt að skilja hvað nákvæmlega væri hægt að nota sem AnyObject, sem leiddi til galla.

Maður myndi þó krefjast þess að við iOS verktaki þurfum alltaf að vera eins sértækir og mögulegt er hvað varðar notkun tegunda í kóða.

Reyndar mælir Apple með:

Notaðu eingöngu hvert sem er og hvert sem er þegar þú þarft beinlínis að hegðun og getu sem þeir bjóða upp á. Það er alltaf betra að vera nákvæmur um þær tegundir sem þú býst við að vinna með í kóðanum þínum.

Hugsaðu um þessa atburðarás: Við erum að vinna með númer 12.5 í Swift. Í þessu tilfelli viljum við sérstaklega taka fram að það er tegund af tvöföldum eða floti frekar en að lýsa því yfir af gerðinni hvaða. Þannig getum við auðveldlega nálgast mismunandi eiginleika eða aðferðir sem eru í boði fyrir þá tegund. Í þessu samhengi myndum við nota AnyObject fyrir tegundir af tegundum vegna þess að þær eru aðeins nákvæmari en nokkur. En aftur, notkun AnyObject er bara valkostur.

Ég vona að þessi bloggfærsla hafi hjálpað mörgum ykkur frábæru verktaki við að skýra Any og AnyObject. Notaðu hvaða sem er með sjálfstrausti í Swift 3 þegar þú vinnur með API-skjölum með Ob Object-C.

Þakka þér fyrir að lesa og ánægð kóðun!