2014-06-07 3 views
32

Есть ли функция для определения типа переменной в Swift? Я предполагаю, что в Python может быть что-то вроде type().Как определить тип переменной в Swift

Мне нужен способ оценить, является ли переменная объектом Foundation или переменной C в Swift. Как и NSString vs String, или NSArray vs array. Чтобы я мог выходить на консоль и ясно видеть, что это такое.

Например, я хотел бы знать тип, выведенный для первого array ниже:

var array = [1,2,3] // by default NSArray or array? 
var array:[Int] = [1,2,3] 
var array:NSArray = [1,2,3] 
var array:Array<Any> = [1,2,3] 

Я видел ответы для оценки, если данного переменного является своим родом данным типа в this question, но я скажу, что это совсем не то, что я хочу спросить.

+0

Не то, что я не знаю, но вы можете свернуть вниз самостоятельно? –

+0

Я редактировал вопрос, чтобы сделать мой оператор более ясным – piaChai

+0

Не могли бы вы привести пример типа кода, в котором вы хотели бы использовать эти знания? Если тип известен во время компиляции, вы, вероятно, можете использовать общую функцию, например «func show (x: T) {println (" \ (x) имеет тип \ (T) "}'. не известно, как во время компиляции, я не уверен, что это будет возможно, поскольку это не похоже на то, что значение C будет иметь необходимые метаданные времени выполнения. (К сожалению, я не могу попробовать это для себя, потому что Apple все еще не одобрил мою учетную запись разработчика.) –

ответ

23

Вы можете получить ссылку на объект типа значения с помощью свойства .dynamicType. Это эквивалентно функции type() Python и упоминается in the Swift documentation under Language Reference: Types: Metatype Type.

var intArray = [1, 2, 3] 
let typeOfArray = intArray.dynamicType 

С этим объектом типа мы можем создать новый экземпляр того же типа массива.

var newArray = typeOfArray() 
newArray.append(5) 
newArray.append(6) 
println(newArray) 
[5, 6] 

Мы можем видеть, что это новое значение одного и того же типа ([Int]) при попытке добавить поплавок:

newArray.append(1.5) 
error: type 'Int' does not conform to protocol 'FloatLiteralConvertible' 

Если мы импортируем какао и использовать массив мы видим, что создается NSArray:

import Cocoa 

var mixedArray = [1, "2"] 
let mixedArrayType = mixedArray.dynamicType 

var newArray = mixedArrayType() 
var mutableArray = newArray.mutableCopy() as NSMutableArray 

mutableArray.addObject(1) 
mutableArray.addObject(1.5) 
mutableArray.addObject("2") 

println(mutableArray) 

Однако на данный момент не существует общего способа генерации описания строки объекта типа, поэтому это может не служить той ролью отладки, о которой вы просили.

Типы, полученные из NSObject есть метод .description(), как используется in SiLo's answer,

println(mixedArrayType.description()) 
__NSArrayI 

Однако это не присутствует на типах, таких как встроенные массивы Свифта.

println(typeOfArray.description()) 
error: '[Int].Type' does not have a member named 'description' 
+0

BTW: вместо 'obj.description() ', вы всегда можете использовать' String (obj) '(это будет использовать описание, если оно доступно). – Tali

+2

. DynamicType устарел сейчас. typeof эквивалент теперь type (из: myvariable) – logicor

+0

@logicor Спасибо за информацию. Хотите предложить редактировать это сообщение (так что вы получите кредит на добавление)? Если нет, я отредактирую его позже. –

0

Я использую точки останова во время отладки, но если вам нужно проверить, соответствуют ли они определенного типа во время выполнения, то drewag правильно

другая вещь, которую вы можете сделать, это испытание типа данных с утверждением, это будет работать только при отладке, но с утверждением вы можете установить условия, которые, если встретились приложение аварий

может быть что-то вроде assert(let tArray == oldArray as? NSArray[] //if not NSArray app crashes)

+0

Это проверяет _if_ a var имеет тип_специфического типа, а не _what_ type it_is_. Спасибо за ваш вклад. –

10

можно сделать так, хотя это не обязательно, что легко и не полезно:

func getClassName(obj : AnyObject) -> String 
{ 
    let objectClass : AnyClass! = object_getClass(obj) 
    let className = objectClass.description() 

    return className 
} 

let swiftArray = [1, 2, 3] 
let swiftDictionary = ["Name": "John Doe"] 
let cocoaArray : NSArray = [10, 20, 30] 
var mutableCocoaArray = NSMutableArray() 

println(getClassName(swiftArray)) 
println(getClassName(swiftDictionary)) 
println(getClassName(cocoaArray)) 
println(getClassName(mutableCocoaArray)) 

Выход:

_TtCSs22ContiguousArrayStorage00007F88D052EF58 
__NSDictionaryM 
__NSArrayI 
__NSArrayM 

Вы лучше использовать в is и as ключевые слова в Swift. Многие базовые классы используют кластеры класса (как вы можете увидеть __NSArrayI (неизменное) и __NSArrayM (изменяемые).

Обратите внимание на интересное поведение. The swiftArray по умолчанию для использования Swift Array<Int> в то время как swiftDictionary дефолт NSMutableDictionary. С такого рода поведение я бы не полагаться на что-либо быть определенного типа (проверьте первый).

+2

Почему бы просто не использовать object_getClassName? – Brian

20

вариант + щелкните переменную, которую вы хотели бы проверить.

enter image description here

+0

Это не работает в Xcode 9. –

3

Кто-то говорил об этом выше, но я думаю, что он заслуживает обзорность ответа, а не комментарий. Теперь вы можете просто использовать тип (из: ___):

var red, green, blue: Double 
print(type(of: green)) 

дает

Двойной

Смежные вопросы