Jebkurš pret AnyObject operētājsistēmā Swift 3.0

Pirmoreiz parsējot JSON datus, es saskāros ar šiem divu veidu aizstājvārdiem, man nebija ne mazākās nojausmas, kā tos pareizi atšķirt vai ieviest. Kas viņi ir? Jebkurš un AnyObject ir divi īpaši Swift tipi, kurus izmanto darbam ar nespecifiskiem tipiem.

Saskaņā ar Apple Swift dokumentāciju,

  • Jebkurš var pārstāvēt jebkura veida instanci, ieskaitot funkciju tipus un izvēles tipus.
  • AnyObject var attēlot jebkura veida klases gadījumu.

Labi, pietiekami vienkārši - jebkurš tiek izmantots visiem veidiem, AnyObject tiek izmantots klases tipiem, vai ne?

Lai saprastu, kā viņi īsti uzvedas kodā, es nolēmu spēlēties ar viņiem rotaļu laukumā.

Jebkurš piemērs

Ikviens ļāva man strādāt ar dažādu tipu sajaukumu, ieskaitot funkciju un ārpusklases tipus, piemēram, Int, String un Bool. Saskaņā ar dokumentāciju, šajā masīvā ir elementi, kas ir vērtību tipi, tāpēc teorētiski AnyObject šādos gadījumos nevajadzētu darboties.

Lai to pārbaudītu, es, izmantojot AnyObject, mēģināju iekļaut virknes un ints, kas ir vērtību tipi Swift.

AnyObjectArray kļūda, iekļaujot striju veidus

Kā gaidīts, kompilators man iemeta kļūdu, sakot, ka masīvā elementi neatbilst tipam AnyObject. Gotcha!

Pēc tam notika šī dīvainā lieta, kad es mēģināju ievērot kompilatora ieteikumus:

Elementi, kas nodoti AnyObject

Kas tikko notika?! Kā es varēju izmantot AnyObject uz iespiedumiem un virknēm, skaidri norādot katru elementu uz AnyObject?

Pēc tam anyObjectArray iespiedu konsolē.

AnyObjectArray drukāšana

Elements Hi acīmredzami man izskatījās pēc stīgas, bet tam nebija tādu pēdiņu kā normālai stīgas vērtībai Swift!

Tālāk es katru elementu izdrukāju, izmantojot iespraužamo cilpu, lai pārbaudītu tā faktisko veidu, nevis AnyObject izlietoto veidu.

Pirmkārt, es izmantoju operatoru, lai redzētu, vai elementi ir Swift Struct tipi vai nē.

JebkuraObjectArray elementu veidu pārbaude

Tas ir stīgu tips! Tad kā to var nodot AnyObject? Atkal stīgas Swift ir šķipsnas, nevis šķiras. Tādējādi teorētiski man nevajadzētu būt iespējai tos parādīt kā AnyObject.

Kas?

Es biju pilnībā apjukusi un nolēmu ar to vēl dažus eksperimentus veikt. Šoreiz es izmantoju NSNumber un NSString, kas ir Objective-C tipi, lai pārbaudītu katra elementa veidu.

Elementu veidu pārbaude jebkurā 2ObjectArray

Pagaidiet, čau ir arī NSString un skaitliskie elementi ir NSNumber! Un… tie ir atsauces veidi Objective-C! Vai tas bija iemesls, kāpēc Hi nebija konsoles citātus par to? Es uzrakstīju vēl dažus kodus, kā norādīts zemāk, lai redzētu, vai mans pieņēmums ir pareizs.

NSString masīva un virkņu masīva drukāšanaSveiki, jo konsoles kontā nav NSString neviena citāta

Apstiprināts! Elementi, kas masīvā ir nodoti AnyObject, tagad ir Objective-C klases tipi: NSString un NSNumber.

Tātad… Kas īsti notiek zem pārsega? Es turpināju iedziļināties šajā tēmā un atradu visticamāko atbildi no dokumenta, izmantojot Swift ar kakao un Objective-C (Swift 3.0.1).

