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)