问题
I want to convert this code into Swift. The Objective-C code here is making a singleton object(if I can describe as such). I can use dispatch_once_t to convert it, but I want to use a more elegant way which should be similar to "static let bundle: NSBundle!". But "static let bundle: NSBundle!" is not allowed in an extension since it doesn't allow stored properties.
So is it possible to convert the code without dispatch_once_t?
And I faced a problem that I can not have stored properties in a class extension
@implementation NSBundle (CTFeedback)
+ (NSBundle *)feedbackBundle
{
static NSBundle *bundle = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
NSBundle *classBundle = [NSBundle bundleForClass:[CTFeedbackViewController class]];
NSURL *bundleURL = [classBundle URLForResource:@"CTFeedback" withExtension:@"bundle"];
if (bundleURL) {
bundle = [NSBundle bundleWithURL:bundleURL];
} else {
bundle = [NSBundle mainBundle];
}
});
return bundle;
}
@end
My Swift Code:
extension NSBundle
{
static func feedbackBundle()-> NSBundle
{
static let bundle: NSBundle! //!! **Compiler Error here**
let classBundle = NSBundle.init(forClass: CTFeedbackViewController.self)
let bundleURL = classBundle.URLForResource("CTFeedback", withExtension: "bundle")
if let bundleURL2 = bundleURL
{
bundle = NSBundle(URL: bundleURL2)
}
else
{
bundle = NSBundle.mainBundle()
}
return bundle;
}
}
Update:
Thanks to people's answerings. I do it like this now. I am not sure it's the best way/
private class FeedbackBundle
{
static let classBundle = NSBundle.init(forClass: CTFeedbackViewController.self)
}
extension NSBundle
{
static func feedbackBundle()-> NSBundle
{
let bundleURL = FeedbackBundle.classBundle.URLForResource("CTFeedback", withExtension: "bundle")
if let bundleURL2 = bundleURL
{
return NSBundle(URL: bundleURL2)!
}
else
{
return NSBundle.mainBundle()
}
}
}
回答1:
In Swift, you cannot add static variables in extensions. You can retry in the original class if accessible. Otherwise, you can modify the code like:
if let bundleURL2 = bundleURL
{
return NSBundle(URL: bundleURL2)
}
else
{
return NSBundle.mainBundle()
}
回答2:
You could always have the static var reside outside of the extension, either in a separate class or as a simple global variable (which static variables are anyway).
for example:
private class FeedbackBundle
{
static var bundle: NSBundle!
}
extension NSBundle
{
static func feedbackBundle()-> NSBundle
{
let classBundle = NSBundle.init(forClass: CTFeedbackViewController.self)
let bundleURL = classBundle.URLForResource("CTFeedback", withExtension: "bundle")
if let bundleURL2 = bundleURL
{
FeedbackBundle.bundle = NSBundle(URL: bundleURL2)
}
else
{
FeedbackBundle.bundle = NSBundle.mainBundle()
}
return FeedbackBundle.bundle;
}
}
回答3:
You can also subclass NSBundle and add this property to it.
来源:https://stackoverflow.com/questions/38863358/how-can-i-add-a-static-stored-property-in-a-class-extension-to-make-a-singleto