Получение описания типа NSObject

Если вы запустите следующее в Playgroup

class Test {
  var description:String {
    return "This is Test"
  }
}

class Test1:NSObject {
  override var description:String {
    return "This is Test"
  }
}

let t = Test()
println(t)
let t1 = Test1()
println(t1)

вы видите, что первый println выводит некоторую рекламу отладчика, а второй повторяет содержимое description.

Итак: есть ли способ, которым «нормальные» классы будут обрабатываться так же, как подклассы NSObject, поэтому println будет уважать содержимое свойства description?


person qwerty_so    schedule 18.02.2015    source источник


Ответы (2)


Из документации API println():

/// Writes the textual representation of `object` and a newline character into
/// the standard output.
///
/// The textual representation is obtained from the `object` using its protocol
/// conformances, in the following order of preference: `Streamable`,
/// `Printable`, `DebugPrintable`.
///
/// Do not overload this function for your type.  Instead, adopt one of the
/// protocols mentioned above.
func println<T>(object: T)

Таким образом, чтобы получить пользовательское представление println(), ваш класс должен (например) явно принять протокол Printable:

class Test : Printable {
    var description:String {
        return "This is Test"
    }
}

Однако это не работает на игровой площадке Xcode 6.1.1. Это было исправлено в бета-версии Xcode 6.3. Из примечаний к выпуску:

• Добавление соответствий в игровую площадку теперь работает как положено, ...

Я не смог найти это в заголовках API, но кажется, что NSObject (и его подклассы) уже известны как соответствующие Printable. Поэтому пользовательское описание работает для вашего класса Test1.


В Swift 2 (Xcode 7) протокол Printable был переименован в CustomStringConvertible:

class Test : CustomStringConvertible {
    public var description:String {
        return "This is Test"
    }
}

let t = Test()
print(t)
// This is Test
person Martin R    schedule 18.02.2015
comment
Вы просто все знаете :-) - person qwerty_so; 18.02.2015
comment
В Swift 2.0 «Printable» был переименован в «CustomStringConvertible». - person leizh00701; 06.01.2016
comment
Также в Swift 3.0 (возможно, и раньше) описание должно быть общедоступным. - person Warpzit; 16.11.2016
comment
@Warpzit: это необходимо, если сам класс объявлен общедоступным (например, в фреймворке), а не в том случае, если класс определен локально (например, в приложении). Но добавление модификатора public в любом случае не повредит, поэтому я добавил его, чтобы избежать путаницы. Спасибо за ответ! - person Martin R; 16.11.2016

Это потому, что вы распечатываете экземпляр класса. В Swift класс не является подклассом по умолчанию для NSObject . Чтобы сделать класс подклассом NSObject, вы должны указать его так же, как вы сделали для второго класса. Вот измененный код:

class Test {
  var description:String {
    return "This is Test"
  }
}

class Test1:NSObject {
  override var description:String {
    return "This is Test"
  }
}

let t = Test()
println(t.description)
let t1 = Test1()
println(t1)

Вот цитата из языка программирования Swift. ,

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

person Dhruv Ramani    schedule 18.02.2015
comment
Я знаю, что могу использовать t.desciption. Но как NSObject управляет тем, что print берет свое свойство description, а не берет его из обычных классов? Я предполагаю, что это какая-то скрытая ерунда, которую Apple делает под капотом. - person qwerty_so; 18.02.2015
comment
- Только что увидел ответ Мартина. В любом случае, я проголосую за ваши усилия :-) - person qwerty_so; 18.02.2015
comment
Хорошо. Возможно, я неправильно понял вопрос. Я думал, что вы хотите знать самый простой способ избежать ошибки. В любом случае, удачи :) - person Dhruv Ramani; 18.02.2015