Làm cách nào để in loại hoặc lớp của một biến trong Swift?


335

Có cách nào để in kiểu thời gian chạy của biến trong swift không? Ví dụ:

var now = NSDate()
var soon = now.dateByAddingTimeInterval(5.0)

println("\(now.dynamicType)") 
// Prints "(Metatype)"

println("\(now.dynamicType.description()")
// Prints "__NSDate" since objective-c Class objects have a "description" selector

println("\(soon.dynamicType.description()")
// Compile-time error since ImplicitlyUnwrappedOptional<NSDate> has no "description" method

Trong ví dụ trên, tôi đang tìm cách để chỉ ra rằng biến "sớm" là loại ImplicitlyUnwrappedOptional<NSDate>, hoặc ít nhất NSDate!.


43
@JasonMArcher Hãy cho tôi biết đây là bản sao như thế nào nếu câu hỏi bạn liên kết được hỏi 4 ngày sau câu hỏi này?
akashivskyy

Có một số câu hỏi về việc kiểm tra loại đối tượng Swift hoặc đọc loại đối tượng Swift. Chúng tôi chỉ tìm những câu hỏi hay nhất để sử dụng làm câu hỏi "chính" cho chủ đề này. Các bản sao được đề xuất có một câu trả lời kỹ lưỡng hơn nhiều. Điều này không có nghĩa là bạn đã làm gì đó sai, chỉ là chúng tôi đang cố gắng giảm sự lộn xộn.
JasonMArcher

4
Bản sao được đề xuất không trả lời cùng một câu hỏi; Type.elf không thể được in ra bàn điều khiển cho mục đích gỡ lỗi, nó có nghĩa là được sử dụng để chuyển đến các chức năng khác lấy Kiểu làm đối tượng.
Matt Bridges

2
OT: Rất kỳ lạ khi Swift không cung cấp điều đó ra khỏi hộp và người ta cần phải tìm hiểu thêm về các thư viện C cấp thấp như vậy. Đáng báo cáo lỗi?
qwerty_so

Các bạn, tôi đã cung cấp câu trả lời của tôi dưới đây. Xin vui lòng xem và cho tôi biết nếu đó là những gì được mong đợi.
DILIP KOSURI

Câu trả lời:


377

Cập nhật tháng 9 năm 2016

Swift 3.0: Sử dụng type(of:), ví dụ type(of: someThing)(vì dynamicTypetừ khóa đã bị xóa)

Cập nhật tháng 10 năm 2015 :

Tôi đã cập nhật các ví dụ bên dưới thành cú pháp Swift 2.0 mới (ví dụ: printlnđã được thay thế bằng print, toString()bây giờ String()).

Từ ghi chú phát hành Xcode 6.3 :

@nschum chỉ ra trong các nhận xét rằng ghi chú phát hành Xcode 6.3 cho thấy một cách khác:

Nhập các giá trị bây giờ in dưới dạng tên loại được sắp xếp đầy đủ khi được sử dụng với phép nội suy println hoặc chuỗi.

import Foundation

class PureSwiftClass { }

var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"

print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")

print( "String(Int.self)           -> \(Int.self)")
print( "String((Int?).self         -> \((Int?).self)")
print( "String(NSString.self)      -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")

Đầu ra nào:

