Whats the difference between different types of global declaration - swift

I need some advice on the global declaration of variables (and hopefully functions)
What is the difference between declaring a variable like
import Foundation
var myglobalvariable = ""
and
import Foundation
struct globalvariablestruct
{
static var myglobalvariable = ""
}
and
import Foundation
class globalstructoperation {
struct glovalVariable {
static var myglobalvariable = ""
}
}
Also, I have an API, that is used around 5 times in different view controllers, would it be ok to declare it as a global function?
import Foundation
import Alamofire
func myapicall()
{
//stuff
}
Will Apple reject an app if there are (a lot of) global variables/functions?
What would be the best way to pass variables between several ViewControllers? Also, there are some variables which are used on 90% of the ViewControllers, is it OK if I declare those are global variables?

There are lots of questions in this question. I have tried to answer some of the questions. Maybe it will help you.
Approach 1
var myglobalvariable = ""
You can access these types of variables without any reference. You can
define it in any file and can access it in the current module
anywhere. So you can define it somewhere in the file outside of any
scope. There is no need for static and all global variables are
computed lazily.
Approach 2
struct globalvariablestruct{
static var myglobalvariable = ""
}
You can access these types of variables with struct name or you can say that we need to use struct name to access these varibles.
Approach 3
class globalstructoperation {
struct glovalVariable {
static var myglobalvariable = ""
}
}
You can access these types of variables with struct and class name. Also, It creates a pass by reference variable using a struct.
Also, I have an API, that is used around 5 times in different view controllers, would it be ok to declare it as a global function?
Yes, You can go with a global function or create a singleton class
for the same.
Will Apple reject an app if there are (a lot of) global variables/functions?
No, because of Apple reviewer team only checked the functionality of
our app and app do not violate any Apple policy.
What would be the best way to pass variables between several ViewControllers? Also, there are some variables which are used on 90% of the ViewcControllers, is it OK if I declare those are global variables?
Yes, You can define the n number of global variables in the project
because Apple doesn't care about the internal development methodology.

This is all about one of the object-oriented programming concepts. And here is the question is what is encapsulation?
let pi = 3.14159
The first approach is generally terrible form. If you just have a few variables in your whole project, it can be okay, but what happens when there are many many? Let's think about your project team includes 10 ios developers. What will happen when someone wants to use this global variable. How can he/she find them and understand what they are?
class MathObjects{
static let pi = 3.14159
}
print(MathObjects.pi)
I think, the better way is to encapsulate your global variables into their own class. This keeps everything all in one place and gives you the added benefit of XCodes’ handy autocomplete.

Related

Global var vs Shared Instance swift

What is the difference between global variable and shared instance in Swift? what are their respective field of use? Could anyone clarify their concept based upon Swift.
A global variable is a variable that is declared at the top level in a file. So if we had a class called Bar, you could store a reference to an instance of Bar in a global variable like this:
var bar = Bar()
You would then be able to access the instance from anywhere, like this:
bar
bar.foo()
A shared instance, or singleton, looks like this:
class Bar {
static var shared = Bar()
private init() {}
func foo() {}
}
Then you can access the shared instance, still from anywhere in the module, like this:
Bar.shared
Bar.shared.foo()
However, one of the most important differences between the two (apart from the fact that global variables are just generally discouraged) is that the singleton pattern restricts you from creating other instances of Bar. In the first example, you could just create more global variables:
var bar2 = Bar()
var bar3 = Bar()
However, using a singleton (shared instance), the initialiser is private, so trying to do this...
var baaar = Bar()
...results in this:
'Bar' initializer is inaccessible due to 'private' protection level
That's a good thing, because the point of a singleton is that there is a single shared instance. Now the only way you can access an instance of Bar is through Bar.shared. It's important to remember to add the private init() in the class, and not add any other initialisers, though, or that won't any longer be enforced.
If you want more information about this, there's a great article by KrakenDev here.
Singleton (sharing instance)
Ensure that only one instance of a singleton object is created & It's provide a globally accessible through shared instance of an object that could be shared even across an app.
The dispatch_once function, which executes a block once and only once for the lifetime of an app.
Global variable
Apple documentation says Global variables are variables that are defined outside of any function, method, closure, or type context.

