In this post, it is very nicely explained how Singletons should be implemented in Swift, essentially it can be done with two lines:
class TheOneAndOnlyKraken {
static let sharedInstance = TheOneAndOnlyKraken()
private init() {} //This prevents others from using the default '()' initializer for this class.
}
However, what happens if my Singleton is supposed to be initalised with some data? Maybe it needs to encapsulate an API Key or other data that it can only receive from the outside. An example could look as follows:
class TheOneAndOnlyKraken {
let secretKey: String
static let sharedInstance = TheOneAndOnlyKraken()
private init() {} //This prevents others from using the default '()' initializer for this class.
}
In that situation, we can't make the initializer private because we will have to create an initializer that takes a String as an argument to satisfy the compiler:
init(secretKey: String) {
self.secretKey = secretKey
}
How can that be saved and we still make sure that we have a thread-safe instantiation of the singleton? Is there a way how we can avoid using dispatch_once or would we have to essentially default back to the Objective-C way where we use dispatch_once to make sure that the initializer indeed only gets called once?
First, note that the ObjC way you're implying is not thread-correct. It may be "safe" in that it doesn't crash and does not generate undefined behavior, but it silently ignores subsequent initializations with differing configuration. That is not expected behavior. Readers that are known to occur after the write will not receive the written data. That fails consistency. So put aside theories that such a pattern was correct.
So what would be correct? Correct would be something like this:
import Dispatch
class TheOneAndOnlyKraken {
static let sharedInstanceQueue: DispatchQueue = {
let queue = DispatchQueue(label: "kraken")
queue.suspend()
return queue
}()
private static var _sharedInstance: TheOneAndOnlyKraken! = nil
static var sharedInstance: TheOneAndOnlyKraken {
var result: TheOneAndOnlyKraken!
sharedInstanceQueue.sync {
result = _sharedInstance
}
return result
}
// until this is called, all readers will block
static func initialize(withSecret secretKey: String) {
// It is a programming error to call this twice. If you want to be able to change
// it, you'll need another queue at least.
precondition(_sharedInstance == nil)
_sharedInstance = TheOneAndOnlyKraken(secretKey: secretKey)
sharedInstanceQueue.resume()
}
private var secretKey: String
private init(secretKey: String) {
self.secretKey = secretKey
}
}
This requires a single explicit call to TheOneAndOnlyKraken.intialize(withSecret:). Until someone makes that call, all requests for sharedInstance will block. A second call to initialize will crash.
Related
TL;DR
I have a class with no public initializers or instances that passes an instance of itself to a closure in another class. It does this through a mirror of the other class. When I go to access that instance from within the closure, I'm getting a EXC_BAD_ACCESS error, but other parameters passed to the closure are clearly accessible and do not result in a bad access error. I have no idea why. See code below for replication in a new project or a playground.
Detailed Explanation
I've been trying to figure out a way to implement class-specific access control, where multiple specific classes have sole access to another class containing variables and functions to be shared between them. All other classes would not have such access. Kind of like a static class, or a Singleton pattern, but with specific, class-named access control.
I thought I had something that would actually work in pure swift, (which is nice for me since I don't know Objective-C, and only started on swift about 16 months ago.) It's done in an almost anti-swift manner, so just bear with me - my goal is to start with something functional and move it towards elegance and beauty from there.
Even though I'm reasonably confident it should all work, I'm encountering a EXC_BAD_ACCESS error in a very unexpected place.
The "class-specific private" class that you are not allowed to access an instance of unless you are on its "okay" list, we can call the Restricted class.
The class(es) that is(are) allowed access to the Restricted class we can call the Accessor class(es).
The programmer must tell the Restricted class to call a function from the Accessor, and "drop in" an instance of the Restricted class by passing it as a parameter to that function. You do this by passing in the name of the function to be called, an instance of the Accessor class on which to call said function, and any parameters that the function would need in addition to the Restricted class instance.
I could make an enormous switch in the Restricted class, each case of which properly calls each function indicated on each of the Accessor classes...but to get around that excessive overhead/setup, I have the name of the function to be called on the Accessor classes passed in as a string, and accessed through a mirror. Since mirrors only reflect properties and not functions, the function must be a property with an assigned closure, instead of a traditional function.
We can call these closures DropClosures, since their purpose is to have the shared, Restricted class dropped into them. In fact we could call this whole pattern the "DropClosure Pattern". (Or maybe anti-pattern, I know it's kind of gruesome as-is.)
The properties of the "shared" instance of the Restricted class are stored internally as a private static dict (as json, basically). To generate an actual instance of itself, the Restricted class uses a private initializer that accepts that dict as a parameter. After a DropClosure runs with said initialized instance, the Restricted class uses a Mirror of that instance to store any changes back in the "shared" dict, and the instance will go out of scope unless a reference is made to it. So after each DropClosure completes its run, the instance passed to it is more or less useless as a representation of the "shared" aspect of the class, intentionally so.
I only do this because there is no way to require that all references to a certain weak reference also be weak. I don't want a class with access to the weak reference to assign a strong reference to the same instance and keep it in memory, that would defeat the access control goal by allowing the instance to be shared outside of its access scope. Since I can't force the instance to expire once the closure has completed, the next best thing is to remove the motivation for doing so by making the object no longer connected to the shared source after the closure completes.
This all theoretically works, and will compile, and will not throw any swift exceptions when run.
The Accessor (or any class that has an instance of an Accessor) calls RestrictedClass.run(), the run code validates the Accessor instance, finds the DropClosure in that instance, and passes in an instance of the Restricted class to that closure.
However, whenever I try to access that instance from within the DropClosure, it gives me the aforementioned bad access error, seemingly on a C or Objective-C level.
As far as I can tell, the instance should be accessible at this point, and none of the variables being used should be dropping out of scope yet.
At this point I'm totally spitballing - is it possible that there is something in the background that prevents a class with no public initializers from being passed through a mirror? Does it have to do with passing it into a closure called from that mirror? Is there some kind of hidden weak reference that's making the instance get ARC'd?
Please note that I've tried discarding the "weak" wrapper object and only passing in the Restricted instance to the closure, and I get the same bad access error. The error is independent of the instance being weakly referenced.
Code:
import Foundation
typealias DropClosureVoid<T: AnyObject & AccessRestricted> = (_ weaklyConnectedInterface: WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Void
typealias DropClosureAny<T: AnyObject & AccessRestricted> = (_ weaklyConnectedInterface: WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Any?
enum AccessError : Error {
case InvalidFunction
case InvalidAccessClass
}
protocol AccessRestricted {
static func run<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws
static func runAndReturn<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws -> Any?
}
///This class contains an instance that should be expected to only temporarily represent the original, even if a strong reference is made that keeps the value in scope.
class WeaklyConnectedInterface<T:AnyObject> {
weak var value:T?
init(_ value: T) {
self.value = value
}
}
class Accessor {
let restrictedClassPassable:DropClosureVoid<RestrictedAccessClass> = { weaklyConnectedInterface, parameters in
print(weaklyConnectedInterface) // **EXC_BAD_ACCESS error here**
//note that the error above happens even if I pass in the instance directly, without the WeaklyConnectedInterface wrapper.
//It's clearly an issue that occurs when trying to access the instance, whether the instance is wrapped in a the class that makes a weak reference to it or not, which means that it is inaccessible even when strongly referenced.
if let parameterDict = parameters as? [String:String] {
print(parameterDict["paramkey"] ?? "nil")
print(weaklyConnectedInterface)
weaklyConnectedInterface.value?.restrictedVariable = "I've changed the restricted variable"
}
}
let anotherRestrictedClassPassable:DropClosureAny<RestrictedAccessClass> = { weaklyConnectedInterface, parameters in
if let parameterDict = parameters as? [String:String] {
print(parameterDict["paramkey"] ?? "nil")
print(weaklyConnectedInterface.value?.restrictedVariable as Any)
return weaklyConnectedInterface.value?.restrictedVariable
}
return nil
}
func runRestrictedClassPassable() throws {
let functionName = "restrictedClassPassable"
print("trying validateClosureName(functionName)")
try validateClosureName(functionName)//this is in case you refactor/change the function name and the "constant" above is no longer valid
print("trying RestrictedAccessClass.run")
try RestrictedAccessClass.run(functionName, in: self, with: ["paramkey":"paramvalue"])
let returningFunctionName = "anotherRestrictedClassPassable"
print("trying validateClosureName(returningFunctionName)")
try validateClosureName(returningFunctionName)
print("trying RestrictedAccessClass.runAndReturn")
let result = (try RestrictedAccessClass.runAndReturn(returningFunctionName, in: self, with: ["paramkey":"ParamValueChanged"]) as! String?) ?? "NIL, something went wrong"
print("result is \(result)")
}
func validateClosureName(_ name:String) throws {
let mirror = Mirror(reflecting: self)
var functionNameIsPresent = false
for child in mirror.children {
if child.label != nil && child.label! == name {
functionNameIsPresent = true
break
}
}
guard functionNameIsPresent else {
print("invalid function")
throw AccessError.InvalidFunction
}
}
}
extension Mirror {
func getChildrenDict() -> [String:Any]
{
var dict = [String:Any]()
for child in children
{
if let name = child.label
{
dict[name] = child.value
}
}
return dict
}
}
class RestrictedAccessClass:AccessRestricted {
private static var shared:[String:Any] = [
"restrictedVariable" : "You can't access me!"
]
private static func validateType<T>(of classObject:T) throws {
switch classObject {
case is Accessor:
return
default:
print("Invalid access class")
throw AccessError.InvalidAccessClass
}
}
var restrictedVariable:String
private init() {
restrictedVariable = "You can't access me!"
}
private init(from json:[String:Any]) {
restrictedVariable = json["restrictedVariable"] as! String
}
static func run<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws {
print("trying validateType(of: classObject) in run")
try validateType(of: classObject)
for child in Mirror(reflecting: classObject).children {
if let childName = child.label {
if childName == closureName {
let dropClosure = child.value as! DropClosureVoid<RestrictedAccessClass>
let selfInstance = RestrictedAccessClass(from:shared)
let interface = WeaklyConnectedInterface(selfInstance)
dropClosure(interface, parameters)
runCleanup(on: selfInstance)//parses any data changed by the end of the drop closure back into the dict for use in future instances. This means you mustn't try using the instance in an async closure. The correct way to do this would be to call run inside of an async closure, rather than putting an anync closure inside of the drop closure.
_ = interface.value
return
}
}
}
}
static func runAndReturn<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws -> Any? {
print("trying validateType(of: classObject) in runAndReturn")
try validateType(of: classObject)
for child in Mirror(reflecting: classObject).children {
if let childName = child.label {
if childName == closureName {
let dropClosure = child.value as! DropClosureAny<RestrictedAccessClass>
let selfInstance = RestrictedAccessClass(from:shared)
let interface = WeaklyConnectedInterface(selfInstance)
let result = dropClosure(interface, parameters)
runCleanup(on: selfInstance)//parses any data changed by the end of the drop closure back into the dict for use in future instances. This means you mustn't try using the instance in an async closure. The correct way to do this would be to call run inside of an async closure, rather than putting an anync closure inside of the drop closure.
_ = interface.value
return result
}
}
}
return nil
}
private static func runCleanup(on instance:RestrictedAccessClass) {
shared = Mirror(reflecting:instance).getChildrenDict()
//once this function goes out of scope(or shortly thereafter), the instance passed will become useless as a shared resource
}
}
Code to encounter error:
I just put this in a new project's AppDelegate.application(didFinishLaunching). You can put all of the code above and below, in order, in a playground and it will break in the same spot, but not as clearly.
let accessor = Accessor()
do {
try accessor.runRestrictedClassPassable()
}
catch {
print(error.localizedDescription)
}
Updates
Whether zombie objects are turned on or off, I'm getting the same error message from Xcode: Thread 1: EXC_BAD_ACCESS (code=1, address=0x1a1ebac696e)
Running an analysis with Command+Shift+B reveals no warnings.
Running with all of the malloc options enabled reveals the following error:
Thread 1: signal SIGABRT, objc[somenumber]: Attempt to use unknown class 0xSomevalue
This just got weird...
Apparently, the "unknown class" is the project. I found this out by selecting the (i) bubble on the inline object inspector for the Restricted instance that was causing the crash. It gives me the following message:
Printing description of weaklyConnectedInterface:
expression produced error: error:
/var/folders/zq/_x931v493_vbyhrfc25z1yd80000gn/T/expr52-223aa0..swift:1:65:
error: use of undeclared type 'TestProject'
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<TestProject.RestrictedAccessClass>(bitPattern: 0x103450690)!.pointee)
^~~~~~~~~~~
I thought that maybe this would happen for other classes, so I tested, and it's able to access other project-level classes just fine. Only for this specific instance is the project "namespace" undefined.
Please find below required modifications (not many)... Tested with Xcode 11.2 / iOS 13.2.
1) made interface inout to pass it as-is original, otherwise it somehow copied loosing type information
typealias DropClosureVoid<T: AnyObject & AccessRestricted> =
(_ weaklyConnectedInterface: inout WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Void
typealias DropClosureAny<T: AnyObject & AccessRestricted> =
(_ weaklyConnectedInterface: inout WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Any?
2) fix places of usage (same in two places)
var interface = WeaklyConnectedInterface(selfInstance) // made var
dropClosure(&interface, parameters) // << copy closure args here was a reason of crash
3) ... and that's it - build & run & output
Note: I would recommend to avoid force unwrap and use the following
if let dropClosure = child.value as? DropClosureVoid<RestrictedAccessClass> {
dropClosure(&interface, parameters)
}
I learned from Using Swift with Cocoa and Objective-C that a singleton can be created like this:
class Singleton {
static let sharedInstance = Singleton()
}
But as I learned, we should also prevent an instance created from the constructor. Creating an instance of the class Singleton outside the class scope, like the statement below, should be prevented:
let inst = Singleton()
So, could I do just like this:
class Singleton {
static let sharedInstance = Singleton()
private init() {}
}
Or, is there any better practice?
The way that you have suggested is the way that I always implemented it.
public class Singleton
{
static public let sharedInstance = Singleton();
private init()
{
}
}
It's the cleanest solution for a Singleton pattern that I've ever found. Now that in Swift 2 you can specify accessibility it does actually prevent you from calling something like:
var mySingleton = Singleton();
Doing so results in a compile time error:
'Singleton' cannot be constructed because it has no accessible initializers
private let singletonInstance = Singleton()
final class Singleton: NSObject {
static func getInstance() -> Singleton {
return singletonInstance
}
}
Try that. Nothing is wrong in using global object here, it is created lazily (on first call).
Please help me with Swift,
I need singleton with can inheritance.
I can do like this
class A {
var defaultPort: Int
required init() {
self.defaultPort = 404
}
class var defaultClient: A {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return Static.instance!
}
}
but in swift 2.0 we can do like this
static let defaultClient = A() //self.init()
but it creates an instance of the class A any way.
How i can use like this self.init()
static let defaultClient = self.init()
in order to be able to inherit
UPD
best way for now
class A {
class func defaultClient() -> Self {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return instance(Static.instance, asType: self)
}
}
here we need helper as
func instance<T>(instance: Any, asType type: T.Type) -> T {
let reurnValue = instance as! T
return reurnValue
}
because another way cast A to Self not exist, for now.
p.s. crazy swift way!
why i can not do instance as! Self
Your question isn't very clear. You're looking for something like the class constant solution posted in this answer, but which automatically uses "my own class" instead of explicitly creating an instance of a specific class... right?
That is, you want to turn this:
class Singleton {
static let sharedInstance = Singleton()
}
into this:
class Singleton {
static let sharedInstance = SomeMagicThing()
}
class SingletonSubclass {}
where SomeMagicThing automatically creates a Singleton instance when you call Singleton.sharedInstance, and a SingletonSubclass instance when you call SingletonSubclass.sharedInstance. Correct?
Sorry, that can't be done (as of Swift 2.1).
Part of your issue is that static and class mean two different things. The static modifier means that the declaration it modifies is associated only with a specific type declaration. So, the Singleton type owns a pointer to a specific object -- its subclasses don't inherit that pointer. (And if they did, would it point to the same object or a subclass-specific one?)
If you could create a class var or class let, that'd (in theory) give you the kind of dispatch/inheritance you want. But trying that gives you an error (emphasis mine):
class stored properties not yet supported in classes; did you mean static?
So it sounds like this sort of thing might show up someday.
Of course, the other side of the problem is finding a way to dynamically refer to the "current" type responsible for executing some statement. In the context of an instance method, you have self.dynamicType for such things... but there's no equivalent for classes. (Self is a type constraint, not an actual type.) This is a side effect of the type system in Swift being much more strict and static than that of Objective-C (for example, metatypes aren't just a special flavor of otherwise normal objects). File a bug if you'd like to see a change to that effect?
New to IOS programming but just wondering where is the best place to put functions that I would use throughout my code. For example, I want to write a few functions to perform a POST request to a web service and return a dictionary. Maybe another function to do some calculations. Is it best to create another .swift file and put all my functions there. And what would be a good name to give the file if so?
public func postRequest() -> [String:String] {
// do a post request and return post data
return ["someData" : "someData"]
}
The best way is to create a helper class with static functions, like this:
class Helper{
static func postRequest() -> [String:String] {
// do a post request and return post data
return ["someData" : "someData"]
}
}
Now every time you need to use postRequest you can just use like so: Helper.postRequest()
I usually create a separate class if I have functions that will be used by multiple classes, especially for the ones involving network operations.
If you just have separate functions that will be used, you can simply create static functions inside that class so it is easily accessible by other classes in a static way:
class DataController {
static func getData() -> [String:String] {
// do some operations
return ["someData" : "someData"]
}
}
let data = DataController.getData() // example
However, what often has been the case for me (especially if it involves more complicated operations) was that these network operations needed to establish an initial connection beforehand or required some initial setups, and they also performed asynchronous operations that needed to be controlled. If this is the case and you will often be calling such methods, you might want to create a singleton object that you could use throughout different classes and functions. This way, you could do the initial setup or establish an initial connection just once, and then do the rest as needed with the other functions, instead of doing them every time the function gets called.
Creating a singleton object is pretty simple in Swift:
class DataController {
static let sharedInstance = DataController() // singleton object
init() {
// do initial setup or establish an initial connection
}
func getData() -> [String:String] {
// do some operations
return ["someData" : "someData"]
}
}
let data = DataController.sharedInstance.getData() // example
For the name of the class, I usually name it something like DataController or DataHelper, but anything that makes sense as a "helper" class would work.
Hope this helps :)
For reusable functions it depends what I decide to use. For this specific case I use a separate file, because posting to a backend will become more complicated when the application evolves. In my app I use a backend class, with all kinds of helper classes:
struct BackendError {
var message : String
}
struct SuccessCall {
var json : JSON
var containsError : Bool {
if let error = json["error"].string {
return true
}
else {
return false
}
}
}
typealias FailureBlock = (BackendError) -> Void
typealias SuccessBlock = (SuccessCall) -> Void
typealias AlamoFireRequest = (path: String, method: Alamofire.Method, data: [String:String]) -> Request
typealias GetFunction = (path: String , data: [String : String], failureBlock: FailureBlock, successBlock: SuccessBlock) -> Void
class Backend {
func getRequestToBackend (token: String )(path: String , data: [String : String], failureBlock: FailureBlock, successBlock:
}
For other cases I often use extensions on Swift classes. Like for getting a random element from an Array.
extension Array {
func sampleItem() -> T {
let index = Int(arc4random_uniform(UInt32(self.count)))
return self[index]
}
}
This very old question but I would like to chirp some more points.
There are a few option, basically you can write your utility functions in Swift -
A class with static function. For example
class CommonUtility {
static func someTask() {
}
}
// uses
CommonUtility.someTask()
Also, you can have class method's as well instead of static method but those functions can be overridden by subclasses unlike static functions.
class CommonUtility {
class func someTask() {
}
}
// uses
CommonUtility.someTask()
Secondly, you can have Global functions as well, that are not part of any class and can be access anywhere from your app just by name.
func someTask() {
}
Though, selecting one over other is very subjective and I thing this is ok to make a class with static function in this particular case, where you need to achieve networking functionality but if you have some functions which perform only one task than Global function is a way to go because Global functions are more modular and separate out single tasks for a single function.
In case of static functions, if we access one of the static member, entire class gets loaded in memory. But in case of global function, only that particular function will be loaded in mem
You can create a separate swift class, might name it WebServicesManager.swift, and write all methods related to web requests in it.
You can use class methods, or singleton pattern to access the methods.
I have the following class:
class FeedDataManager: URLManagerdelegate {
let TAG: String = "FeedDataManager"
weak var mDelegate: KeyboardViewController?
var mModelManager: ModelManager!
var mURLManager: UrlManager!
var mGetNewsTimer: NSTimer?
var mFeedsArray: Array<News>!
var mManagedObjectContext: NSManagedObjectContext!
var mPersistentStoreCoordinator: NSPersistentStoreCoordinator!
var mManagedObjectModel: NSManagedObjectModel!
class var sharedInstance: FeedDataManager {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: FeedDataManager? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = FeedDataManager()
}
return Static.instance!
}
init (aDelegate: KeyboardViewController) {
self.mDelegate = aDelegate
}
}
The Problem: If you look at the init method you will see that it should receive as a parameter a delegate pointer that I want to store in the singleton, so basically I need to pass this parameter to this line:
Static.instance = FeedDataManager()
But I have no idea how it's done, Does any knows how this can be done?
BTW: I saw this link:
Singleton and init with parameter
But the singleton creation there is different.
We can show you how you can add parameter to declaration of singleton, but that's not really a good idea. The entire idea behind a singleton is that it doesn't matter where it is instantiated, you can use it anywhere. What does it mean if you invoked this singleton in two different places in your code, with different parameters? You have a race condition, where the behavior may change depending upon where and how the singleton was first encountered.
Unrelated, but the dispatch_once is redundant. The static variables are already employed with dispatch_once. See discussion at end of http://developer.apple.com/swift/blog/?id=7 (this is primarily geared towards globals, but as they parenthetically point out, it applies to static variables, too). Also, in Swift 1.2, we can now have static class variables, eliminating the need for the struct, too