String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self)           -> Int
String((Int?).self         -> Optional<Int>
String(NSString.self)      -> NSString
String(Array<String>.self) -> Array<String>

Cập nhật cho Xcode 6.3:

Bạn có thể sử dụng _stdlib_getDemangledTypeName():

print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")

và lấy điều này làm đầu ra:

TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String

Câu trả lời gốc:

Trước Xcode 6.3 _stdlib_getTypeNamecó tên loại được đọc sai của một biến. Mục blog của Ewan Swick giúp giải mã các chuỗi này:

ví dụ: _TtSiviết tắt của Intkiểu nội bộ của Swift .

Mike Ash có một mục blog tuyệt vời bao gồm cùng một chủ đề .


2
Làm thế nào bạn tìm thấy _stdlib_getTypeName()? REPL tích hợp không còn tồn tại, swift-ide-testcũng không tồn tại và in mã của các mô-đun Swift trong các _giá trị được tinh chỉnh.
Lily Ballard

10
Có vẻ như tôi có thể tìm kiếm các biểu tượng với lldbđủ dễ dàng trong thay thế. Cũng có _stdlib_getDemangledTypeName(), và _stdlib_demangleName().
Lily Ballard

1
Ôi gọn gàng, tôi không nhận ra đó imagelà lối tắt cho target modules. Tôi đã kết thúc bằng cách sử dụng target modules lookup -r -n _stdlib_, tất nhiên được thể hiện tốt hơn nhưimage lookup -r -n _stdlib_ libswiftCore.dylib
Lily Ballard

1
FYI - Có vẻ như toString (...) đã được thay thế bằng String (...).
Nick

6
Swift 3.0: dynamicTypeTừ khóa đã bị xóa khỏi Swift. Thay vào đó, một chức năng nguyên thủy mới type(of:)đã được thêm vào ngôn ngữ: github.com/apple/swift/blob/master/CHANGELOG.md
Szu

46

Chỉnh sửa: Một toStringchức năng mới đã được giới thiệu trong Swift 1.2 (Xcode 6.3) .

Bây giờ bạn có thể in loại đã gỡ rối của bất kỳ loại nào bằng cách sử dụng .selfvà bất kỳ trường hợp nào bằng cách sử dụng .dynamicType:

struct Box<T> {}

toString("foo".dynamicType)            // Swift.String
toString([1, 23, 456].dynamicType)     // Swift.Array<Swift.Int>
toString((7 as NSNumber).dynamicType)  // __NSCFNumber

toString((Bool?).self)                 // Swift.Optional<Swift.Bool>
toString(Box<SinkOf<Character>>.self)  // __lldb_expr_1.Box<Swift.SinkOf<Swift.Character>>
toString(NSStream.self)                // NSStream

Hãy thử gọi YourClass.selfyourObject.dynamicType.

Tham khảo: https://devforums.apple.com/thread/227425 .


2
Tôi đã trả lời chủ đề đó, nhưng tôi sẽ thêm nhận xét của mình ở đây. Các giá trị đó thuộc loại "Metatype", nhưng dường như không phải là một cách dễ dàng để tìm ra loại đối tượng Metatype đại diện cho loại nào, đó là thứ tôi đang tìm kiếm.
Matt Bridges

Chúng thuộc loại Metatype, và chúng là các lớp. Họ đại diện cho một lớp. Không chắc chắn chính xác vấn đề của bạn là gì với điều đó. someInstance.dynamicType.printClassName()sẽ in tên của lớp.
Tệp tương tự

18
phương thức printClassName () chỉ là một phương thức ví dụ mà họ đã tạo trong một trong các mẫu trong tài liệu, nó không phải là lệnh gọi API mà bạn có thể truy cập.
Dave Wood

4
FYI - Có vẻ như toString (...) đã được thay thế bằng String (...)
Nick

33

Swift 3.0

let string = "Hello"
let stringArray = ["one", "two"]
let dictionary = ["key": 2]

print(type(of: string)) // "String"

// Get type name as a string
String(describing: type(of: string)) // "String"
String(describing: type(of: stringArray)) // "Array<String>"
String(describing: type(of: dictionary)) // "Dictionary<String, Int>"

// Get full type as a string
String(reflecting: type(of: string)) // "Swift.String"
String(reflecting: type(of: stringArray)) // "Swift.Array<Swift.String>"
String(reflecting: type(of: dictionary)) // "Swift.Dictionary<Swift.String, Swift.Int>"

1
Việc triển khai Swift 2 đặc biệt tốt với các trường hợp enum. Có ai biết liệu hành vi này được Apple ghi nhận / bảo đảm không? Thư viện tiêu chuẩn chỉ bao gồm một nhận xét rằng điều này phù hợp để gỡ lỗi ...
milos

30

Đây có phải là những gì bạn đang tìm kiếm?

println("\(object_getClassName(now))");

Nó in "__NSDate"

CẬP NHẬT : Xin lưu ý rằng điều này dường như không còn hoạt động kể từ Beta05


2
Không làm việc cho các lớp nhanh chóng. Trả về "UnsafePulum (0x7FBB18D06DE0)"
aryaxt

4
Không hoạt động cho các lớp ObjC (ít nhất là trong Beta5), đối với NSManagedObject, tôi chỉ nhận được "Buildin.RawPulum = address"
Kendall Helmstetter Gelner

23

Xcode hiện tại của tôi là Phiên bản 6.0 (6A280e).

import Foundation

class Person { var name: String; init(name: String) { self.name = name }}
class Patient: Person {}
class Doctor: Person {}

var variables:[Any] = [
    5,
    7.5,
    true,
    "maple",
    Person(name:"Sarah"),
    Patient(name:"Pat"),
    Doctor(name:"Sandy")
]

for variable in variables {
    let typeLongName = _stdlib_getDemangledTypeName(variable)
    let tokens = split(typeLongName, { $0 == "." })
    if let typeName = tokens.last {
        println("Variable \(variable) is of Type \(typeName).")
    }
}

Đầu ra:

Variable 5 is of Type Int.
Variable 7.5 is of Type Double.
Variable true is of Type Bool.
Variable maple is of Type String.
Variable Swift001.Person is of Type Person.
Variable Swift001.Patient is of Type Patient.
Variable Swift001.Doctor is of Type Doctor.

1
Tốt, nhưng câu hỏi cũng bao gồm Tùy chọn, đầu ra của các tùy chọn được đặt Optional(...), vì vậy mã của bạn sẽ chỉ trả về Optionallà Loại. Nó cũng sẽ hiển thị var optionalTestVar: Person? = Person(name:"Sarah")dưới dạng Tùy chọn (Người) và var với Người! như ImplicitlyUnwrappingOptional (Person)
Binary

18

Kể từ Xcode 6.3 với Swift 1.2, bạn chỉ cần chuyển đổi các giá trị loại thành bản đầy đủ String.

toString(Int)                   // "Swift.Int"
toString(Int.Type)              // "Swift.Int.Type"
toString((10).dynamicType)      // "Swift.Int"
println(Bool.self)              // "Swift.Bool"
println([UTF8].self)            // "Swift.Array<Swift.UTF8>"
println((Int, String).self)     // "(Swift.Int, Swift.String)"
println((String?()).dynamicType)// "Swift.Optional<Swift.String>"
println(NSDate)                 // "NSDate"
println(NSDate.Type)            // "NSDate.Type"
println(WKWebView)              // "WKWebView"
toString(MyClass)               // "[Module Name].MyClass"
toString(MyClass().dynamicType) // "[Module Name].MyClass"

Là hướng khác có thể trong 1,2? Để khởi tạo một thể hiện dựa trên tên lớp?
dùng965972

@ user965972 Theo như tôi biết tôi không nghĩ là có.
trốn

17

Bạn vẫn có thể truy cập lớp, thông qua className(trả về a String).

Thực tế, có một số cách để có được lớp, ví dụ classForArchiver, classForCoder, classForKeyedArchiver(tất cả trở lại AnyClass!).

Bạn không thể có được kiểu người nguyên thủy (người nguyên thủy không phải là một lớp).

Thí dụ:

var ivar = [:]
ivar.className // __NSDictionaryI

var i = 1
i.className // error: 'Int' does not have a member named 'className'

Nếu bạn muốn có được kiểu nguyên thủy, bạn phải sử dụng bridgeToObjectiveC(). Thí dụ:

var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber

Tôi cá rằng đó là một người nguyên thủy. Thật không may, bạn không thể có được kiểu nguyên thủy.
Leandros

Những ví dụ đó dường như không hoạt động trong sân chơi. Tôi nhận được lỗi cho người nguyên thủy và không nguyên thủy như nhau.
Matt Bridges

cố gắng import Cocoa.
Leandros

9
className dường như chỉ khả dụng cho NSObjects khi phát triển cho OSX; nó không có sẵn trong SDK iOS cho các đối tượng NSObjects hoặc "bình thường"
Matt Bridges

3
classNamelà một phần của hỗ trợ AppleScript của Cốc Cốc và chắc chắn không nên được sử dụng cho hướng nội. Rõ ràng là nó không có sẵn trên iOS.
Nikolai Ruhe

16

Bạn có thể sử dụng phản ánh để có được thông tin về đối tượng.
Ví dụ tên của lớp đối tượng:

var classname = phản ánh (ngay bây giờ) .summary

Trong bản Beta 6, điều này đã cho tôi tên ứng dụng + tên lớp ở dạng hơi bị xáo trộn, nhưng đó là một sự khởi đầu. +1 cho reflect(x).summary- cảm ơn!
Olie

không hoạt động, in một dòng trống trong Swift 1.2 Xcode 6.4 và iOs 8.4
Juan Boero

13

Tôi đã may mắn với:

let className = NSStringFromClass(obj.dynamicType)

@hdost anh chàng không có gì làm việc nhưng classForCoder đã làm việc.
Sediteshwaran

12

Loại sử dụng Xcode 8 Swift 3.0 (của :)

let className = "\(type(of: instance))"

10

Trong Xcode 8, Swift 3.0

Các bước:

1. Lấy Loại:

Lựa chọn 1:

let type : Type = MyClass.self  //Determines Type from Class

Lựa chọn 2:

let type : Type = type(of:self) //Determines Type from self

2. Chuyển đổi Loại thành Chuỗi:

let string : String = "\(type)" //String

8

Trong Swift 3.0, bạn có thể sử dụng type(of:), vì dynamicTypetừ khóa đã bị xóa.


7

Chuyển 5

Với bản phát hành mới nhất của Swift 3, chúng ta có thể nhận được những mô tả khá hay về tên loại thông qua trình Stringkhởi tạo. Giống như, ví dụ print(String(describing: type(of: object))). Trường hợp object có thể là một biến đối tượng như mảng, từ điển, an Int, a NSDate, thể hiện của một lớp tùy chỉnh, v.v.

Đây là câu trả lời hoàn chỉnh của tôi: Lấy tên lớp của đối tượng dưới dạng chuỗi trong Swift

Câu hỏi đó đang tìm cách lấy tên lớp của một đối tượng dưới dạng chuỗi, nhưng tôi cũng đề xuất một cách khác để lấy tên lớp của một biến không phải là lớp con của NSObject. Đây là:

class Utility{
    class func classNameAsString(obj: Any) -> String {
        //prints more readable results for dictionaries, arrays, Int, etc
        return String(describing: type(of: obj))
    }
}

Tôi đã tạo một hàm tĩnh lấy tham số là một đối tượng kiểu Anyvà trả về tên lớp của nó là String:).

