Accessing Swift OptionSetType in Objective-C - ios

In my Swift class, I have an OptionSetType defined for fulfillment options.
struct FulfillmentOption : OptionSetType {
let rawValue: Int
static let Pickup = FulfillmentOption(rawValue: 1 << 0)
static let Shipping = FulfillmentOption(rawValue: 1 << 1)
static let UserShipping = FulfillmentOption(rawValue: 1 << 2)
}
I then create a variable to add/remove and read options. This works as expected.
var options: FulfillmentOption = []
options.insert(FulfillmentOption.Pickup)
options.contains(FulfillmentOption.Pickup)
However I need to access the options variable from one of my Objective-C classes. Since OptionSetType is not defined in Objective-C, the variable is not visible to any of my Objective-C classes.
What is the best way for me to expose this to Objective-C? Should I stop using OptionSetType altogether?
I've considered doing creating public and private variables like this to convert between the two. I don't love this, but it's the best I've come up with thus far.
private var _options: FulfillmentOptions = []
private var options: UInt {
get {
// get raw value from _options
}
set {
// set raw value to _options
}
}
Is there a more elegant way to accomplish this? I'd like to avoid writing unnecessary code.

Not a direct answer to your question, but as an alternative you can
work the other way around. Define
typedef NS_OPTIONS(NSInteger, FulfillmentOption) {
FulfillmentOptionPickup = 1 << 0,
FulfillmentOptionShipping = 1 << 1,
FulfillmentOptionUserShipping = 1 << 2,
};
in an Objective-C header, this would be imported into Swift as
public struct FulfillmentOption : OptionSetType {
public init(rawValue: Int)
public static var Pickup: FulfillmentOption { get }
public static var Shipping: FulfillmentOption { get }
public static var UserShipping: FulfillmentOption { get }
}
More Information can be found in the "Using Swift with Cocoa and Objective-C" reference:
"Interaction with C APIs":
Swift also imports C-style enumerations marked with the
NS_OPTIONS
macro as a Swift option set. Option sets behave similarly to imported
enumerations by truncating their prefixes to option value names.
"Swift and Objective-C in the Same Project":
You’ll have access to anything within a class or protocol that’s
marked with the #objc attribute as long as it’s compatible with
Objective-C. This excludes Swift-only features such as those listed
here:
...
Structures defined in Swift
...

