2015-11-09 42 views
2

在这里好几个地方,有人建议,使用的NSDate的延伸内的计算机属性可能一个好办法,通过NSDateFormatter获得日期的字符串版本,像这样:如何在Swift类扩展中创建一个'static'?

extension NSDate { 
    public var UTC : String { 
     let formatter = NSDateFormatter() 
     formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" 
     formatter.timeZone = NSTimeZone(abbreviation: "UTC") 
     return formatter.stringFromDate(self) 
    } 
} 

然而,分配NSDateFormatter是昂贵的,并且建议它们被创建一次并被缓存。每次日期格式化时,上面的代码都会创建NSDateFormatter,我想知道是否有一种方法可以在扩展中创建一次NSDateFormatter以供重用?

很明显,我可以在扩展名之外创建一次,但似乎打败了表征类的封装。

我想起了:https://xkcd.com/1179/ !!

+1

Apple在https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html中说道:“以下类和函数通常不是线程安全的,在大多数情况下,你可以从任何线程使用这些类,只要你一次只从一个线程使用它们... NSDateFormatter ...“ –

+2

实际上,https://developer.apple.com/library/mac/documentation/ (1)在iOS 7和更高版本上NSDateFormatter是线程安全的, (2)在OS X v10上。(2)在OS X v10上安装NSDateFormatter9和更高版本NSDateFormatter是线程安全的,只要您在64位应用程序中使用现代行为,即可使用 ;(3)在早期版本的操作系统上,或者在使用旧格式化器行为或在32位在OS X上,NSDateFormatter不是线程安全的,因此您不能同时从多个线程中变更日期格式化程序。 –

+0

很酷,谢谢@ ramsay咨询。那是一种解脱。 –

回答

4

您可以将静态成员添加到类扩展中,就像在类上一样。您需要在使用它时将类名前缀添加到静态成员名称,例如NSDate.dateFormatterUTC,即使你在同一个班级使用它。

这工作:

extension NSDate { 
    private static let dateFormatterUTC: NSDateFormatter = { 
     let formatter = NSDateFormatter() 
     formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" 
     formatter.timeZone = NSTimeZone(abbreviation: "UTC") 
     return formatter 
    }() 

    public var UTC : String { 
     return NSDate.dateFormatterUTC.stringFromDate(self) 
    } 
} 

它也不是世界上最糟糕的事情只是使用私人常数:

private let dateFormatterUTC: NSDateFormatter = { 
    let formatter = NSDateFormatter() 
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" 
    formatter.timeZone = NSTimeZone(abbreviation: "UTC") 
    return formatter 
}() 

extension NSDate { 
    public var UTC : String { 
     return dateFormatterUTC.stringFromDate(self) 
    } 
} 

这不是比静态类成员显著更糟,因为斯威夫特的private文件私人,而不是类型私人dateFormatterUTC这两个声明具有相同的范围。即使在第一个例子中,NSDate.dateFormatterUTC在整个声明的文件中都是可访问的。

我确实同意静态版本更可取,但仅限于文体原因:我喜欢它的缩进方式,它。

由于Gwendal wisely notes above,此方法假设UTC将永远只能从一个线程调用。尽管static let和全局let在Swift中都是线程安全的, NSDateFormatter类不是! 看起来像it’s threadsafe starting in iOS 7。唷。

不过,在任何提及单身人士旁边总是保持线程安全警告。如果您确实想要使用来自多个线程的非线程安全帮助程序对象,请考虑在每次调用时创建一个新的帮助程序,或者使用NSThread.currentThread().threadDictionary来创建每个线程实例。在选择更复杂的线程本地选项之前,一定要做一点分析以确保实际解决性能问题。

+0

智慧在StackOverflow上丰富!我是“风格理由”的忠实粉丝,所以我也喜欢静态版本。非常感谢Gwendal和Paul .. –

+0

Ramsay咨询公司确实为Apple提供了一个关于NSDateFormatter线程安全性的更准确的链接[#comment55020759_33602923]。 –

+0

很高兴知道!更新的答案反映了这一点。 –

相关问题