Tôi đã thử nghiệm chức năng này với một số biến như:

    let diccionary: [String: CGFloat] = [:]
    let array: [Int] = []
    let numInt = 9
    let numFloat: CGFloat = 3.0
    let numDouble: Double = 1.0
    let classOne = ClassOne()
    let classTwo: ClassTwo? = ClassTwo()
    let now = NSDate()
    let lbl = UILabel()

và đầu ra là:

  • diccionary là loại từ điển
  • mảng là kiểu Array
  • numInt thuộc loại Int
  • numFloat thuộc loại CGFloat
  • numDouble thuộc loại Double
  • classOne có loại: ClassOne
  • classTwo có loại: ClassTwo
  • bây giờ là loại: Ngày
  • lbl là loại: UILabel

5

Khi sử dụng Ca cao (không phải là Cốc Cốc), bạn có thể sử dụng thuộc classNametính cho các đối tượng là các lớp con của NSObject.

println(now.className)

Thuộc tính này không có sẵn cho các đối tượng Swift bình thường, không phải là các lớp con của NSObject (và trên thực tế, không có id gốc hoặc loại đối tượng trong Swift).

class Person {
    var name: String?
}

var p = Person()
println(person.className) // <- Compiler error

Trong CocoaTouch, tại thời điểm này không có cách nào để có được một mô tả chuỗi về loại biến đã cho. Chức năng tương tự cũng không tồn tại đối với các loại nguyên thủy trong cả Ca cao hoặc Ca cao.

