1

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

6
  • FWIW, setting the dateFormat on a date formatter is just as expensive as creating a new one so if you're trying to avoid the expensiveness of creating a date formatter by sharing one for the whole app you aren't actually accomplishing anything by doing it this way. Commented Mar 21, 2017 at 15:39
  • According to this, DateFormatter is thread safe on iOS 7 and later. Commented Mar 21, 2017 at 15:43
  • @dan, interesting. I actually suspected that and meant to ask about it with my question. For some reason the developer who wrote the Obj-C code wrote it that way, but I was wondering if it was actually premature optimization. Commented Mar 21, 2017 at 15:45
  • 1
    @BallpointBen It is thread safe in that multiple threads can use it to format things at the same time, but setting the dateFormat while another thread is using it to format something isn't safe. Commented Mar 21, 2017 at 15:47
  • @dan, how do you know setting a dateFormat on a date formatter is just as expensive as creating a new one? The Apple documentation (developer.apple.com/library/content/documentation/Cocoa/…) says "creating a date formatter is not a cheap operation." By "creating" are they including setting the properties? Commented Mar 21, 2017 at 16:04

1 Answer 1

1

@synchronized is said to be equivalent to an NSRecursiveLock. I believe creating such a lock at the right scope and using it in the same places as you use @syncronized, wrapping it instead with a call to lock and unlock, is the most direct equivalent in Swift.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.