Что такое Swift-эквивалент - [описание NSObject]?
В Objective-C к их классу можно добавить метод description
, чтобы помочь в отладке:
@implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p, foo = %@>", [self class], foo _foo];
}
@end
Затем в отладчике вы можете сделать:
po fooClass
<MyClass: 0x12938004, foo = "bar">
Что такое эквивалент в Swift? Может оказаться полезным выход Swift REPL:
1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}
Но я хотел бы переопределить это поведение для печати на консоли:
4> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
Есть ли способ очистить этот вывод println
? Я видел протокол Printable
:
/// This protocol should be adopted by types that wish to customize their
/// textual representation. This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
var description: String { get }
}
Я решил, что это будет автоматически "видно" на println
, но это не так:
1> class MyClass: Printable {
2. let foo = 42
3. var description: String { get { return "MyClass, foo = \(foo)" } }
4. }
5>
6> let x = MyClass()
x: MyClass = {
foo = 42
}
7> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
И вместо этого я должен явно вызвать описание:
8> println("x = \(x.description)")
x = MyClass, foo = 42
Есть ли лучший способ?
Ответы
Ответ 1
В ходе некоторых экспериментов я обнаружил, что протоколы Printable
и DebugPrintable
работают при компиляции реального приложения, но не в REPL или Playground.
Боковое примечание. Код, который вы написали, верен, но в этом случае вы, вероятно, ищете DebugPrintable
Swift переименовал эти протоколы как CustomStringConvertible
и CustomDebugStringConvertible
- хотя компилятор в настоящее время помогает вам сделать это:)
Ответ 2
Пример использования протоколов CustomStringConvertible
и CustomDebugStringConvertible
в Swift:
PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
var pageIndex : Int = 0
override var description : String {
return "**** PageContentViewController\npageIndex equals \(pageIndex) ****\n"
}
override var debugDescription : String {
return "---- PageContentViewController\npageIndex equals \(pageIndex) ----\n"
}
...
}
ViewController.swift
import UIKit
class ViewController: UIViewController
{
/*
Called after the controller view is loaded into memory.
*/
override func viewDidLoad() {
super.viewDidLoad()
let myPageContentViewController = self.storyboard!.instantiateViewControllerWithIdentifier("A") as! PageContentViewController
print(myPageContentViewController)
print(myPageContentViewController.description)
print(myPageContentViewController.debugDescription)
}
...
}
Распечатка:
**** PageContentViewController
pageIndex equals 0 ****
**** PageContentViewController
pageIndex equals 0 ****
---- PageContentViewController
pageIndex equals 0 ----
Примечание:, если у вас есть собственный класс, который не наследуется ни от одного класса, включенного в библиотеки UIKit или Foundation, а затем наследует его класса NSObject
или сделать его совместимым с протоколами CustomStringConvertible
и CustomDebugStringConvertible
.
Ответ 3
Просто используйте CustomStringConvertible
и var description: String { return "Some string" }
работает в Xcode 7.0 betap >
class MyClass: CustomStringConvertible {
var string: String?
var description: String {
//return "MyClass \(string)"
return "\(self.dynamicType)"
}
}
var myClass = MyClass() // this line outputs MyClass nil
// and of course
print("\(myClass)")
// Use this newer versions of Xcode
var description: String {
//return "MyClass \(string)"
return "\(type(of: self))"
}
Ответ 4
Ответы, относящиеся к CustomStringConvertible
, - это путь. Лично, чтобы определение класса (или структуры) было как можно более чистым, я также выделил бы код описания в отдельное расширение:
class foo {
// Just the basic foo class stuff.
var bar = "Humbug!"
}
extension foo: CustomStringConvertible {
var description: String {
return bar
}
}
let xmas = foo()
print(xmas) // Prints "Humbug!"
Ответ 5
class SomeBaseClass: CustomStringConvertible {
//private var string: String = "SomeBaseClass"
var description: String {
return "\(self.dynamicType)"
}
// Use this in newer versions of Xcode
var description: String {
return "\(type(of: self))"
}
}
class SomeSubClass: SomeBaseClass {
// If needed one can override description here
}
var mySomeBaseClass = SomeBaseClass()
// Outputs SomeBaseClass
var mySomeSubClass = SomeSubClass()
// Outputs SomeSubClass
var myOtherBaseClass = SomeSubClass()
// Outputs SomeSubClass
Ответ 6
struct WorldPeace: CustomStringConvertible {
let yearStart: Int
let yearStop: Int
var description: String {
return "\(yearStart)-\(yearStop)"
}
}
let wp = WorldPeace(yearStart: 2020, yearStop: 2040)
print("world peace: \(wp)")
// outputs:
// world peace: 2020-2040