ios swift swift2 nsdate method-swizzling

ios - ¿Cómo anular la descripción de NSDate?..Método Swizzling?



swift swift2 (5)

Cómo puedo llamar

print(NSDate())

y en lugar de recibir la respuesta habitual, obtenga la que tengo en una función llamada getString() que es parte de una extension de NSDate .

Aquí está mi extensión:

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) } }

Por favor, tenga en cuenta que no quiero simplemente usar:

NSDate().getString()

Quiero anular la description original de esta clase.

ACTUALIZAR:

Entonces, todo parece que la única opción es Method Swizzling , si es posible .

¿Alguien interesado en la recompensa?

AVISO

Hago esto solo para el crecimiento personal y para llegar a comprender el concepto, sin planear enviar una aplicación que lo use en este escenario, ni siquiera estoy seguro en este momento en qué escenarios podría estar usándolo.


Estoy bastante seguro de que esta es una idea terrible, mala, no buena, horrible. Pero aquí tienes:

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)

Salida:

2016-03-04 22:17:20 +0000 2016-03-04 16:17:20 -0600


Podría definir una anulación de NSDate en su módulo con el mismo nombre de clase. Debes seguir las pautas para anular NSDate, que es un poco tedioso (pero al menos funciona en el patio de recreo)

El compilador debe usar su anulación en lugar de la base cuando esté en el alcance:

public class NSDate:Foundation.NSDate { override public var description:String { return getString() } private var dateValue:NSTimeInterval = Foundation.NSDate().timeIntervalSinceReferenceDate override public var timeIntervalSinceReferenceDate:NSTimeInterval { return dateValue } override public init() { super.init() } override public init(timeIntervalSinceReferenceDate ti: NSTimeInterval) { super.init() dateValue = ti } required public init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } //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) + " This is the Overriden One" } } print("/(NSDate())")

impresiones: 2016-03-04 18:16:22 -0500 Esta es la Anulada

tenga en cuenta que esto realmente anula la variable de descripción y no simplemente engaña a la función de impresión.


Por definición, las extensiones pueden agregar funcionalidades pero no anularlas. Souce: El lenguaje de programación Swift - Extensiones

Lo que puede hacer es implementar el protocolo CustomStringConvertible y reemplazar ese comportamiento:

extension NSDate : CustomStringConvertible { var description: String { let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" dateFormatter.locale = NSLocale.currentLocale() return dateFormatter.stringFromDate(self) } }


podría definir su propia versión de impresión:

func print(date: NSDate) { print(date.getString()) } 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) } }

Ambas llamadas ahora imprimirán lo mismo:

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


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

para imprimir comportamiento / uso ''predeterminado'' / original

print(date.description)

Si le preocupa usar la impresión en su extensión simplemente reemplácela con

//print("without swizzling", dateFormatter.stringFromDate(self), toStream: &target) let str = dateFormatter.stringFromDate(self) str.writeTo(&target)