Objective-C can't see structs, but luckily, you can implement OptionSet with an #objc class instead.
Note that it is very important to implement -hash and -isEqual: because lots of the SetAlgebra default implementations that OptionSet inherits rely on them to work. If you don't implement them, print("\(Ability(.canRead) == Ability(.canRead))") prints false.
#objc
public final class Ability: NSObject, OptionSet {
// Don't use
//
// public static let canRead = Ability(rawValue: 1 << 0)
// public static let canWrite = Ability(rawValue: 1 << 1)
//
// because `Ability` is a `class`, not a `struct`,
// so `let` doesn't enforce immutability, and thus
//
// Ability.canRead.formUnion(Ability.canWrite)
//
// would break `Ability.canRead` for everyone!
public static func canRead(): Ability {
return Ability(rawValue: 1 << 0)
}
public static func canWrite(): Ability {
return Ability(rawValue: 1 << 1)
}
public var rawValue: Int
public typealias RawValue = Int
public override convenience init() {
self.init(rawValue: 0)
}
public init(rawValue: Int) {
self.rawValue = rawValue
super.init()
}
/// Must expose this to Objective-C manually because
/// OptionSet.init(_: Sequence) isn't visible to Objective-C
/// Because Sequence isn't an Objective-C-visible type
#objc
#available(swift, obsoleted: 1.0)
public convenience init(abilitiesToUnion: [Ability]) {
self.init(abilitiesToUnion)
}
// MARK: NSObject
// Note that it is very important to implement -hash and
// -isEqual: because lots of the `SetAlgebra`
// default implementations that `OptionSet` inherits
// rely on them to work. If you don't implement them,
// print("\(Ability(.canRead) == Ability(.canRead))")
// prints `false`
public override var hash: Int {
return rawValue
}
public override func isEqual(_ object: Any?) -> Bool {
guard let that = object as? Ability else {
return false
}
return rawValue == that.rawValue
}
// MARK: OptionSet
public func formUnion(_ other: Ability) {
rawValue = rawValue | other.rawValue
}
public func formIntersection(_ other: Ability) {
rawValue = rawValue & other.rawValue
}
public func formSymmetricDifference(_ other: Ability) {
rawValue = rawValue ^ other.rawValue
}
}
Then, I can instantiate this from Objective-C:
Ability *emptyAbility = [Ability new];
Ability *readOnlyAbility = [[Ability alloc] initWithAbilitiesToUnion:#[Ability.canRead]];
Ability *readWriteAbility = [[Ability alloc] initWithAbilitiesToUnion:#[Ability.canRead, Ability.canWrite]];

Related

Using Class as RawValue of Enum not working

I am trying to use my custom class ChallengeUIElement as rawValue of my enum ChallengeUIElementType.
Therefore, I tried everything that Xcode wanted me to do, but I still get error messages thrown right at my face. It starts to hurt...
Anyways, I followed along this tutorial and get lots of error messages that I do not understand.
After googling for a while, I found some stack overflow entries about classes as rawValue types of enums.
However, I still was unable to get my enum with class type working.
My errors:
Here is my code:
enum ChallengeUIElementType: ChallengeUIElement, CaseIterable {
typealias RawValue = ChallengeUIElement
case Default = "DefaultElementCell"
}
class ChallengeUIElement: Equatable, ExpressibleByStringLiteral {
static func == (lhs: ChallengeUIElement, rhs: ChallengeUIElement) -> Bool {
return lhs.identifier == rhs.identifier && lhs.height == rhs.height && lhs.type == rhs.type
}
var height: CGFloat
var identifier: String
var type: UICollectionViewCell.Type
public init(stringLiteral value: String) {
let components = value.components(separatedBy: ",")
if components.count == 1 {
if components[0] == "DefaultElementCell" {
self.identifier = components[0]
self.type = DefaultElementCell.self
self.height = 380
}
}
}
public init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
public init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
}
Also, I do not understand why I could use RawRepresentable as protocol with this approach, but not with this one?
Any help would be highly appreciated.
The errors you get are mostly about the way you incorrectly declared your initialisers. They don't really have much to do with creating an enum with a class raw value.
Because your initialisers are required by the protocol, they need to be marked as required. You don't need to do this if your class is final. So either mark the class as final or mark all the initialisers as required.
The two convenience initialisers need to be marked as convenience:
public convenience init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
public convenience init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
These are "convenience" initialisers because they call another initialiser declared in the class.
Additionally, the public init(stringLiteral value: String) initialiser does not initialise all the properties. Think about what happens if the if statements are not run. You need to give your properties (height, identifier and type) some default values.

How to implement a computed property like a abstract property in Swift?

I know there is no abstract class and either Abstract keyword in Swift. The following problem just like implementing a abstract property.
For convenient, supposed that there are three classes as following:
class SuperClass: NSManagedObject { // the compiler will complain without 'NSManagedObject', and I don't know why.
public let superInt: Int = 1 // use superInt to represent other stored property for SuperClass.
}
class SubClass1: SuperClass {
let subInt1: Int = 2 // use 'subInt1' to represent other stored property for SubClass1.
}
class SubClass2: SuperClass {
let subInt2: Int = 3 // use 'subInt2' to represent other stored property for SubClass2.
}
protocol TestProtocol {
var count: Int { get } // a computed property
func printInt() // a custom method
}
Here, those classes are all objects defined in CoreData, especially SuperClass is a abstract Entity. I want to extend some interfaces(the TestProtocol above) for SuperClass, so that I can use polymorphism. I come up with 2 methods:
Method 1: let SuperClass confirms TestProtocol.
extension SuperClass: TestProtocol {
var count: Int { return superInt }
func printInt() { print("Here is SuperClass. Count: \(count)") }
}
extension SubClass1 {
override var count: Int { return subInt1 }
override func printInt() { print("Here is SubClass1. Count is \(count)") }
}
extension SubClass2 {
override var count: Int { return subInt2 }
override func printInt() { print("Here is SubClass2. Count is \(count)") }
}
// Here is the test code
let subClasses: [SuperClass] = [SubClass1(), SubClass2()]
subClasses.forEach { $0.printInt() }
Method 2: Convert subClasses to a protocol object.
extension SubClass1: TestProtocol {
var count: Int { return subInt1 }
func printInt() { print("Here is SubClass1. Count is \(count)") }
}
extension SubClass2: TestProtocol {
var count: Int { return subInt2 }
func printInt() { print("Here is SubClass1. Count is \(count)") }
}
// Here is the test code
let subClasses: [SuperClass] = [SubClass1(), SubClass2()]
subClasses.forEach { ($0 as! TestProtocol).printInt() }
In method 1, everything looks good. But I have to implement the code in SuperClass which is totally useless. The method seems like a little trick of grammar.
In method 2, all code is useful, but the conversion at last line broke the elegance of code. It makes me crazy continuously using code like ($0 as! TestProtocol).printInt().
I'm not satisfied with both methods. So which is recommended way or is there a better way to do it?
In your second method you actually do not need to use casting (($0 as! TestProtocol).printInt()). Here is how:
let subClasses: [TestProtocol] = [SubClass1(), SubClass2()]
subClasses.forEach { $0.printInt() }
By typing the subClasses array to TestProtocol instead of SuperClass you can remove the need for casting because the compiler now knows that every element in subClasses conforms to TestProtocol and thus, has a method printInt().
Your super class does not serve any purpose in both method 1 and method 2. In both methods you have defined, you want to eventually call printInt() which should be common to all sub classes. Notice I have highlighted "should be common". The purpose of a protocol is to specify requirements that conforming types must implement. Therefore, a protocol is sufficient to form the contract that your classes 1 and 2 should implement var count and func printInt(). Also a protocol is a type, so you do not need a super class to hold references to the other two classes as you did here:
let subClasses: [SuperClass] = [SubClass1(), SubClass2()]
In my opinion, this would be a better way:
protocol TestProtocol {
var count: Int { get } // a computed property
func printInt() // a custom method
}
Class1: TestProtocol {
var subInt = 2
var count: Int { return subInt1 }
func printInt() { print("Here is SubClass1. Count is \(count)") }
}
Class2: TestProtocol {
var subInt = 3
var count: Int { return subInt2 }
func printInt() { print("Here is SubClass2. Count is \(count)") }
}
let smallClasses: [TestProtocol] = [Class1(), Class2()]
smallClasses.forEach { $0.printInt() }
This way of doing things fulfills the Protocol Oriented way of programming in Swift, which is the favored approach. Generally speaking, inheritance and subclassing is shunned in iOS design patterns and I will direct you to this blog post so you can learn more about why https://krakendev.io/blog/subclassing-can-suck-and-heres-why
EDIT
You have clarified your question a bit more so I am going to attempt to answer it better. You are looking for the equivalent of what is an abstract class in Java which are classes that contain one or more abstract methods. An abstract method in Java is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and require subclasses to provide implementations for the abstract methods.
Swift does not come with the same functionality but something that is functionaly equivalent would require a super class where all sub classes are forced to implement properties or methods that must be common to all sub classes. This is of course achieved by the protocol method I have shown above but you also require the ability to call properties or methods from the super class from the sub class which means each sub class must be able to cast as both the protocol type and the super class type.
Here is my solution to that written in Swift 3:
protocol TestProtocol {
var count: Int { get } // a computed property
func printInt() // a custom method
}
//base class
class SuperClass: TestProtocol {
var sharedInt: Int = 0
var subInt: Int = 1
var count: Int { return subInt }
func printInt() { print("Here is SubClass. Count is \(count)") }
}
class class1: SuperClass {
override init(){
super.init()
self.subInt = 2
}
}
class class2: SuperClass {
override init(){
super.init()
self.subInt = 3
}
}
//I can get count and printInt() which superClass, class1 and class2 share becuase of the protocol.
let smallClasses: [TestProtocol] = [SuperClass(), class1(), class2()]
smallClasses.forEach { $0.printInt() }
//I can convert the sub classes to super class type and call their printInt method
let smallClasses2: [SuperClass] = [class1(), class2()]
smallClasses2.forEach { $0.printInt() }
//I can get to the shared values the sub classes have from the super class
smallClasses2.forEach { print($0.sharedInt) }
If you copy and paste the code above into a Playground in Xcode, you will receive the following output:
Here is SubClass. Count is 1
Here is SubClass. Count is 2
Here is SubClass. Count is 3
Here is SubClass. Count is 2
Here is SubClass. Count is 3
0
0

How to display OptionSet values in human-readable form?

Swift has the OptionSet type, which basically adds set operations to C-Style bit flags. Apple is using them pretty extensively in their frameworks. Examples include the options parameter in animate(withDuration:delay:options:animations:completion:).
On the plus side, it lets you use clean code like:
options: [.allowAnimatedContent, .curveEaseIn]
However, there is a downside as well.
If I want to display the specified values of an OptionSet, there doesn't seem to be a clean way to do it:
let options: UIViewAnimationOptions = [.allowAnimatedContent, .curveEaseIn]
print("options = " + String(describing: options))
Displays the very unhelpful message:
options = UIViewAnimationOptions(rawValue: 65664)
The docs for some of these bit fields expresses the constant as a power-of-two value:
flag0 = Flags(rawValue: 1 << 0)
But the docs for my example OptionSet, UIViewAnimationOptions, doesn't tell you anything about the numeric value of these flags and figuring out bits from decimal numbers is not straightforward.
Question:
Is there some clean way to map an OptionSet to the selected values?
My desired output would be something like:
options = UIViewAnimationOptions([.allowAnimatedContent, .curveEaseIn])
But I can't think of a way to do this without adding messy code that would require me to maintain a table of display names for each flag.
(I'm interested in doing this for both system frameworks and custom OptionSets I create in my own code.)
Enums let you have both a name and a raw value for the enum, but those don't support the set functions you get with OptionSets.
Here is one approach I've taken, using a dictionary and iterating over the keys. Not great, but it works.
struct MyOptionSet: OptionSet, Hashable, CustomStringConvertible {
let rawValue: Int
static let zero = MyOptionSet(rawValue: 1 << 0)
static let one = MyOptionSet(rawValue: 1 << 1)
static let two = MyOptionSet(rawValue: 1 << 2)
static let three = MyOptionSet(rawValue: 1 << 3)
var hashValue: Int {
return self.rawValue
}
static var debugDescriptions: [MyOptionSet:String] = {
var descriptions = [MyOptionSet:String]()
descriptions[.zero] = "zero"
descriptions[.one] = "one"
descriptions[.two] = "two"
descriptions[.three] = "three"
return descriptions
}()
public var description: String {
var result = [String]()
for key in MyOptionSet.debugDescriptions.keys {
guard self.contains(key),
let description = MyOptionSet.debugDescriptions[key]
else { continue }
result.append(description)
}
return "MyOptionSet(rawValue: \(self.rawValue)) \(result)"
}
}
let myOptionSet = MyOptionSet([.zero, .one, .two])
// prints MyOptionSet(rawValue: 7) ["two", "one", "zero"]
This article in NSHipster gives an alternative to OptionSet that offers all the features of an OptionSet, plus easy logging:
https://nshipster.com/optionset/
If you simply add a requirement that the Option type be CustomStringConvertible, you can log Sets of this type very cleanly. Below is the code from the NSHipster site - the only change being the addition of CustomStringConvertible conformance to the Option class
protocol Option: RawRepresentable, Hashable, CaseIterable, CustomStringConvertible {}
enum Topping: String, Option {
case pepperoni, onions, bacon,
extraCheese, greenPeppers, pineapple
//I added this computed property to make the class conform to CustomStringConvertible
var description: String {
return ".\(self.rawValue)"
}
}
extension Set where Element == Topping {
static var meatLovers: Set<Topping> {
return [.pepperoni, .bacon]
}
static var hawaiian: Set<Topping> {
return [.pineapple, .bacon]
}
static var all: Set<Topping> {
return Set(Element.allCases)
}
}
typealias Toppings = Set<Topping>
extension Set where Element: Option {
var rawValue: Int {
var rawValue = 0
for (index, element) in Element.allCases.enumerated() {
if self.contains(element) {
rawValue |= (1 << index)
}
}
return rawValue
}
}
Then using it:
let toppings: Set<Topping> = [.onions, .bacon]
print("toppings = \(toppings), rawValue = \(toppings.rawValue)")
That outputs
toppings = [.onions, .bacon], rawValue = 6
Just like you want it to.
That works because a Set displays its members as a comma-delimited list inside square brackets, and uses the description property of each set member to display that member. The description property simply displays each item (the enum's name as a String) with a . prefix
And since the rawValue of a Set<Option> is the same as an OptionSet with the same list of values, you can convert between them readily.
I wish Swift would just make this a native language feature for OptionSets.
StrOptionSet Protocol:
Add a labels set property to test each label value on Self.
StrOptionSet Extension:
Filter out which is not intersected.
Return the label text as array.
Joined with "," as CustomStringConvertible::description
Here is the snippet:
protocol StrOptionSet : OptionSet, CustomStringConvertible {
typealias Label = (Self, String)
static var labels: [Label] { get }
}
extension StrOptionSet {
var strs: [String] { return Self.labels
.filter{ (label: Label) in self.intersection(label.0).isEmpty == false }
.map{ (label: Label) in label.1 }
}
public var description: String { return strs.joined(separator: ",") }
}
Add the label set for target option set VTDecodeInfoFlags.
extension VTDecodeInfoFlags : StrOptionSet {
static var labels: [Label] { return [
(.asynchronous, "asynchronous"),
(.frameDropped, "frameDropped"),
(.imageBufferModifiable, "imageBufferModifiable")
]}
}
Use it
let flags: VTDecodeInfoFlags = [.asynchronous, .frameDropped]
print("flags:", flags) // output: flags: .asynchronous,frameDropped
This is how I did it.
public struct Toppings: OptionSet {
public let rawValue: Int
public static let cheese = Toppings(rawValue: 1 << 0)
public static let onion = Toppings(rawValue: 1 << 1)
public static let lettuce = Toppings(rawValue: 1 << 2)
public static let pickles = Toppings(rawValue: 1 << 3)
public static let tomatoes = Toppings(rawValue: 1 << 4)
public init(rawValue: Int) {
self.rawValue = rawValue
}
}
extension Toppings: CustomStringConvertible {
static public var debugDescriptions: [(Self, String)] = [
(.cheese, "cheese"),
(.onion, "onion"),
(.lettuce, "lettuce"),
(.pickles, "pickles"),
(.tomatoes, "tomatoes")
]
public var description: String {
let result: [String] = Self.debugDescriptions.filter { contains($0.0) }.map { $0.1 }
let printable = result.joined(separator: ", ")
return "\(printable)"
}
}
struct MyOptionSet: OptionSet {
let rawValue: UInt
static let healthcare = MyOptionSet(rawValue: 1 << 0)
static let worldPeace = MyOptionSet(rawValue: 1 << 1)
static let fixClimate = MyOptionSet(rawValue: 1 << 2)
static let exploreSpace = MyOptionSet(rawValue: 1 << 3)
}
extension MyOptionSet: CustomStringConvertible {
static var debugDescriptions: [(Self, String)] = [
(.healthcare, "healthcare"),
(.worldPeace, "world peace"),
(.fixClimate, "fix the climate"),
(.exploreSpace, "explore space")
]
var description: String {
let result: [String] = Self.debugDescriptions.filter { contains($0.0) }.map { $0.1 }
return "MyOptionSet(rawValue: \(self.rawValue)) \(result)"
}
}
Usage
var myOptionSet: MyOptionSet = []
myOptionSet.insert(.healthcare)
print("here is my options: \(myOptionSet)")

How to call static method provided by protocol in Swift

How to access to static protocol method within a instance
I have a list of Contact, the contact can be a FamilyContact that inherit from Contact and the GroupStatus protocol
I want to call the static method from GroupStatus but in vain...
Here is my code
protocol GroupStatus {
static func isPrivate() -> Bool // static method that indicates the status
}
protocol IsBusy {
func wizzIt()
}
class AdresseBook {
private var contacts = [Contact]()
func addOne(c: Contact) {
contacts.append(c)
}
func listNonPrivated() -> [Contact]? {
var nonPrivateContact = [Contact]()
for contact in contacts {
// here is I should call the static method provided by the protocol
if self is GroupStatus {
let isPrivate = contact.dynamicType.isPrivate()
if !isPrivate {
nonPrivateContact.append(contact)
}
}
nonPrivateContact.append(contact)
}
return nonPrivateContact
}
}
class Contact : Printable {
var name: String
init(name: String) {
self.name = name
}
func wizz() -> Bool {
if let obj = self as? IsBusy {
obj.wizzIt()
return true
}
return false
}
var description: String {
return self.name
}
}
class FamilyContact: Contact, GroupStatus {
static func isPrivate() -> Bool {
return true
}
}
I can't compile Contact.Type does not have a member named 'isPrivate'
How can I call it ? It works if I delete the static keyword, but I think is more logical to define it static.
If I replace
let isPrivate = contact.dynamicType.isPrivate()
by
let isPrivate = FamilyContact.isPrivate()
It works, but I can have more than 1 subclasses
If I remove the static keywork I can do it by this way :
if let c = contact as? GroupStatus {
if !c.isPrivate() {
nonPrivateContact.append(contact)
}
}
But I want to keep the static keyword
This looks like a bug or a non-supported feature. I would expect that
the following works:
if let gsType = contact.dynamicType as? GroupStatus.Type {
if gsType.isPrivate() {
// ...
}
}
However, it does not compile:
error: accessing members of protocol type value 'GroupStatus.Type' is unimplemented
It does compile with FamilyContact.Type instead of GroupStatus.Type. A similar problem is reported here:
Swift 1.1 and 1.2: accessing members of protocol type value XXX.Type' is unimplemented
Making isPrivate() an instance method instead of a class method is
the only workaround that I currently can think of, maybe someone comes
with a better solution ...
Update for Swift 2 / Xcode 7: As #Tankista noted below, this has
been fixed. The above code compiles and works as expected in Xcode 7 beta 3.
type(of: contact).isPrivate()
This should work in recent Swift.

How to use singleton in swift? [duplicate]

I'm trying to work out an appropriate singleton model for usage in Swift. So far, I've been able to get a non-thread safe model working as:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
Wrapping the singleton instance in the Static struct should allow a single instance that doesn't collide with singleton instances without complex naming schemings, and it should make things fairly private. Obviously though, this model isn't thread-safe. So I tried to add dispatch_once to the whole thing:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(Static.token) { Static.instance = TPScopeManager() }
return Static.instance!
}
}
But I get a compiler error on the dispatch_once line:
Cannot convert the expression's type 'Void' to type '()'
I've tried several different variants of the syntax, but they all seem to have the same results:
dispatch_once(Static.token, { Static.instance = TPScopeManager() })
What is the proper usage of dispatch_once using Swift? I initially thought the problem was with the block due to the () in the error message, but the more I look at it, the more I think it may be a matter of getting the dispatch_once_t correctly defined.
tl;dr: Use the class constant approach if you are using Swift 1.2 or above and the nested struct approach if you need to support earlier versions.
From my experience with Swift there are three approaches to implement the Singleton pattern that support lazy initialization and thread safety.
Class constant
class Singleton {
static let sharedInstance = Singleton()
}
This approach supports lazy initialization because Swift lazily initializes class constants (and variables), and is thread safe by the definition of let. This is now officially recommended way to instantiate a singleton.
Class constants were introduced in Swift 1.2. If you need to support an earlier version of Swift, use the nested struct approach below or a global constant.
Nested struct
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static let instance: Singleton = Singleton()
}
return Static.instance
}
}
Here we are using the static constant of a nested struct as a class constant. This is a workaround for the lack of static class constants in Swift 1.1 and earlier, and still works as a workaround for the lack of static constants and variables in functions.
dispatch_once
The traditional Objective-C approach ported to Swift. I'm fairly certain there's no advantage over the nested struct approach but I'm putting it here anyway as I find the differences in syntax interesting.
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
}
See this GitHub project for unit tests.
Since Apple has now clarified that static struct variables are initialized both lazy and wrapped in dispatch_once (see the note at the end of the post), I think my final solution is going to be:
class WithSingleton {
class var sharedInstance: WithSingleton {
struct Singleton {
static let instance = WithSingleton()
}
return Singleton.instance
}
}
This takes advantage of the automatic lazy, thread-safe initialization of static struct elements, safely hides the actual implementation from the consumer, keeps everything compactly compartmentalized for legibility, and eliminates a visible global variable.
Apple has clarified that lazy initializer are thread-safe, so there's no need for dispatch_once or similar protections
The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as dispatch_once to make sure that the initialization is atomic. This enables a cool way to use dispatch_once in your code: just declare a global variable with an initializer and mark it private.
From here
For Swift 1.2 and beyond:
class Singleton {
static let sharedInstance = Singleton()
}
With a proof of correctness (all credit goes here), there is little to no reason now to use any of the previous methods for singletons.
Update: This is now the official way to define singletons as described in the official docs!
As for concerns on using static vs class. static should be the one to use even when class variables become available. Singletons are not meant to be subclassed since that would result in multiple instances of the base singleton. Using static enforces this in a beautiful, Swifty way.
For Swift 1.0 and 1.1:
With the recent changes in Swift, mostly new access control methods, I am now leaning towards the cleaner way of using a global variable for singletons.
private let _singletonInstance = SingletonClass()
class SingletonClass {
class var sharedInstance: SingletonClass {
return _singletonInstance
}
}
As mentioned in the Swift blog article here:
The lazy initializer for a global variable (also for static members of
structs and enums) is run the first time that global is accessed, and
is launched as dispatch_once to make sure that the initialization is
atomic. This enables a cool way to use dispatch_once in your code:
just declare a global variable with an initializer and mark it
private.
This way of creating a singleton is thread safe, fast, lazy, and also bridged to ObjC for free.
Swift 1.2 or later now supports static variables/constants in classes. So you can just use a static constant:
class MySingleton {
static let sharedMySingleton = MySingleton()
private init() {
// ...
}
}
There is a better way to do it. You can declare a global variable in your class above the class declaration like this:
var tpScopeManagerSharedInstance = TPScopeManager()
This just calls your default init or whichever init and global variables are dispatch_once by default in Swift. Then in whichever class you want to get a reference, you just do this:
var refrence = tpScopeManagerSharedInstance
// or you can just access properties and call methods directly
tpScopeManagerSharedInstance.someMethod()
So basically you can get rid of the entire block of shared instance code.
Swift singletons are exposed in the Cocoa frameworks as class functions, e.g. NSFileManager.defaultManager(), NSNotificationCenter.defaultCenter(). So it makes more sense as a class function to mirror this behavior, rather than a class variable as some other solutions. e.g:
class MyClass {
private static let _sharedInstance = MyClass()
class func sharedInstance() -> MyClass {
return _sharedInstance
}
}
Retrieve the singleton via MyClass.sharedInstance().
Per the Apple documentation, it has been repeated many times that the easiest way to do this in Swift is with a static type property:
class Singleton {
static let sharedInstance = Singleton()
}
However, if you're looking for a way to perform additional setup beyond a simple constructor call, the secret is to use an immediately invoked closure:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
This is guaranteed to be thread-safe and lazily initialized only once.
Swift 4+
protocol Singleton: class {
static var sharedInstance: Self { get }
}
final class Kraken: Singleton {
static let sharedInstance = Kraken()
private init() {}
}
Looking at Apple's sample code I came across this pattern. I'm not sure how Swift deals with statics, but this would be thread safe in C#. I include both the property and method for Objective-C interop.
struct StaticRank {
static let shared = RankMapping()
}
class func sharedInstance() -> RankMapping {
return StaticRank.shared
}
class var shared:RankMapping {
return StaticRank.shared
}
In brief,
class Manager {
static let sharedInstance = Manager()
private init() {}
}
You may want to read Files and Initialization
The lazy initializer for a global variable (also for static members of
structs and enums) is run the first time that global is accessed, and
is launched as dispatch_once to make sure that the initialization is
atomic.
If you are planning on using your Swift singleton class in Objective-C, this setup will have the compiler generate appropriate Objective-C-like header(s):
class func sharedStore() -> ImageStore {
struct Static {
static let instance : ImageStore = ImageStore()
}
return Static.instance
}
Then in Objective-C class you can call your singleton the way you did it in pre-Swift days:
[ImageStore sharedStore];
This is just my simple implementation.
First solution
let SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
Later in your code:
func someFunction() {
var socketManager = SocketManager
}
Second solution
func SocketManager() -> SocketManagerSingleton {
return _SocketManager
}
let _SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
And later in your code you will be able to keep braces for less confusion:
func someFunction() {
var socketManager = SocketManager()
}
final class MySingleton {
private init() {}
static let shared = MySingleton()
}
Then call it;
let shared = MySingleton.shared
Use:
class UtilSingleton: NSObject {
var iVal: Int = 0
class var shareInstance: UtilSingleton {
get {
struct Static {
static var instance: UtilSingleton? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token, {
Static.instance = UtilSingleton()
})
return Static.instance!
}
}
}
How to use:
UtilSingleton.shareInstance.iVal++
println("singleton new iVal = \(UtilSingleton.shareInstance.iVal)")
The best approach in Swift above 1.2 is a one-line singleton, as -
class Shared: NSObject {
static let sharedInstance = Shared()
private override init() { }
}
To know more detail about this approach you can visit this link.
From Apple Docs (Swift 3.0.1),
You can simply use a static type property, which is guaranteed to be
lazily initialized only once, even when accessed across multiple
threads simultaneously:
class Singleton {
static let sharedInstance = Singleton()
}
If you need to perform additional setup beyond initialization, you can
assign the result of the invocation of a closure to the global
constant:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
I would suggest an enum, as you would use in Java, e.g.
enum SharedTPScopeManager: TPScopeManager {
case Singleton
}
Just for reference, here is an example Singleton implementation of Jack Wu/hpique's Nested Struct implementation. The implementation also shows how archiving could work, as well as some accompanying functions. I couldn't find this complete of an example, so hopefully this helps somebody!
import Foundation
class ItemStore: NSObject {
class var sharedStore : ItemStore {
struct Singleton {
// lazily initiated, thread-safe from "let"
static let instance = ItemStore()
}
return Singleton.instance
}
var _privateItems = Item[]()
// The allItems property can't be changed by other objects
var allItems: Item[] {
return _privateItems
}
init() {
super.init()
let path = itemArchivePath
// Returns "nil" if there is no file at the path
let unarchivedItems : AnyObject! = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
// If there were archived items saved, set _privateItems for the shared store equal to that
if unarchivedItems {
_privateItems = unarchivedItems as Array<Item>
}
delayOnMainQueueFor(numberOfSeconds: 0.1, action: {
assert(self === ItemStore.sharedStore, "Only one instance of ItemStore allowed!")
})
}
func createItem() -> Item {
let item = Item.randomItem()
_privateItems.append(item)
return item
}
func removeItem(item: Item) {
for (index, element) in enumerate(_privateItems) {
if element === item {
_privateItems.removeAtIndex(index)
// Delete an items image from the image store when the item is
// getting deleted
ImageStore.sharedStore.deleteImageForKey(item.itemKey)
}
}
}
func moveItemAtIndex(fromIndex: Int, toIndex: Int) {
_privateItems.moveObjectAtIndex(fromIndex, toIndex: toIndex)
}
var itemArchivePath: String {
// Create a filepath for archiving
let documentDirectories = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
// Get the one document directory from that list
let documentDirectory = documentDirectories[0] as String
// append with the items.archive file name, then return
return documentDirectory.stringByAppendingPathComponent("items.archive")
}
func saveChanges() -> Bool {
let path = itemArchivePath
// Return "true" on success
return NSKeyedArchiver.archiveRootObject(_privateItems, toFile: path)
}
}
And if you didn't recognize some of those functions, here is a little living Swift utility file I've been using:
import Foundation
import UIKit
typealias completionBlock = () -> ()
extension Array {
func contains(#object:AnyObject) -> Bool {
return self.bridgeToObjectiveC().containsObject(object)
}
func indexOf(#object:AnyObject) -> Int {
return self.bridgeToObjectiveC().indexOfObject(object)
}
mutating func moveObjectAtIndex(fromIndex: Int, toIndex: Int) {
if ((fromIndex == toIndex) || (fromIndex > self.count) ||
(toIndex > self.count)) {
return
}
// Get object being moved so it can be re-inserted
let object = self[fromIndex]
// Remove object from array
self.removeAtIndex(fromIndex)
// Insert object in array at new location
self.insert(object, atIndex: toIndex)
}
}
func delayOnMainQueueFor(numberOfSeconds delay:Double, action closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue()) {
closure()
}
}
In swift, you can create a singleton class following way:
class AppSingleton: NSObject {
//Shared instance of class
static let sharedInstance = AppSingleton()
override init() {
super.init()
}
}
I prefer this implementation:
class APIClient {
}
var sharedAPIClient: APIClient = {
return APIClient()
}()
extension APIClient {
class func sharedClient() -> APIClient {
return sharedAPIClient
}
}
My way of implementation in Swift...
ConfigurationManager.swift
import Foundation
let ConfigurationManagerSharedInstance = ConfigurationManager()
class ConfigurationManager : NSObject {
var globalDic: NSMutableDictionary = NSMutableDictionary()
class var sharedInstance:ConfigurationManager {
return ConfigurationManagerSharedInstance
}
init() {
super.init()
println ("Config Init been Initiated, this will be called only onece irrespective of many calls")
}
Access the globalDic from any screen of the application by the below.
Read:
println(ConfigurationManager.sharedInstance.globalDic)
Write:
ConfigurationManager.sharedInstance.globalDic = tmpDic // tmpDict is any value that to be shared among the application
The only right approach is below.
final class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code if anything
return instance
}()
private init() {}
}
To Access
let signleton = Singleton.sharedInstance
Reasons:
static type property is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously, so no need of using dispatch_once
Privatising the init method so instance can't be created by other classes.
final class as you do not want other classes to inherit Singleton class.
After seeing David's implementation, it seems like there is no need to have a singleton class function instanceMethod since let is doing pretty much the same thing as a sharedInstance class method. All you need to do is declare it as a global constant and that would be it.
let gScopeManagerSharedInstance = ScopeManager()
class ScopeManager {
// No need for a class method to return the shared instance. Use the gScopeManagerSharedInstance directly.
}
func init() -> ClassA {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : ClassA? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = ClassA()
}
return Static.instance!
}
Swift to realize singleton in the past, is nothing more than the three ways: global variables, internal variables and dispatch_once ways.
Here are two good singleton.(note: no matter what kind of writing will must pay attention to the init () method of privatisation.Because in Swift, all the object's constructor default is public, needs to be rewritten init can be turned into private, prevent other objects of this class '()' by default initialization method to create the object.)
Method 1:
class AppManager {
private static let _sharedInstance = AppManager()
class func getSharedInstance() -> AppManager {
return _sharedInstance
}
private init() {} // Privatizing the init method
}
// How to use?
AppManager.getSharedInstance()
Method 2:
class AppManager {
static let sharedInstance = AppManager()
private init() {} // Privatizing the init method
}
// How to use?
AppManager.sharedInstance
Swift 5.2
You can point to the type with Self. So:
static let shared = Self()
And should be inside a type, like:
class SomeTypeWithASingletonInstance {
static let shared = Self()
}
This is the simplest one with thread safe capabilities. No other thread can access the same singleton object even if they want. Swift 3/4
struct DataService {
private static var _instance : DataService?
private init() {} //cannot initialise from outer class
public static var instance : DataService {
get {
if _instance == nil {
DispatchQueue.global().sync(flags: .barrier) {
if _instance == nil {
_instance = DataService()
}
}
}
return _instance!
}
}
}
I required my singleton to allow inheritance, and none of these solutions actually allowed it. So I came up with this:
public class Singleton {
private static var sharedInstanceVar = Singleton()
public class func sharedInstance() -> Singleton {
return sharedInstanceVar
}
}
public class SubSingleton: Singleton {
private static var sharedInstanceToken: dispatch_once_t = 0
public class override func sharedInstance() -> SubSingleton {
dispatch_once(&sharedInstanceToken) {
sharedInstanceVar = SubSingleton()
}
return sharedInstanceVar as! SubSingleton
}
}
This way when doing Singleton.sharedInstance() first it will return the instance of Singleton
When doing SubSingleton.sharedInstance() first it will return the instance of SubSingleton created.
If the above is done, then SubSingleton.sharedInstance() is Singleton is true and the same instance is used.
The issue with this first dirty approach is that I cannot guarantee that subclasses would implement the dispatch_once_t and make sure that sharedInstanceVar is only modified once per class.
I will try to refine this further, but it would be interesting to see if anyone has strong feelings against this (besides the fact that it is verbose and requires to manually update it).
This is my implementation. It also prevents the programmer from creating a new instance:
let TEST = Test()
class Test {
private init() {
// This is a private (!) constructor
}
}
I use the following syntax:
public final class Singleton {
private class func sharedInstance() -> Singleton {
struct Static {
//Singleton instance.
static let sharedInstance = Singleton()
}
return Static.sharedInstance
}
private init() { }
class var instance: Singleton {
return sharedInstance()
}
}
This works from Swift 1.2 up to 4, and has several advantages:
Reminds the user not to subclass implementation
Prevents creation of additional instances
Ensures lazy creation and unique instantiation
Shortens syntax (avoids ()) by allowing to access instance as Singleton.instance

Resources