Swift REPL có thể in ra một bản tóm tắt các giá trị bao gồm loại của nó, vì vậy có thể cách thức hướng nội này có thể thông qua API trong tương lai.

EDIT : dump(object)dường như để thực hiện các mẹo.


Ngay cả khi Xcode 10 và Swift 4.2, dump(object)thực sự mạnh mẽ. Cảm ơn bạn.
Alex Zavatone

5

Câu trả lời hàng đầu không có ví dụ hoạt động về cách thức mới để làm điều này bằng cách sử dụng type(of:. Vì vậy, để giúp những tân binh như tôi, đây là một ví dụ hoạt động, được lấy chủ yếu từ các tài liệu của Apple tại đây - https://developer.apple.com/documentation/swift/2885064-type

doubleNum = 30.1

func printInfo(_ value: Any) {
    let varType = type(of: value)
    print("'\(value)' of type '\(varType)'")
}

printInfo(doubleNum)
//'30.1' of type 'Double'

4

Tôi đã thử một số câu trả lời khác ở đây nhưng dường như rất rõ đối tượng thuộc hạ là gì.

Tuy nhiên tôi đã tìm thấy một cách bạn có thể lấy tên lớp Object-C cho một đối tượng bằng cách làm như sau:

now?.superclass as AnyObject! //replace now with the object you are trying to get the class name for

Đây là và ví dụ về cách bạn sẽ sử dụng nó:

let now = NSDate()
println("what is this = \(now?.superclass as AnyObject!)")

Trong trường hợp này, nó sẽ in NSDate trong bảng điều khiển.


4

Tôi tìm thấy giải pháp này mà hy vọng có thể làm việc cho người khác. Tôi đã tạo một phương thức lớp để truy cập giá trị. Xin lưu ý rằng điều này sẽ chỉ hoạt động cho lớp con NSObject. Nhưng ít nhất là một giải pháp sạch sẽ và gọn gàng.

class var className: String!{
    let classString : String = NSStringFromClass(self.classForCoder())
    return classString.componentsSeparatedByString(".").last;
}

4

Trong XCode 6.3 mới nhất với Swift 1.2, đây là cách duy nhất tôi tìm thấy:

if view.classForCoder.description() == "UISegment" {
    ...
}

LƯU Ý: description () trả về tên lớp theo định dạng <swift module name>.<actual class name>, vì vậy bạn muốn tách chuỗi bằng a .và nhận mã thông báo cuối cùng.
Matthew Quiros

4

Nhiều câu trả lời ở đây không hoạt động với Swift mới nhất (Xcode 7.1.1 tại thời điểm viết).

Cách hiện tại để có được thông tin là tạo ra Mirrorvà thẩm vấn điều đó. Đối với tên lớp, nó đơn giản như:

let mirror = Mirror(reflecting: instanceToInspect)
let classname:String = mirror.description

Thông tin bổ sung về đối tượng cũng có thể được lấy từ Mirror. Xem http://swiftdoc.org/v2.1/type/Mirror/ để biết chi tiết.


Có gì sai với câu trả lời stackoverflow.com/a/25345480/1187415stackoverflow.com/a/32087449/1187415 ? Cả hai dường như hoạt động khá tốt với Swift 2. (Không kiểm tra những cái khác.)
Martin R

Tôi thích điều này như một giải pháp chung, nhưng nhận được "Mirror for ViewContoder" (ngoại lai "Mirror for") - chờ đã, có vẻ như sử dụng ".subjectType" thực hiện thủ thuật!
David H

3

Trong lldb kể từ phiên bản beta 5, bạn có thể thấy lớp của một đối tượng bằng lệnh:

fr v -d r shipDate

mà xuất ra một cái gì đó như:

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

Lệnh được mở rộng có nghĩa là:

Frame Variable(in một biến khung) -d run_target(mở rộng các kiểu động)

Một điều hữu ích cần biết là việc sử dụng "Biến khung" để xuất các giá trị biến đầu ra đảm bảo không có mã nào được thực thi.


3

Tôi đã tìm thấy một giải pháp cho các lớp tự phát triển (hoặc như vậy bạn có quyền truy cập).

Đặt thuộc tính được tính sau trong định nghĩa lớp đối tượng của bạn:

var className: String? {
    return __FILE__.lastPathComponent.stringByDeletingPathExtension
}

Bây giờ bạn có thể chỉ cần gọi tên lớp trên đối tượng của mình như vậy:

myObject.className

Xin lưu ý rằng điều này sẽ chỉ hoạt động nếu định nghĩa lớp của bạn được tạo trong một tệp có tên chính xác như lớp bạn muốn tên.

Vì đây thường là trường hợp câu trả lời ở trên nên làm điều đó cho hầu hết các trường hợp . Nhưng trong một số trường hợp đặc biệt, bạn có thể cần phải tìm ra một giải pháp khác.


Nếu bạn cần tên lớp trong chính lớp (tệp), bạn chỉ cần sử dụng dòng này:

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

Có lẽ phương pháp này giúp một số người ngoài kia.


3

Dựa trên các câu trả lời và nhận xét được đưa ra bởi Klass và Kevin Ballard ở trên, tôi sẽ đi với:

println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!)

