How can remove all variables value from one place when I logout from the application? Like for NSUserDefaults we use below code:
/*===CLEAR ALL NSUSERDEFAULTS====*/
let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
create a class which consist of all the properties of the loggedin user(that you want to clear at the time of logout)
and best way is to create shared instance using dispatch once and than when you need to reset the properties just reset the dispatch onceToken
here is the sample code in objective C
static dispatch_once_t onceToken;
+ (id)sharedInstance
{
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
+ (void)clearMemberInfo
{
// [[NSNotificationCenter defaultCenter] removeObserver:self];
//instance = nil;
onceToken = 0;
}
From a design point, create a class that handles all settings - e.g. I have XUPreferences in my projects and store all settings there in one place (generally a class that has various variables that delegate their values to NSUserDefaults). Aside from not having various defaults key floating around the namespace, you have a nice overview of everything the app is setting.
On this class, you can have a func clearAllPreferences() method, which may (various options):
you can try using the resetStandardUserDefaults() class method on NSUserDefaults
enumerate all the defaults keys you have and call the removeObjectForKey: method on NSUserDefaults
if you prefix your keys (e.g. I prefix all my defaults keys with XU), you can do this automatically by going through the keys in NSUserDefaults.standardUserDefaults().dictionaryRepresentation() and matching those against your prefix.
use suites - see the designated initializer - pass in extra suite name, and then you can call func removeSuiteNamed() on NSUserDefaults - which is probably the best way, since it allows you to distinguish between session-related and non-session-related settings and wipe just the session-related ones.
EDIT:
/// Key in defaults for myOption
private let XUMyOptionDefaultsKey = "XUMyOption"
public class XUPreferences {
/// Shared instance
public static var sharedPreferences = XUPreferences()
/// Your option, purely based on the values in NSUserDefaults.
public var myOption: Bool {
get {
return NSUserDefaults.standardUserDefaults().boolForKey(XUMyOptionDefaultsKey)
}
set {
NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: XUMyOptionDefaultsKey)
}
}
/// Clears preferences.
public func clearPreferences1() {
let defaults = NSUserDefaults.standardUserDefaults()
for (key, _) in defaults.dictionaryRepresentation() {
// All keys are prefixed with XU
if key.hasPrefix("XU") {
defaults.removeObjectForKey(key)
}
}
}
/// Clears preferences another way
public func clearPreferences2() {
let defaults = NSUserDefaults.standardUserDefaults()
for key in [ XUMyOptionDefaultsKey /**, all keys for your options go here. */ ] {
defaults.removeObjectForKey(key)
}
}
}
// Usage:
// x is now false (most likely)
var x = XUPreferences.sharedPreferences.myOption
// Change the option to true
XUPreferences.sharedPreferences.myOption = true
XUPreferences.sharedPreferences.clearPreferences1()
// False again, since we've cleared the preferences.
x = XUPreferences.sharedPreferences.myOption
Related
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.
I am trying to use a singleton for Core Data. Previously, I've been successfully able to do it by creating a class CoreDataStack.h/.m, calling the default stack method below, and its respective managed object context, in Objective-C, and works very well:
//RETURNS CoreDataStack
+ (instancetype)defaultStack {
static CoreDataStack *defaultStack;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defaultStack = [[self alloc]init];
});
return defaultStack;
}
However, I am using a Swift project, and I've been struggling to convert this into the latest Swift syntax. How would I go about creating this? This is my attempt so far:
class func defaultStack() -> Self {
var defaultStack: CoreDataStack
var onceToken: dispatch_once_t = 0
dispatch_once(&onceToken) {
defaultStack = self.init()
}
return defaultStack
}
and my Xcode generated error:
To create a singleton, use Krakendev's single-line singleton code:
class CoreDataStack {
// Here you declare all your properties
static let sharedInstance = User()
private init() {
// If you have something to do at the initialization stage
// you can add it here. It will only be called once. Guaranteed.
}
// Add the rest of your methods here
}
You will call your methods and properties as CoreDataStack.sharedInstance().property and CoreDataStack.sharedInstance().method(). I recommend using something shorter instead of sharedInstance, like service.
This solution applies in general, not only in your Core Data case.
I've defined a global struct with static properties with values I use in many of my view controllers, like this:
public struct AppGlobal {
static var currentUser = UserModel()
static let someManager = SomeManager()
// Prevent others from initializing
private init() { }
}
Then in my UIViewController, I can do something like this:
class MyController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
AppGlobal.currentUser.prop1 = "abc123"
AppGlobal.someManager.startUpdating()
}
}
This is obviously very convenient, but smells really bad. I believe dependency injection would come in handy here, but not sure how. Is there a more elegant alternative to creating the AppGlobal singleton properties?
I can't see why you need to access userModel or someManager through a global state (and yes — Singletons are just that).
Why not just set it where you need it?
"Dependency Injection" is a 25-dollar term for a 5-cent concept.
That's not to say that it's a bad term…
[…]
Dependency injection means
giving an object its instance variables. Really. That's it.
– James Shore: Dependency Injection Demystified
Either do it during constructing
class C {
let currentUser: UserModel
let someManager: SomeManager
init(currentUser:UserModel, someManger:SomeManager) {
self.currentUser = currentUser
self.someManager = someManager
}
}
or through properties. If you need to make sure that all properties are set, do something like this:
class MyController: UIViewController {
var currentUser: UserModel? {
didSet{
self.configureIfPossible()
}
}
var someManager: SomeManager?{
didSet{
self.configureIfPossible()
}
}
func configureIfPossible(){
if let currentUser = self.currentUser, someManager = self.someManager {
// configure
}
}
}
In my current project we have the policy that every dependency must be visible and configurable from outside the class.
An example:
class LibrarySegmentViewController: BaseContentViewController {
var userDefaults: NSUserDefaults?
var previousSorting : LibrarySortingOrder = .AZ
var sorting : LibrarySortingOrder {
set{
self.previousSorting = sorting
if let filterMode = self.filterMode {
self.userDefaults?.setInteger(newValue.rawValue, forKey: "\(filterMode)_LibrarySorting")
}
self.setupIfReady()
}
get{
if let filterMode = self.filterMode {
if let s = LibrarySortingOrder(rawValue: self.userDefaults!.integerForKey("\(filterMode)_LibrarySorting")) {
return s
}
}
return .Date
}
}
}
So as you can see, we even use properties to reference NSUserDefaults.standardUserDefaults(). We do this as we can pass in fresh instances during testing, without bigger mocking hassle.
And this is the most importing reason why not to use singletons directly: The dependencies are hidden and might bite you during testing and refactoring. Another example would be an API client singleton that is hidden in the code and performs unwanted networking requests during testing. If it is set from outside of the tested class you can just pass in a mocked networking client that does not perform any requests but returns test data.
So even if you use singletons, you should pass it in as a dependencies.
If this question is about global or not, you should see this thread :
What is so bad about singletons?
But if you want a better design for your implementation of a singleton you can try something like this :
class SingletonExample: NSObject {
static let sharedInstance: SingletonExample()
}
class OtherSingletonExample: NSObject {
static let sharedInstance: OtherSingletonExample()
}
Then you can use SingletonExample.sharedInstance and OtherSingletonExample.sharedInstance anywhere in your code.
The idea is to isolate one singleton from another and access it as a class attribute instead of creating a big global struct for anything.
I have written a helper struct for saving and loading stuff to NSUserDefaults.
import UIKit
struct Database {
static let defaults = NSUserDefaults.standardUserDefaults()
static var myVariable: AnyObject?
static func save() {
defaults.setObject(myVariable, forKey: "myVariable")
}
static func load() {
if let myVariable = defaults.objectForKey("myVariable") {
self.myVariable = myVariable
}
}
static func clear() {
defaults.removeObjectForKey("myVariable")
}
}
Now I can simply use Database.load() to load myVariable from NSUSerDefaults.
However, the same is achievable with this code:
struct Database2 {
static var sharedInstance = Database()
let defaults = NSUserDefaults.standardUserDefaults()
var myVariable: AnyObject?
func save() {
defaults.setObject(myVariable, forKey: "myVariable")
}
func load() {
if let myVariable = defaults.objectForKey("myVariable") {
self.myVariable = myVariable
}
}
func clear() {
defaults.removeObjectForKey("myVariable")
}
}
Now I would use Database2.sharedInstance.load().
Which one is seen as a better practice and why? What's the use of a sharedInstance, if I can do everything I want with the static declaration?
A shared instance is recommendable, at least for the following reasons:
class methods make unit testing harder
you need class instances for dependency injection
if later on you decide that a non-singleton is more suitable - e.g. you decide to have two persistence storages for "myVariable", then you're stuck
and not lastly, class members live in the global space, and we should avoid using globals
The real question you should ask, is if you really need a singleton (with or without a shared instance) for your problem. If the only reason to have a singleton is ease-of-access, then you don't really need a singleton.
P.S. There is a very good article on objc.io about singletons, and although it was written for Objective-C, many concepts from there apply in Swift too.
// with singleton pattern, there exist only one copy of the object
// sigleton pattern can be applied for reference type only
// let st1 = Singleton(); let st2 = Sigleton(); st1 === st2
// in your example, S is value type. All instances of S share only type properties, here only i
struct S {
static var i: Int = 100
var j: Int
func foo() {
//print(i) // error: static member 'i' cannot be used on instance of type 'S'
print(S.i)
}
init(_ j: Int) {
self.j = j
}
}
var s1 = S(1)
var s2 = S(2)
//s1.i // error: static member 'i' cannot be used on instance of type 'S'
S.i // 100
s1.foo() // 100
s1.j // 1
s2.foo() // 100
s2.j // 2
S.i = 200
s1.foo() // 200
s2.foo() // 200
by the way, this (your) approach can be very useful and could be preferred in some situations.
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?