Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override NSDate description? ..Method Swizzling?

How can I call

print(NSDate()) 

and instead of receiving the usual response, obtain the one I have in a function named getString() that is part of an extension of NSDate.

Here's my extension:

extension NSDate {
    
   //NSDate to String
    public func getString() -> String {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        dateFormatter.locale = NSLocale.currentLocale()
        
        return dateFormatter.stringFromDate(self)
    }
}

Please, note that I don't want to just use:

NSDate().getString()

I want to override original description of this class.

UPDATE:

So, everything looks like the only option is Method Swizzling, if even possible.

Anyone interested in the bounty?

HEADS UP

I'm doing this just for personal growth and to get to understand the concept, not planning on shipping an App using it in this scenario, not even sure right now in what scenarios I could be using it.

like image 641
Hugo Alonso Avatar asked Dec 15 '22 08:12

Hugo Alonso


2 Answers

import Foundation

extension NSDate: Streamable {
    public func writeTo<Target : OutputStreamType>(inout target: Target) {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        dateFormatter.locale = NSLocale.currentLocale()

        print("without swizzling", dateFormatter.stringFromDate(self), toStream: &target)
    }
}

let date = NSDate()

print(date) // without swizzling 2016-03-05 00:09:34 +0100

to print 'default' / original behavior / use

print(date.description)

if you are worry about using print in your extension just replace it with

//print("without swizzling", dateFormatter.stringFromDate(self), toStream: &target)
let str = dateFormatter.stringFromDate(self)
str.writeTo(&target)
like image 105
user3441734 Avatar answered Dec 21 '22 02:12

user3441734


I'm pretty sure this is a terrible, bad, no-good, horrible idea. But here you go:

extension NSDate {
    private static let dateFormatter = NSDateFormatter()
    private static var once = dispatch_once_t()
    static func swizzleDescription() {
        dispatch_once(&once) {
            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
            dateFormatter.locale = NSLocale.currentLocale()

            let originalMethod = class_getInstanceMethod(self, "description")
            let replacementMethod = class_getInstanceMethod(self, "description_terribleIdea")
            method_exchangeImplementations(originalMethod, replacementMethod)
        }
    }

    func description_terribleIdea() -> String {
        return NSDate.dateFormatter.stringFromDate(self)
    }
}

let date = NSDate()
print(date)
NSDate.swizzleDescription()
print(date)

Output:

2016-03-04 22:17:20 +0000
2016-03-04 16:17:20 -0600
like image 27
rob mayoff Avatar answered Dec 21 '22 02:12

rob mayoff