What is the Swift equivalent of -[NSObject description]?
To implement this on a Swift type you must implement the CustomStringConvertible
protocol and then also implement a string property called description
.
For example:
class MyClass: CustomStringConvertible {
let foo = 42
var description: String {
return "<\(type(of: self)): foo = \(foo)>"
}
}
print(MyClass()) // prints: <MyClass: foo = 42>
Note: type(of: self)
gets the type of the current instances instead of explicitly writing ‘MyClass’.
Getting description like NSObject
From the println()
API documentation:
/// 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)
So in order to get a custom println()
representation, your class must (e.g.) adopt the Printable
protocol explicitly:
class Test : Printable {
var description:String {
return "This is Test"
}
}
However, this does not work in a Playground of Xcode 6.1.1.
It has been fixed in Xcode 6.3 beta. From the release notes:
• Adding conformances within a Playground now works as expected, ...
I could not find this in the API headers, but it seems that NSObject
(and its subclasses) are already known to conform to Printable
.
Therefore the custom description works for your Test1
class.
In Swift 2 (Xcode 7), the Printable
protocol has been renamed
to CustomStringConvertible
:
class Test : CustomStringConvertible {
public var description:String {
return "This is Test"
}
}
let t = Test()
print(t)
// This is Test
whats the swift equivalent of NSObject Protocol ?
You can do this a couple of ways. First, you can make Consumer
generic:
class Consumer<T: NSObject where T: Prototest> {
var protoInstance: T?
var protoInstance2: T?
}
If you do that, then all references to protoInstance
or protoInstance2
will inherit from NSObject
, and you will be able to call methods like .copy()
directly on the object.
If you don't want Consumer
to be generic, you can enforce restraints on the init
methods using generic parameters, like this:
class Consumer {
// ...
init<T: NSObject where T: Prototest>(x: T) {
protoInstance = x
}
}
If you do that, you will be guaranteed that protoInstance
will be an NSObject
, but you will have to cast to NSObject
to use any of NSObject
's methods:
func doSomething() {
if let x = protoInstance as? NSObject {
x.copy()
}
}
Edit:
Note that I wasn't sure if you really wanted protoInstance
and protoInstance2
to be of different types I was a little unclear from your question. If you do want them to be different types, I can add additional suggestions to this answer.
Swift: Unable To Set Description on Subclass of NSObject
Look at where description
is defined. It is listed in the NSObjectProtocol
as
public var description: String { get }
You can only get
the description property, you can't set
it.
In Objective-C, description is implemented in most classes as a method; it has no underlined storage. The swift equivalent would be a computed property:
public override var description: String {
return "I'm an object"
}
tl;dr Use a computed property instead of a stored property
class CustomObject : NSObject {
private var des: String
override var description: String {
get {
return des
}
set(newValue) {
des = newValue
}
}
init(string: String) {
des = string
}
}
[NSObject description]
The description of the instance gives you information about the specific instance you have created.
- (NSString *)description;
NSString *string = [NSString alloc] initwithString:@"aString"]];
[string description];
Gives you information about this instance (location in memory etc)
On the other side:
+ (NSString *)description;
[NSString description];
Gives you information about the class NSString.
The same rules apply to all NSObject subclasses and other classes that conform to NSObject protocol such NSArray, NSDictionary *NSProxy* etc
Overriding description method in NSObject on swift
description
is a (computed) property ofNSObjectProtocol
, not a method.- Its Swift view returns a
String
, notNSString
. - Since you are overriding a property of a superclass, you must specify
override
explicitly.
Together:
// main.swift:
import Foundation
class Rectangulo: NSObject {
var ladoA : Int
var ladoB : Int
var area: Int {
get {
return ladoA*ladoB
}
}
init (ladoA:Int,ladoB:Int) {
self.ladoA = ladoA
self.ladoB = ladoB
}
override var description : String {
return "El area es \(area)"
}
}
let r = Rectangulo(ladoA: 2, ladoB: 3)
print(r) // El area es 6
hash() and description() not allowed in Xcode 6.3 for NSObject
As the error says, in both cases there's a naming conflict between a property and a method. The most obvious way to fix is by turning your 2 methods into properties:
public override var hash: Int {
return self.hashValue
}
public override var description: String {
return EVReflection.description(self)
}
which can also be written as:
public override var hash:Int {
get {
return self.hashValue
}
}
public override var description : String {
get {
return EVReflection.description(self)
}
}
The reason why it worked in the previous version is most likely because of this:
Swift now detects discrepancies between overloading and overriding in the Swift type system and the effective behavior seen via the Objective-C runtime.
Read more in the release notes (search for 18391046
and 18383574
)
Related Topics
How to Speed Up Updating Relationship Among Tables, After One or Both Tables Are Already Saved
How to Demonstrate a Zombie Object in Swift
Function That Takes a Protocol and a Conforming Class (!) Instance as Parameters
Swiftui: How to Make a Button Open a Url in Safari
How to Implement Protocol Methods That Return Covariant Selfs
Nested Types in Swift - What Is the Good Practice
Uipickerview Selectrow Doesn't Works
How to Handle Two Different Types in an Array in Swift for a Uitableview
Swift, Sprite Kit Game: Have Circle Disappear in Clockwise Manner? on Timer
Swift & Firebase - How to Store More User Data Other Than Email and Password
For-In Loop and Type Casting Only for Objects Which Match Type
How to Rotate Sprites Around a Joint
Using Applescript with Apple Events in MACos - Script Not Working
How to Implement iOServicematchingcallback in Swift
Split Uint32 into [Uint8] in Swift
How to Debug "Precondition Failure" in Xcode
Swift 3 Optional Trouble. Can't Unwrap Url with Passed in String