In Objective-C, one can add a description method to their class to aid in debugging:
#implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:#"<%#: %p, foo = %#>", [self class], foo _foo];
}
#end
Then in the debugger, you can do:
po fooClass
<MyClass: 0x12938004, foo = "bar">
What is the equivalent in Swift? Swift's REPL output can be helpful:
1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}
But I'd like to override this behavior for printing to the console:
4> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
Is there a way to clean up this println output? I've seen the Printable protocol:
/// 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 }
}
I figured this would automatically be "seen" by println but it does not appear to be the case:
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)
And instead I have to explicitly call description:
8> println("x = \(x.description)")
x = MyClass, foo = 42
Is there a better way?
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’.
Example of using CustomStringConvertible and CustomDebugStringConvertible protocols in 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's 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)
}
...
}
Which print out:
**** PageContentViewController
pageIndex equals 0 ****
**** PageContentViewController
pageIndex equals 0 ****
---- PageContentViewController
pageIndex equals 0 ----
Note: if you have a custom class which does not inherit from any class included in UIKit or Foundation libraries, then make it inherit of NSObject class or make it conform to CustomStringConvertible and CustomDebugStringConvertible protocols.
Just use CustomStringConvertible and var description: String { return "Some string" }
works in Xcode 7.0 beta
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))"
}
The answers relating to CustomStringConvertible are the way to go. Personally, to keep the class (or struct) definition as clean as possible, I would also separate out the description code into a separate extension:
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!"
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
As described here, you can also use Swift's reflection capabilities to make your classes generate their own description by using this extension:
extension CustomStringConvertible {
var description : String {
var description: String = "\(type(of: self)){ "
let selfMirror = Mirror(reflecting: self)
for child in selfMirror.children {
if let propertyName = child.label {
description += "\(propertyName): \(child.value), "
}
}
description = String(description.dropLast(2))
description += " }"
return description
}
}
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
Related
I have a protocol FooProtocol. and a class Bar<Foo:FooProtocol>. Inside a class an Array var mess: [Foo?]? to keep [foo1, foo2, nil, foo3...] or nil
And I try to make extension for this array to count new Foo object. I prefer to have protocols, because Foos could be very different objects delivered from outer world.
protocol FooProtocol {
....
init(from heaven: Int)
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional,
Wrapped.Element.Wrapped: FooProtocol // 'Wrapped' is not a member type of 'Wrapped.Element'
{
var united: Wrapped.Element.Wrapped { // Nope
let i = ...
return Wrapped.Element.Wrapped(from: i) // Nope
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
var important: Foo {
return mess.united
}
}
Any ideas? I'm blocked.
Edit 1:
After Leo suggestions I changed some parts of my code. But still stucked. This time more code from Playgrounds.
Any object that could be converted into '[Double]'. Could be color (as RGBA), Bezier curve, square, whatever...
public protocol FooProtocol {
var atomized: () -> [Double] {get}
static var count: Int {get}
init(_ array:[Double])
init()
}
public extension Array where Element: FooProtocol {
var average: Element {
var resultAtoms: [Double] = []
let inputAtoms = self.map {$0.atomized()}
for i in 0..<Element.count {
let s = inputAtoms.reduce(into: 0.0, {$0 += $1[i]}) / Double (Element.count)
resultAtoms.append(s)
}
return Element(resultAtoms)
}
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional<FooProtocol>
{
typealias Foo = Wrapped.Element.Wrapped // Doesn't work. How to get class?
var average: Foo { // I cannot use Wrapped.Element, it's Optional
if let thatsList = self {
let withOptionals = Array(thatsList) // OK, its [Optional<FooProtocol>]
let withoutOptionals = thatsList.compactMap({$0}) // OK, its [FooProtocol]
// This is funny, called from class works and makes 'bingo'.
return withoutOptionals.average // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
} else {
return Foo() // Hello? init Wrapped? Foo? How to get Foo()?
}
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
func workOn() {
let z:Foo = mess.average // OK, I can make 'mess.average ?? Foo()' but prefer not do it
}
// Thats OK
func workHard() { // To prove 'Array extension where Element: FooProtocol' works
if let messExist = mess {
let withoutOptionals = messExist.compactMap({$0})
let bingo = withoutOptionals.average //It's OK
}
}
}
class SomeFoo : FooProtocol {
static var count = 3
required init() {
a = 0
b = 0
c = 0
}
required init(_ array: [Double]) {
self.a = Int(array[0])
self.b = Float(array[1])
self.c = array[2]
}
var atomized: () -> [Double] {
return {return [Double(self.a), Double(self.b), self.c]}
}
var a: Int
var b: Float
var c: Double
}
let aFoo = SomeFoo([1, 2, 3])
let bFoo = SomeFoo([7, 9, 1])
let cFoo = SomeFoo([2, 6, 5])
let barData = [nil, aFoo, nil, bFoo, cFoo]
let barWithData = Bar(with: barData)
let barWithoutData = Bar<SomeFoo>(with: nil)
Maybe I should forget about extending array and make some functions inside a class (I'm almost sure I will need those functions somewhere else)
Edit 2
Even if I try to simplify and to make extension for Array I found troubles.
extension Array where
Element == Optional<FooProtocol>
{
func averageNils <Foo: FooProtocol>() -> Foo {
let withOptionals = Array(self) // OK, its [Optional<FooProtocol>]
let withoutOptionals = self.compactMap({$0}) // OK, its [FooProtocol]
return withoutOptionals.average as! Foo // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
}
}
From my understanding, it should work as you did, but one never knows what happens in the swift compiler world (and especially it's error messages).
Anyway, you can circumvent digging deeper into Wrapped.Element.Wrapped by specifyig the Wrapped.Element more precisely to be an Optional<FooProtocol>:
protocol FooProtocol {}
class Foo : FooProtocol {}
extension Optional where
Wrapped: Collection, //OK
Wrapped.Element == Optional<FooProtocol> // still good
{
var unfied: Wrapped.Element // Should be 'Foo' if self is '[Foo?]?' {
{
return 1 == 0 ? nil : Foo()
}
}
Is there a way to create accessors of inner object properties without having boilerplate?
Here's an example of a class with the boilerplate
public class Foo {
internal let bar: Bar
internal init(bar: Bar) {
self.bar = bar
}
private struct Bar: Codable {
let id: Int
let name: String
}
// MARK: - Boilerplate
public var id: Int {
return self.bar.id
}
public var name: String {
return self.bar.name
}
}
// Usage
do {
let bar: Bar = try data.decoded()
let foo = Foo(bar: bar)
print(foo.id)
print(foo.name)
} catch {
...
}
Is there a way to do this without having to write the boilerplate? For larger objects with more properties this could be really helpful
Take Note: The Access Control Modifiers are important
New in Swift 5.1, you can use dynamic member lookup with a key path. This works brilliantly for this sort of "has-a" situation, because key paths maintain full type checking. Here's a simplified example (with no attempt to mirror your actual situation):
struct Dog {
let name : String
}
#dynamicMemberLookup
struct Kennel {
let dog : Dog
subscript(dynamicMember kp:KeyPath<Dog,String>) -> String {
self.dog[keyPath:kp]
}
}
The result is that, given a Kennel k, we can get k.name as a way of getting k.dog.name.
But saying k.xxx would be illegal, because a Dog has no String xxx property; that's what I mean when I say that full type checking is maintained.
The old way would be to use protocols. That way you can use protocol extension to inject the boilerplate.
protocol HasNameAndId {
var id: Int {get}
var name: String {get}
}
protocol WrapperOfHasNameAndId {
associatedtype T : HasNameAndId
var bar: T {get}
}
extension WrapperOfHasNameAndId { // boilerplate
var id: Int {
return self.bar.id
}
var name: String {
return self.bar.name
}
}
// ==============
struct Bar: HasNameAndId {
let id: Int
let name: String
}
class Foo : WrapperOfHasNameAndId {
let bar: Bar
init(bar: Bar) {
self.bar = bar
}
}
// =======
let f = Foo(bar: Bar(id: 1, name: "howdy"))
print(f.id) // 1
print(f.name) // "howdy"
I want to "make" a number of class instances similar to a base class but different in underlying type. (Not quite the same as the typical "Animal" class factory examples seen all over the net!)
The code below is close to working but it requires the user to "upcast" the make result, as in:
var f1 = FOO.make(version: FOO.Ver.f1) as! FOO1_32
I do not want the user to know about the specific class type other than it is a FOO. I have seen other proposals and they all indicate that the solution is to define the make with a generic type that conforms to the protocol as in:
make<T: FOOProtocol>(version: Ver = .f1) -> T
However this gives me the error "generic parameter 'T' could not be inferred" on the call to FOO.make(version: FOO.Ver.f1)
Anyone know how to do this? My Playground code follows.
protocol FOOProtocol
{
associatedtype FOOtype
var value: FOOtype {get set}
}
class FOO
{
enum Ver
{
case f1
case f2
}
class func make(version: Ver = .f1) -> FOO
{
print("FOO make")
switch version
{
case .f1:
return FOO1_32()
case .f2:
return FOO2_64()
}
}
}
class FOO1_32: FOO, FOOProtocol
{
typealias FOOtype = UInt32
private var fooVal: UInt32 = 0
var value: UInt32
{
get { return self.fooVal }
set { self.fooVal = newValue }
}
override init()
{
print("FOO1_32 init")
self.fooVal = 132
}
}
class FOO2_64: FOO, FOOProtocol
{
typealias FOOtype = UInt64
private var fooVal: UInt64 = 0
var value: UInt64
{
get { return self.fooVal }
set { self.fooVal = newValue }
}
override init()
{
print("FOO2_64 init")
self.fooVal = 264
}
}
var f1 = FOO.make(version: FOO.Ver.f1) // requires: as! FOO1_32
let f1v = f1.value
print("\(f1v)")
var f2 = FOO.make(version: FOO.Ver.f2) // requires: as! FOO2_64
let f2v = f2.value
print("\(f2v)")
Lets say I have this class:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children") how can I get its type? (In this case [Node]?)
I imagine having a global function like below will solve my needs:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
Swift 2 (Note: Reflection changed):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
Reflection is achieved in Swift using the global reflect() function. When passing an instance of some type to reflect() it returns a MirrorType, which has a range of properties allowing you to analyze your instance:
var value: Any { get }
var valueType: Any.Type { get }
var objectIdentifier: ObjectIdentifier? { get }
var count: Int { get }
var summary: String { get }
var quickLookObject: QuickLookObject? { get }
var disposition: MirrorDisposition { get }
subscript(i: Int) -> (String, MirrorType) { get }
This seems to work:
func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
let mirror = reflect(instance)
var variableCollection = [String: MirrorType]()
for item in 0..<mirror.count {
variableCollection[mirror[item].0] = mirror[item].1
}
if let type = variableCollection[name] {
let longName = _stdlib_getDemangledTypeName(type.value)
let shortName = split(longName, { $0 == "."}).last
return shortName ?? longName
}
return nil
}
Here's some example code on SwiftStub.
Edit:
The result for optional values is only "Optional".
The result for arrays is only "Array".
The result for dictionaries is only "Dictionary".
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
Building on #PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
extension NSObject {
// Returns the property type
func getTypeOfProperty (name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
while let parent = type.superclassMirror() {
for child in parent.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
type = parent
}
return nil
}
}
Hope this may help someone.
Swift 3 update:
// Extends NSObject to add a function which returns property type
extension NSObject {
// Returns the property type
func getTypeOfProperty (_ name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
while let parent = type.superclassMirror {
for child in parent.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
type = parent
}
return nil
}
}
The solution provided by #peter-kreinz using Swift's class Mirror works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}
This is a bit of a head banger (for me). Basically I want to have 2 different singletons that inherit from the same class. In either I want to use a certain class which itself is derived. So I have Utility and both AUtil:Utility and BUtil:Utility. And Singleton that is used as ASingleton using AUtility in its stomach and B respectively. I failed on all frontiers. The last attempt was a factory pattern which simply got Swift 1.2 to Segfault:
protocol Initializable { init() }
class A:Initializable {
var x = "A"
required init() {}
}
class B:Initializable {
var x = "B"
required init() {}
}
class C {
let t:Initializable
init(t:Initializable) {
self.t = t
println(t)
}
func factory() {
println(t.dynamicType())
}
}
As said I also tried to make the following pattern generic:
private let _SingletonSharedInstance = StaticClass()
class StaticClass {
class var sharedInstance : StaticClass {
return _SingletonSharedInstance
}
}
let s = StaticClass.sharedInstance
(This one isn't generic as you see. But all my attempts failed and so I show my starting point.)
Anyway I seem to be lost between doom and death.
Do you mean something like this?
protocol Initializable: class { init() }
private var instances = [String: Initializable]()
func singletonInstance<T: Initializable>(_ ty: T.Type = T.self) -> T {
let name = NSStringFromClass(ty)
if let o = (instances[name] as? T) {
return o
}
let o = ty()
instances[name] = o
return o
}
An use-side of it, for instance.
class Foo: Initializable { required init() {} }
class Bar: Initializable { required init() {} }
let foo1 = singletonInstance() as Foo // or `singletonInstance(Foo.self)`
let foo2 = singletonInstance() as Foo
assert(foo1 === foo2)
let bar1 = singletonInstance() as Bar
let bar2 = singletonInstance() as Bar
assert(bar1 === bar2)
(I've tested the code above and got it to work in Swift 1.2.)
Inspired by findalls implementation, I build my own singleton generator, which is a little more powerful.
You can create a singleton of any Class or Structure type in Swift. The only thing you have to do is to implement one of two different protocols to your type and use Swift 2.0 or newer.
public protocol SingletonType { init() }
private var singletonInstances = [String: SingletonType]()
extension SingletonType {
// this will crash Xcode atm. it's a Swift 2.0 beta bug. Bug-ID: 21850697
public static var singleton: Self { return singleton { $0 } }
public static func singleton(setter: (_: Self) -> Self) -> Self {
guard let instance = singletonInstances["\(self)"] as? Self else {
return setInstance(self.init(), withSetter: setter, overridable: true)
}
return setInstance(instance, withSetter: setter, overridable: false)
}
private static func setInstance(var instance: Self, withSetter setter: (_: Self) -> Self, overridable: Bool) -> Self {
instance = restoreInstanceIfNeeded(instance1: instance, instance2: setter(instance), overridable: overridable)
singletonInstances["\(self)"] = instance
return instance
}
private static func restoreInstanceIfNeeded(instance1 i1: Self, instance2 i2: Self, overridable: Bool) -> Self {
// will work if the bug in Swift 2.0 beta is fixed !!! Bug-ID: 21850627
guard i1.dynamicType is AnyClass else { return i2 }
return ((i1 as! AnyObject) !== (i2 as! AnyObject)) && !overridable ? i1 : i2
}
}
This may look a little scary, but don't be afraid of this code. The public function inside the protocol extension will create two access points for you.
For example you will be able to write code like this now:
// extend your type: as an example I will extend 'Int' here
extension Int : SingletonType {} // nothing else to do, because Int already has an 'init()' initializer by default
// let the magic happen
Int.singleton // this will generate a singleton Int with 0 as default value
Int.singleton { (_) -> Int in 100 } // should set your Int singleton to 100
Int.singleton { $0 - 55 } // your singleton should be 45 now
// I need to mention that Xcode will produce the setter like this and trow an error
Int.singleton { (yourCustomInstanceName) -> Self in // replace 'Self' with 'Int' and you should be fine
return yourCustomInstanceName
}
// btw. we just ignored the return value everywhere
print(Int.singleton) // will print 45 here
var singleton2 = Int.singleton { $0 + 5 }
singleton2 += 10
print(Int.singleton) // should print 50, because 'singleton2' is just a copy of an Int value type
class A : SingletonType {
var name = "no name"
required init() {}
}
A.singleton { $0; let i = A(); i.name = "hello world"; return i } // custom init on first singleton call for type A
print(A.singleton.name)
print(A.singleton { $0.name = "A"; return $0 }.name)
print(A.singleton.name)
// should print "hello world" and twice the string "A"
If you have any idea how to enhance this code and make it even safer, please let me know. I will push this code on GitHub (MIT License) soon, so everyone can benefit from it.
UPDATE: I modified the code a little so you can now pass a custom initialized instance of a class with the setter function when its called the first time.
UPDATE 2: I removed ClassInstance protocol and modified the private restore function. The Instance protocol is now called SingletonType. The setter function is not optional anymore. Right now Xcode 7 beta 3 will crash and provide an illegal instruction: 4 error when you will call the getter. But this is a confirmed beta bug.