I am converting an old Objective-C class into Swift. My actual question is at the very end after all of the code.
Here is a cut-down version of the Objective-C class:
DateInfo.h:
#import <Foundation/Foundation.h>
@interface RMYearInfo : NSObject
// There are also some instance properties but those aren't relevant to the question
+ (NSInteger)numberOfMonths;
+ (NSArray *)shortMonthNames;
+ (NSArray *)longMonthNames;
// several other class methods
@end
DateInfo.m:
#import "DateInfo.h"
static NSArray *shortMonthNames = nil;
static NSArray *longMonthNames = nil;
// there are several other statics as well
@implementation DateInfo
+ (void)reinitialize {
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateFormatter *yearFormatter = [[NSDateFormatter alloc] init];
shortMonthNames = [yearFormatter shortStandaloneMonthSymbols];
longMonthNames = [yearFormatter standaloneMonthSymbols];
// lots of other processing for the other statics
}
+ (void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reinitialize) name:NSCurrentLocaleDidChangeNotification object:nil];
[self reinitialize];
}
+ (NSInteger)numberOfMonths {
return shortMonthNames.count;
}
+ (NSArray *)shortMonthNames {
return shortMonthNames;
}
+ (NSArray *)longMonthNames {
return longMonthNames;
}
// Lots of other instance and class methods
As you can see, the initialize
method sets up a notification handler so all of the static variables can be reinitialized if the locale is changed while the app is running.
Here is my Swift code. Since there is no initialize
in Swift (any more), my solution is to use private backing variables for the public static variables.
import Foundation
public struct DateInfo {
// some normal instance properties irrelevant to the question
private static var _formatter: DateFormatter!
private static var formatter: DateFormatter {
if _formatter == nil {
_formatter = DateFormatter()
NotificationCenter.default.addObserver(forName: NSLocale.currentLocaleDidChangeNotification, object: nil, queue: nil) { (notification) in
_formatter = DateFormatter()
_shortMonthNames = nil
_longMonthNames = nil
// reset all of the other statics as well
}
}
return _formatter
}
private static var _shortMonthNames: [String]!
public static var shortMonthNames: [String] {
if _shortMonthNames == nil {
_shortMonthNames = formatter.shortStandaloneMonthSymbols
}
return _shortMonthNames
}
private static var _longMonthNames: [String]!
public static var longMonthNames: [String] {
if _longMonthNames == nil {
_longMonthNames = formatter.standaloneMonthSymbols
}
return _longMonthNames
}
public static var numberOfMonths: Int {
return shortMonthNames.count
}
// lots of other similar private/public pairs of statics
}
Is this an appropriate way to translate the functionality given the need to be able to reinitialize the statics? I don't like having a private static backing each public static property.
init
in swift: docs.swift.org/swift-book/LanguageGuide/Initialization.html \$\endgroup\$init
. I'm referring to the Objective-C class methodinitialize
which Swift also had until Swift 3 (I think that's when it went away). \$\endgroup\$initialize
method does. See Swift 3.1 deprecates initialize(). How can I achieve the same thing? for a discussion about Swift eliminating the same method. \$\endgroup\$