I'm trying to convert some Objective-C code to Swift. I've found some similar questions: Swift equivalent to Objective-C Synchronized and objc_sync_enter / objc_sync_exit not working with DISPATCH_QUEUE_PRIORITY_LOW, but I'm not completely happy with the answers. Many answers suggest objc_sync_exit
and objc_sync_enter
, which as far as I can tell, are undocumented implementation details of Apple's frameworks, so I'm not comfortable using them in my production app.
The specific code I'm trying to convert involves an NSDateFormatter which can be accessed by multiple methods:
@implementation NSDateFormatter (MyApp)
+ (NSDateFormatter *)MyAppDateFormatter
{
static NSDateFormatter *formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
formatter = [[NSDateFormatter alloc] init];
});
return formatter;
}
+ (NSString *)stringFromDate:(NSDate *)date withDateFormat:(NSString *)dateFormat
{
NSDateFormatter *formatter = [NSDateFormatter MyAppDateFormatter];
NSString *dateString = nil;
@synchronized(formatter)
{
formatter.dateFormat = dateFormat;
dateString = [formatter stringFromDate:date];
}
return dateString;
}
+ (NSDate *)dateFromString:(NSString *)string
{
NSDateFormatter *formatter = [NSDateFormatter MyAppDateFormatter];
NSDate *date = nil;
@synchronized(formatter)
{
formatter.dateStyle = NSDateFormatterFullStyle;
date = [formatter dateFromString:string];
}
return date;
}
@end
In my swift code, I made the MyAppDateFormatter
a static constant, which in Swift is automatically lazily initialized.
extension DateFormatter {
private static let myAppDateFormatter = DateFormatter()
static func string(from date: Date, with dateFormat: String) -> String {
let dateFormatter = DateFormatter.myAppDateFormatter
dateFormatter.dateFormat = dateFormat
return dateFormatter.string(from: date)
}
static func date(from string: String) -> Date? {
let dateFormatter = DateFormatter.myAppDateFormatter
dateFormatter.dateStyle = .full
return dateFormatter.date(from: string)
}
}
How do I reproduce the @synchronized behavior in Swift? Would adding getters and setters with GCD functions to myAppDateFormatter, as seen here work? And would the technique shown in that answer work even though set
wouldn't be called when setting a property of myAppDateFormatter
? (A property's setter is not called if it is a class instance, and one of it's properties is being changed.)