How is a global variable set to private understood in swift?

I'm working through a Core Data exercise from a book and it starts out creating a helper class which is a singleton. I understand that global variables can be created outside of a class's scope and accessible throughout the project however where I'm confused is than an example from the book creates a global variable and sets it to private. I assumed that by setting a variable to private, it is only accessible to that specific class. This private global variable is created outside of the helper class so I assume its accessible by all classes in the project therefore the private keyword isn't necessary. Can anyone help by confirming if my assumptions are correct or incorrect as I'd really like to understand.
Here is the code from the book's example:
import Foundation
import CoreData
//this is a global variable accessible from any module or class
private let _sharedCDHelper = CDHelper()
class CDHelper: NSObject {
// MARK: - SHARED INSTANCE
class var shared: CDHelper {
return _sharedCDHelper
}
}
A private global variable in Swift is a global that is only accessible from the file in which it is declared.
The book you are using isn't following current best-practice as far as creating singletons in Swift (perhaps it is a little out-dated?).
There is no need for the private global variable. You can just say:
class CDHelper: NSObject {
// MARK: - SHARED INSTANCE
static let shared = CDHelper()
}

Swift: refactor singleton pattern

I have a Swift singleton class that maintains app state by storing several arrays. What is the best practices' way to go here? Should we change it, and if we do, then how?
Here is the singleton class:
import Foundation
class FilterModel {
static let sharedInstance = FilterModel()
private init() { }
var muscleExercisesArray = [Int]()
var equipmentExercisesArray = [Int]()
var typeExercisesArray = [Int]()
}
If you're wondering about the basic singleton pattern, a couple of observations:
I might suggest you declare the class to be final, too, to avoid having some future developer subclass it and introduce confusion about to what type sharedInstance refers.
I might also suggest that in Swift 3, the convention is to simplify the name of sharedInstance to just shared. It's not a hard and fast rule, but is the emerging standard.
This implementation is not thread-safe. If you're ok with that, I'd at least include some warning in the comments warning future developers of this concern. Or, obviously, with a little work you could change this to be thread-safe by wrapping this all in some internal synchronization mechanism.
You said:
Singletons are considered a bad approach towards app architecture, so I was wondering what to do instead of it when we need to maintain app state. Somehow I can not find anything online except for DI approach that does not work (or I do not know how) in this case when we need app state to be modified by different files
Yes, singletons are not ideal for model objects for a number of reasons (makes unit testing harder; makes responsibilities unclear, etc.) and there are better patterns (see What's Alternative to Singleton). At the very least, one simple approach is to have app delegate or root view controller instantiate this model object and then only pass this to whatever subsequent controllers need access to it (e.g. in prepareForSegue). This way, it's explicit which objects might be interacting with the model, making responsibilities a little more clear.

Any reason not use use a singleton "variable" in Swift?

For Sept 2015, here's exactly how you make a singleton in Swift:
public class Model
{
static let shared = Model()
// ( for ocd friends ... private init() {} )
func test()->Double { print("yo") }
}
then elsewhere...
blah blah
Model.shared.test()
No problem.
However. I add this little thing...
public let model = Model.shared
public class Model
{
static let shared = Model()
func test()->Double { print("yo") }
}
then, you can simply do the following project-wide:
blah blah
model.test()
Conventional idiom:
You see Model.shared.blah() everywhere in the code.
"My" idiom:
You see model.blah() everywhere in the code.
So, this results in everything looking pretty!
This then, is a "macro-like" idiom.
The only purpose of which is to make the code look pretty.
Simplifying appearances of ImportantSystem.SharedImportantSystem down to importantSystem. throughout the project.
Can anyone see any problems with this idiom?
Problems may be technical, stylistic, or any other category, so long as they are really deep.
As a random example, here's an "article in singletons in Swift" that happens to also suggest the idea: https://theswiftdev.com/swift-singleton-design-pattern/
Functionally, these are very similar, but I'd advise using the Model.shared syntax because that makes it absolutely clear, wherever you use it, that you're dealing with a singleton, whereas if you just have that model global floating out there, it's not clear what you're dealing with.
Also, with globals (esp with simple name like "model"), you risk of having some future class that has similarly named variables and accidentally reference the wrong one.
For a discussion about the general considerations regarding globals v singletons v other patterns, see Global Variables Are Bad which, despite the fairly leading title, presents a sober discussion, has some interesting links and presents alternatives.
By the way, for your "OCD friends" (within which I guess I must count myself, because I think it's best practice), not only would declare init to be private, but you'd probably declare the whole class to be final, to avoid subclassing (at which point it becomes ambiguous to what shared references).
There are a few things to look out for when using this approach:
The global variable
A global variable in itself is no big deal, but if you have quite some global variables, you might have trouble with autocompletion, because it will always suggest these global variables.
Another problem with global variables is that you could have another module in your application (written by you or otherwise) define the same global variable. This causes problems when using these 2 modules together. This can be solved by using a prefix, like the initials of your app.
Using global variables is generally considered bad practice.
The singleton pattern
A singleton is helpful when working with a controller, or a repository. It is once created, and it creates everything it depends on. There can be only one controller, and it opens only one connection to the database. This avoids a lot of trouble when working with resources or variables that need to be accessed from throughout your app.
There are downsides however, such as testability. When a class uses a singleton, that class' behaviour is now impacted by the singletons behaviour.
Another possible issue is thread safety. When accessing a singleton from different threads without locking, problems may arise that are difficult to debug.
Summary
You should watch out when defining global variables and working with singletons. With the appropriate care, not many problems should arise.
I can't see a single downside to this approach:
You can use different variables for different parts of the program (-> No namespace cramming if you don't like this I guess)
It's short, pretty, easy to use and makes sense when you read it. Model.shared.test() doesn't really make sense if you think about it, you just want to call test, why would I need to call shared when I just need a function.
It uses Swift's lazy global namespace: The class gets allocated and initialized when you use it the first time; if you never use it, it doesn't even get alloced/inited.
In general, setting aside the exact idiom under discussion, regarding the use of singletons:
Recall that, of course, instead of using static var shared = Model() as a kind of macro to a singleton, as suggested in this Q, you can just define let model = Model() which simply creates a normal global (unrelated to singletons).
With Swift singletons, there has been discussion that arguably you want to add a private init() {} to your class, so that it only gets initialized once (noting that init could still be called in the same file).
Of course in general, when considering use of a singleton, if you don't really need a state and the class instance itself, you can simply use static functions/properties instead. It's a common mistake to use a singleton (for say "calculation-like" functions) where all that is needed is a static method.

Combine generics and extensions in Swift?

Looking at:
Using a dispatch_once singleton model in Swift
I see a very generic pattern for creating a shared singleton instance of my class. What I'd like to be able to do is create an extension for "all classes" that implements this sharedInstance method with generics.
I don't see any syntax for doing this; anybody want to take a crack at it?
As others have pointed out, Swift offers a simpler way to create singletons.
As an example: let's say we have a class called Model, and we want to have a single instance, visible throughout our app. All we need to write in the global scope is:
let modelSingleton = Model()
This will create an instance of the Model class, visible everywhere, and that cannot be replaced by another instance (Hmmm, that's pretty much what one would expect from a singleton, isn't it?).
Now, this way of doing would, on the other hand, still allow you to create other Model instances, apart from the singleton. While this departs from the official definition of singletons in other languages, this approach would have the interesting advantage of allowing the creation of other instances for testing purposes (singletons have bad press in the unit testing world :) ).
Swift will soon offer everything needed to create real Singleton<T> classes (it's hard now because class vars aren't allowed yet). But that being said, the approach described above will probably be more than enough for many Swift programmers.
I don't think this is possible.
Even if it was possible to extend Any / AnyObject, every object would share the same implementation of the sharedInstance singleton getter, and therefore the same static instance variable. Thus, instance would get set to an instance of the first class on which sharedInstance was called.
extension Any {
class var sharedInstance:TPScopeManager {
get {
struct Static {
static var instance : TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
}
...
NSString.sharedInstance() // Returns an NSString
NSArray.sharedInstance() // Returns the same NSString object!
In Swift you can make an extension to NSObject, but you can't extend Any/AnyObject