Багато програмістів при написанні коду використовують тип Any, наприклад при обробці JSON даних. Але також є і другий тип - AnyObject. Яка ж різниця між цими двома типами?
Згідно з документацією Apple:
- Any - може представляти екземпляр будь-якого типу
- AnyObject - може представляти екземпляр будь-якого класу
Якщо сказати трохи простіше, то:
- Any використовується для всіх типів
- AnyObject - використовується для типів Class
Перевіримо на ділі ці два типи. Почнемо з типу Any
Для цього створимо масив з типом Any
let anyArray: [Any] = [ "Macbook" , 1 , 2 ]
print (anyArray)
Console: [ "Macbook" , 1 , 2 ]
Як ми бачимо, Any дозволяє працювати з різними типами даних одночасно (String, Int).
Згідно з документацією, елементи ( String і Int ) в цьому масиві є структури, які є типами значень, тому, теоретично, AnyObject не повинен працювати.
Щоб перевірити це, створимо ідентичний масив, з типом AnyObject.
let anyObjectArray: [AnyObject] = [ "Macbook" , 1 , 2 ]
Як і очікувалося, компілятор видає нам помилку про неможливість перетворення типу «String / Int» до типу AnyObject
Can not convert value of type «Int» to expected element type «AnyObject»
Can not convert value of type «Int» to expected element type «AnyObject»
Can not convert value of type "String" to expected element type "AnyObject"
Але давайте все таки спробуємо привести три наших типи до AnyObject.
let anyObjectArray: [ AnyObject ] = [ "Macbook" as AnyObject , 1 as AnyObject , 2 as AnyObject ]
print (anyObjectArray)
Console : [ Macbook , 1 , 2 ]
Помилка компілятора зникла. Як ми бачимо, рядок Macbook явно виглядає як рядок, але не має звичних лапок як у типу String в Swift.
Спробуємо розпакувати масив за допомогою циклу, щоб перевірити їх фактичний тип.
for item in anyObjectArray {
if item is String {
print ( "\ (item) є типом String" )} else if item is Int {
print ( "\ (item) є типом Int" )}}
Console :
Macbook є типом String
1 є типом Int
2 є типом Int
Рядок має тип String. Як було сказано раніше, рядки в Swift є структурами, а не типами класів. Значить, ми не повинні мати можливість використовувати їх як AnyObject .
Проведемо ще пару експериментів з нашим масивом. Спробуємо перевірити їх на типи з Objective-C: NSString і NSNumber .
for item in anyObjectArray {
if item is NSString {print ( "\ (item) є типом NSString" )} else if item is NSNumber {print ( "\ (item) є типом NSNumber" )}} Console: Macbook є типом NSString
1 є типом NSNumber
2 є типом NSNumber
Рядок є NSString, а числовий елемент є NSNumber. І обидва цих типу є ссилочні в Objective-C.
Так чому так відбувається?
Як частину своєї сумісності з Objective-C, Swift пропонує зручні та ефективні способи роботи з платформами Cocoa.
Swift автоматично перетворює деякі типи Objective-C в типи Swift, а деякі типи Swift в типи Objective-C. Типи, які можна конвертувати між Objective-C і Swift, називаються з'єднаними.
Іншими словами, компілятор робить все можливе, щоб бути гнучким в обробці таких типів за допомогою автоматичного перетворення і створення «мостів», в той же час запобігаючи збою програми.
Коли ж використовувати AnyObject?
Як говориться в документації Apple, AnyObject може бути використаний для роботи з об'єктами, які є похідними від Class, але не мають спільного кореневого класу.
В Swift 3 тип id в Objective-C тепер відображається на тип Any в Swift, який описує значення будь-якого типу, будь то клас, перерахування, структура або будь-який інший тип Swift. Ця зміна робить API-інтерфейси Objective-C більш гнучкими в Swift.
Таким чином, AnyObject бажано використовувати коли ви хочете обмежити протокол, щоб його можна було використовувати лише з класами, а Any в інших випадках.
0 комментариев
Добавить комментарий