The use of singleton class in objective c and swift - ios

I have a project implemented in both Objective C and Swift classes and I need to have global variables to be shared among these classes .
I have two variables currentUsername and currentUsernumber , I need to use these two in each view in the project, what is the best way to implement that ?
I have tried to implement singleton class and here is my code :
class curentUserSingleton {
static var instance: curentUserSingleton!
var currentUsername: String = ""
var currentUsernumber: String = ""
// SHARED INSTANCE
class func sharedInstance(Name : String , Number : String) -> curentUserSingleton {
self.instance = (self.instance ?? curentUserSingleton(uName: Name , uNumber: Number))
return self.instance
}
// METHODS
init(uName : String , uNumber : String) {
self.currentUsername = uName
self.currentUsernumber = uNumber
}}
But I don't know how to use this class safely in the OC and Swift and I am a little confused since I get declaration errors when I use the class in my code!
Is this the right way to write a singleton class and how to call it in both languages ?

I'd be inclined to do something like:
class User: NSObject {
static let sharedInstance = User()
var name: String?
var number: String?
}
Then you can set and retrieve name and number like so in Swift:
User.sharedInstance.name = "Foo"
User.sharedInstance.number = "42"
print(User.sharedInstance.name)
print(User.sharedInstance.number)
Obviously, to access this from Objective-C .m file, you have to have to include the system generated header like so:
#import "ModuleName-Swift.h" // obviously, replace `ModuleName` with the name of your module
But then the syntax for setting and retrieving these properties is similar as it was in Swift:
[User sharedInstance].name = #"Foo";
[User sharedInstance].number = #"42";
NSLog(#"%#", [User sharedInstance].name);
NSLog(#"%#", [User sharedInstance].number);

To me it seems you do not need a singleton at all. I suggest you would be best of redesigning the architecture to have a user class that can store the information you are needing (and more if you finds the need in the future).
Then you could either pass that user object around between the view controllers as they need or perhaps easier define a currentUser property for the app delegate class.
That way each view controller can obtain the app delegate from the NSApp global reference to the application object and then get the current user object from there. With this pattern the app delegate acts as the globally accessible singleton you need without any need to manage it yourself.

Related

How to create Singleton in generic class using swift 4.2?

I have been trying to convert a singleton class to generic. Since swift doesn't support stored property in generic class Singleton could not be implemented. I tried all the possible solutions that I know but nothing works. Other Stackoverflow answers related to this topic doesn't help either. Can someone help me to get on the right path, please? Thanks in advance.
I have added the sample code below.
class SingleTonClass<T: Equatable & RawRepresentable>: NSObject where T.RawValue == String {
private var catlog: CatlogModelClass<T>?
private var catlogArray = [CatlogModelClass<T>]()
**// This stored property Now has to be changed to support Generic**
private static var shared : SingleTonClass = {
return SingleTonClass()
}()
// Accessor for Singleton
static func sharedInstance() -> SingleTonClass {
return shared
}
private override init () {}
}
If you want it to be non-singleton, you need to create a public constructor.
You should pass in the catalog and catalogArray into the constructor and initialize self.catalog and self.catalogArray. You then need to remove the static shared instance of the class, because your new setup would require you to create an instance of it.

Class create an instance of itself

I want an instance method of a class to create an instance of itself
and append it to an array.
I tried this:
var vampireArray: [Vampire] = []
class Vampire {
func createSelf() {
vampireArray.append(Vampire())
}
}
but I get a strange error on console like (lldb)
Any ideas why?
Even without knowing the context to this code, in general, creating and then appending an instance of a class to an array outside of the scope of the class is a bad idea.
Instead, try putting the line vampireArray.append(Vampire()) wherever you were originally planning to put createSelf().
If you wanted to stick with this route, it would seem like the method createSelf() should be a static method and var vampireArray: [Vampire] = [] should also be a static variable inside your class.
EDIT:
If all you want to do is keep track of the number of vampires, this could be a good solution:
class Vampire {
static var VampireCount = 0
init(){
Vampire.VampireCount += 1
}
}
Then, whenever you wanted to access the count, just use Vampire.VampireCount

How to create struct data globally accessible in a singleton class in swift 2.0 (iOS)?

I'm very new to iOS programming and swift. I am trying to create a singleton class to store my global data. My global data are a struct and an array of this struct. I want to have only one instance of this class, thus a singleton class. Global data should be accessible and editable to all ViewControllers. I have been searching around and I almost have it figured out except one last part. Here is the singleton class:
import Foundations
class Global {
struct Info {
var firstname:String!
var lastname:String!
var status:String!
init (firstname:String, lastname:String, status:String)
{
self.firstname=firstname
self.lastname=lastname
self.status=status
}
}
var testString: String="Test" //for debugging
var member:[Info]=[]
class var SharedGlobal:Global
{
struct Static
{static let instance = Global()}
return Static.instance
}
}
Now I want to access the global variables of this singleton class from some viewControllers. When I type this in xcode:
Global.SharedGlobal.
I get two options one is the array member and the other is the testString. The struct Info is not available. However, if I just type
Global.
then I see Global.Info and Global.SharedGlobal as my options.
Why is that I can't access the struct in my singleton class (i.e. Global.SharedGlobal.Info)? I am missing something? I appreciate any feedback or help. Thanks a lot in advance.
Unless there's a very specific reason to do it, you don't need to nest classes like that.
Let's simplify a bit your code for the exercise:
struct Info {
// No need for these properties to be Implicitly Unwrapped Optionals since you initialize all of them
var firstname: String
var lastname: String
var status: String
init (firstname:String, lastname:String, status:String) {
self.firstname=firstname
self.lastname=lastname
self.status=status
}
}
class Global {
// Now Global.sharedGlobal is your singleton, no need to use nested or other classes
static let sharedGlobal = Global()
var testString: String="Test" //for debugging
var member:[Info] = []
}
// Use the singleton like this
let singleton = Global.sharedGlobal
// Let's create an instance of the info struct
let infoJane = Info(firstname: "Jane", lastname: "Doe", status: "some status")
// Add the struct instance to your array in the singleton
singleton.member.append(infoJane)
Now it would make sense to me. A struct holding info about some user, and I can make any number instances of them - and a singleton class, unique, were I can store these Info instances, this singleton being usable anywhere.
Is it the kind of thing you wanted to achieve?

Singleton in one line on Swift 2.0

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?

Using Swift Shared Instance in Objective C

I have a shared instance of a class in Swift that I'm using in Objective-C. I'm unable to create the shared instance and use the instance function. Here's my Swift code.
class VideoPlayerSignaler: NSObject {
static let sharedInstance = VideoPlayerSignaler()
let playerAction = Signal<PlayerAction>()
private override init() {
}
func firePlayerAction(action: PlayerAction) {
playerAction.fire(action)
}
}
Here's my Objective-C code.
VideoPlayerSignaler *signaler = [VideoPlayerSignaler sharedInstance];
// This is the line that is producing the issue.
// It's as if the signaler variable is a Class Instance
[signaler firePlayerAction: PlayerAction.Stop];
The error I'm producing states that firePlayerAction does not exist. In essence, Objective C believes the signaler variable to be a class instance.
What am I doing wrong and how do I fix it so that signaler is a shared instance of VideoPlayerSignaler?
There's nothing wrong with your Swift, or with how you access the singleton instance from ObjC — the problem is the enum value you're passing to it.
Presumably your enum declaration looks something like this:
enum PlayerAction: Int {
case Stop, Collaborate, Listen // etc
}
To make your enum accessible to ObjC, you need to preface the declaration with #objc:
#objc enum PlayerAction: Int { /*...*/ }
This makes it appear as a Cocoa-style NS_ENUM declaration in ObjC, creating global symbols for case names by concatenating the Swift enum type's name with the case names:
typedef NS_ENUM(NSInteger, PlayerAction) {
PlayerActionStop = 1,
PlayerActionCollaborate,
PlayerActionListen, // etc
};
So those names are what you should be passing when you call a method taking an enum value from ObjC:
[signaler firePlayerAction: PlayerActionStop]; // NOT PlayerAction.Stop
(The only docs I can find to cite for this are buried in the Attributes chapter in The Swift Programming Language — scroll down the to objc attribute.)

Resources