Kā daļu no savietojamības ar Objective-C, Swift piedāvā ērtus un efektīvus veidus, kā strādāt ar kakao ietvariem. Swift automātiski pārvērš dažus Objective-C tipus Swift tipos, un dažus Swift tipus Objective-C tipos. Tipus, kurus var pārveidot starp Objective-C un Swift, sauc par apvienotajiem tipiem.
Jebkurā vietā, kur varat izmantot objektīva-C atsauces tipu, tā vietā varat izmantot vērtības tipu Swift. Tas ļauj izmantot atsauces veida ieviešanā pieejamo funkcionalitāti dabiskā veidā Swift kodā. Šī iemesla dēļ gandrīz nekad nevajadzēs izmantot saīsinātu atsauces veidu tieši savā kodā. Faktiski, kad Swift kods importē Objective-C API, importētājs Objective-C atsauces tipus aizstāj ar tiem atbilstošajiem vērtību tipiem. Tāpat, kad Objective-C kods importē Swift API, importētājs arī aizvieto Swift vērtību tipus ar atbilstošajiem Objective-C atsauces tipiem. ”

Citiem vārdiem sakot, kompilators dara visu iespējamo, lai elastīgi rīkotos ar šādiem veidiem, izmantojot automātisku konvertēšanu un savienošanu, vienlaikus novēršot mūsu lietotnes vieglu avāriju. Lieliski!

Tad kad mēs faktiski izmantojam AnyObject? Kā teikts Apple dokumentācijā, AnyObject var izmantot darbam ar objektiem, kas izriet no klases, bet kuriem nav kopīgas sakņu klases.

Bet vai tas ir absolūti nepieciešams to izmantot mūsu kodā?

Mana atbilde uz šo jautājumu ir: Nē.

Apple saka:

Programmā Swift 3 id tips Objective-C tagad sakrīt ar jebkuru tipu Swift, kas apraksta jebkura veida vērtību, neatkarīgi no tā, vai tā ir klase, enum, struktūra vai kāds cits Swift tips. Šīs izmaiņas padara Objective-C API elastīgākas Swift, jo Swift noteiktos vērtību tipus var nodot Objective-C API un iegūt kā Swift tipus, novēršot nepieciešamību pēc manuāliem “lodziņu” tipiem.
Šīs priekšrocības attiecas arī uz kolekcijām: Objective-C kolekciju tipi NSArray, NSD Dictionary un NSSet, kas iepriekš pieņēma tikai AnyObject elementus, tagad var turēt jebkura veida elementus. Saliktiem konteineriem, piemēram, vārdnīcai un kopai, ir jauns tips AnyHashable, kas var turēt jebkura veida vērtību, kas atbilst protokolam Swift Hashable.

Šķiet, ka jebkurš cits darbojas lieliski, savienojot šīs divas valodas ar Swift 3, bez vajadzības izmantot AnyObject!

Kāds bija galīgais iemesls šīm izmaiņām?

Pēc viņu pašu vārdiem, Apple skaidro:

Swift 3 saskarnes ar Objective-C API ir jaudīgākas nekā iepriekšējās versijas. Piemēram, Swift 2 objekta-C ID tipu pielīdzināja AnyObject tipam Swift, kurā parasti var būt tikai klases tipu vērtības. Ērtības labad Swift 2 sniedza arī netiešus konvertējumus uz AnyObject, piemēram, virknes, masīvs, vārdnīca, komplekts un daži skaitļi, lai vietējos Swift tipus varētu viegli izmantot ar kakao API, kas sagaida NSString, NSArray, vai citas konteinera klases no fonda. Šie konvertējumi nebija pretrunā ar pārējo valodu, padarot grūti saprast, ko tieši var izmantot kā AnyObject, kā rezultātā radās kļūdas.

Varētu uzstāt, ka mums, iOS izstrādātājiem, vienmēr jābūt pēc iespējas konkrētākiem attiecībā uz tipu izmantošanu kodā.

Patiešām, Apple iesaka:

Izmantojiet Any un AnyObject tikai tad, ja jums skaidri nepieciešama to sniegtā uzvedība un iespējas. Vienmēr ir labāk precīzi norādīt veidus, ar kuriem jūs domājat strādāt.

Padomājiet par šo scenāriju: mēs strādājam ar numuru 12,5 Swift. Šajā gadījumā mēs īpaši norādām, ka tas ir dubultā vai pludiņa tips, nevis paziņojam, ka tā ir jebkura. Tādā veidā mēs varam ērti piekļūt dažādiem īpašumiem vai metodēm, kas ir pieejamas konkrētajam tipam. Šajā kontekstā klases tipiem mēs izmantotu AnyObject, jo tie ir nedaudz specifiskāki nekā Any. Bet atkal - AnyObject izmantošana ir tikai iespēja.

Es ceru, ka šis emuāra ziņojums daudziem no jums palīdzēja satriecošajos izstrādātājos noskaidrot Any un AnyObject. Izmantojiet jebkuru pārliecinoši Swift 3, strādājot ar Objective-C atbalstītām API.

Paldies par lasīšanu un laimīgo kodēšanu!