println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!)

sẽ in ra:

"NSDate"
"ImplicitlyUnwrappedOptional"
"Optional"
"NSDate"

"NSString"
"PureSwiftClass"
"Int"
"Double"

Tôi nghĩ rằng đây là câu trả lời tốt hơn.
maschall 2/2/2015

Tôi đã kết thúc việc sử dụng trong Swift 1.2 như sau : toString(self.dynamicType).componentsSeparatedByString(".").last!, rõ ràng tôi đang ở trong một bối cảnh đối tượng và có thể tham khảo self.
Joe

3
let i: Int = 20


  func getTypeName(v: Any) -> String {
    let fullName = _stdlib_demangleName(_stdlib_getTypeName(i))
    if let range = fullName.rangeOfString(".") {
        return fullName.substringFromIndex(range.endIndex)
    }
    return fullName
}

println("Var type is \(getTypeName(i)) = \(i)")

3

Phiên bản Swift 4:

print("\(type(of: self)) ,\(#function)")
// within a function of a class

Cảm ơn @Joshua Dance


3

Swift 4:

// "TypeName"
func stringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(describing: some) : String(describing: type(of: some))
    return string
}

// "ModuleName.TypeName"
func fullStringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(reflecting: some) : String(reflecting: type(of: some))
    return string
}

Sử dụng:

print(stringType(of: SomeClass()))     // "SomeClass"
print(stringType(of: SomeClass.self))  // "SomeClass"
print(stringType(of: String()))        // "String"
print(fullStringType(of: String()))    // "Swift.String"

2

Dường như không có cách chung nào để in tên loại của loại giá trị tùy ý. Như những người khác đã lưu ý, cho các trường hợp lớp, bạn có thể invalue.className nhưng đối với các giá trị nguyên thủy thì dường như trong thời gian chạy, thông tin kiểu sẽ không còn nữa.

Chẳng hạn, có vẻ như không có cách nào để gõ: 1.something()và lấy ra Intbất kỳ giá trị nào của something. (Bạn có thể, như một câu trả lời khác được đề xuất, sử dụng i.bridgeToObjectiveC().classNameđể cung cấp cho bạn một gợi ý, nhưng không phải__NSCFNumber thực sự loạii -. Chỉ là những gì nó sẽ được chuyển đổi sang khi nó đi qua ranh giới của một cuộc gọi chức năng Objective-C)

Tôi sẽ rất vui khi được chứng minh là sai, nhưng có vẻ như việc kiểm tra kiểu được thực hiện hoàn toàn vào thời gian biên dịch, và giống như C ++ (với RTTI bị vô hiệu hóa), nhiều thông tin loại đã bị mất trong thời gian chạy.


Bạn có thể đưa ra một ví dụ về việc sử dụng className để in "NSDate" cho biến "now" trong ví dụ của tôi hoạt động trong sân chơi của Xcode6 không? Theo như tôi có thể nói, className không được định nghĩa trên các đối tượng Swift, ngay cả những đối tượng là lớp con của NSObject.
Matt Bridges

Nó xuất hiện 'className' có sẵn cho các đối tượng xuất phát từ NSObject, nhưng chỉ khi phát triển cho mac, không phải cho iOS. Dường như không có cách giải quyết nào cho iOS.
Matt Bridges

1
Vâng, điều thực sự xảy ra ở đây dường như là, trong trường hợp chung, thông tin loại đã bị mất trong thời gian chạy nhanh.
ipmcc

Tuy nhiên, tôi tò mò làm thế nào REPL có thể in các loại giá trị.
Matt Bridges

REPL gần như chắc chắn được giải thích và không được biên dịch, điều này sẽ dễ dàng giải thích nó
ipmcc

2

Đây là cách bạn có được một chuỗi loại của bạn đối tượng hoặc Loại đó là phù hợp và sẽ đưa vào tài khoản mà mô-đun định nghĩa đối tượng thuộc về hoặc lồng trong trình. Trong Swift 4.x.

@inline(__always) func typeString(for _type: Any.Type) -> String {
    return String(reflecting: type(of: _type))
}

@inline(__always) func typeString(for object: Any) -> String {
    return String(reflecting: type(of: type(of: object)))
}

struct Lol {
    struct Kek {}
}

// if you run this in playground the results will be something like
typeString(for: Lol.self)    //    __lldb_expr_74.Lol.Type
typeString(for: Lol())       //    __lldb_expr_74.Lol.Type
typeString(for: Lol.Kek.self)//    __lldb_expr_74.Lol.Kek.Type
typeString(for: Lol.Kek())   //    __lldb_expr_74.Lol.Kek.Type

2

Để có được một loại đối tượng hoặc lớp đối tượng trong Swift , bạn phải sử dụng một loại (của: yourObject)

loại (của: yourObject)


1

Không chính xác những gì bạn đang theo đuổi, nhưng bạn cũng có thể kiểm tra loại biến đối với các loại Swift như vậy:

let object: AnyObject = 1

if object is Int {
}
else if object is String {
}

Ví dụ.


1

Xcode 7.3.1, Swift 2.2:

String(instanceToPrint.self).componentsSeparatedByString(".").last

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.