Duplicating declarations in a swift playgground - swift

is there a way to introduce the concept of 'scope' while trying things out in playground?
Say you want to test a couple of implementations of a class MyClass so you declare it, write some code to test things. You then decide you want to compare that with another version of class MyClass implementation.
Redeclaring MyClass will give a redeclaration error.
So can I have playground treat the first declaration of MyClass and associated code separately from the second without changing the class name or creating multiple playgrounds?
thanks

It's a bit of a hack, but you can use nested types for this – declare a struct the only purpose of which is to have this kind of scoping:
struct Scope1 {
class MyClass { }
}
struct Scope2 {
class MyClass { }
}
let x = Scope1.MyClass()
let y = Scope2.MyClass()
// if you want to quickly switch between using
// one vs the other
typealias MyClass = Scope1.MyClass
let z = MyClass()

No, there isn't. Playground files are order-dependent and run in top-down lexical order.

Related

How to reference static Swift Struct or class variables without using the Type name?

It would be nice to be able to use something similar to "self" as an alias to access the enclosing Struct or Class's static variables. Does swift have an alias to do this?
For example:
struct MyStruct {
static let variable = "Hello"
func accessVariable() {
MyStruct.variable // This works
self.variable // I'd like to be able to do this.
}
}
Or class:
class MyClass {
static let variable = "Hello"
func accessVariable() {
MyClass.variable // This works
self.variable // I'd like to be able to do this.
class.variable // Or this would be nice too!
}
}
There are three ways:
MyStruct.variable
type(of:self).variable
Self.variable
The Self keyword is a relatively recent Swift innovation, and is probably your preferred choice here. The advantage of type(of:) and Self over just saying the name is that they are polymorphic.

Could a Swift Singleton be a class with purely class functions

This feels like the discussion stopped a couple of Swift iterations ago, but I'm curious that in the discussions, it was never suggested (or if it was I never saw it) that a singleton could just be a class with purely class functions, eg -
class MySingleton {
private static var someVar: String?
private static var someOtherVar: SomeType?
class func start() {
// etc...
}
class func doSomething() {
// etc...
}
// etc, etc...
}
Are there any good reasons why we shouldn't do this? I can't think of any.
What do you want to achieve?
In my experience your approach is fine, if
you don't want to create an instance of your class
you don't care, that someone can create an instance of your class (which does not have any benefits, but is still technically possible).
someVar and someOtherVar should contain always the same value for all instances.
Another approach is to have a sharedInstance
class MySingleton {
private(set) static var sharedInstance = MySingleton()
private var someVar: String?
private var someOtherVar: SomeType?
func start() {
// etc...
}
func doSomething() {
// etc...
}
// etc, etc...
}
This gives you more flexibility.
You can call MySingleton.sharedInstance.start() if you want to use the shared instance.
But on the other hand, you can still create your own instance like let customInstance = MySingleton, with its own values for someVar and someOtherVar.
So it really depends on what you want to achieve. If you want to be sure, that no one can create another instance with its own vars, then your approach is safer than my alternative.
In that case, you might even want to consider to make the class final, so no one can create a subclass that behaves differently.
If an object is never instantiated, it's not a singleton. There are no instances of the object, not just a single instance.
There's nothing inherently wrong with doing that, but what's the benefit?
EDIT
It strikes me that the real comparison is between a class that only has class methods and global functions.
In that comparison, the benefit I see is name-spacing. When you create class methods, you have to qualify function calls with the name of the class, so you can say
SomeClass.someMethod()
or
SomeOtherClass.someMethod()
Those are 2 distinct functions and it is obvious that they are distinct functions.
With global functions, you simply say
someMethod()
If at a future date you merge in somebody else's code that also has a global function someMethod() you will get a compiler error about a duplicate function and have to resolve it.

Swift constants: Struct or Enum

I'm not sure which of both are better to define constants. A struct or a enum. A struct will be copied every time i use it or not? When i think about a struct with static let constants it makes no sense that it will copied all the time, in my opinion. But if it won't copied then it doesn't matter what I take?
What advantages does the choice of a struct or enum?
Francescu says use structs.
Ray Wenderlich says use enums. But I lack the justification.
Both structs and enumerations work. As an example, both
struct PhysicalConstants {
static let speedOfLight = 299_792_458
// ...
}
and
enum PhysicalConstants {
static let speedOfLight = 299_792_458
// ...
}
work and define a static property PhysicalConstants.speedOfLight.
Re: A struct will be copied every time i use it or not?
Both struct and enum are value types so that would apply to enumerations as well. But that is irrelevant here
because you don't have to create a value at all:
Static properties (also called type properties) are properties of the type itself, not of an instance of that type.
Re: What advantages has the choice of a struct or enum?
As mentioned in the linked-to article:
The advantage of using a case-less enumeration is that it can't accidentally be instantiated and works as a pure namespace.
So for a structure,
let foo = PhysicalConstants()
creates a (useless) value of type PhysicalConstants, but
for a case-less enumeration it fails to compile:
let foo = PhysicalConstants()
// error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers
Here's a short answer: Do your constants need to be unique? Then use an enum, which enforces this.
Want to use several different constants to contain the same value (often useful for clarity)? Then use a struct, which allows this.
One difference between the two is that structs can be instantiated where as enums cannot. So in most scenarios where you just need to use constants, it's probably best to use enums to avoid confusion.
For example:
struct Constants {
static let someValue = "someValue"
}
let _ = Constants()
The above code would still be valid.
If we use an enum:
enum Constants {
static let someValue = "someValue"
}
let _ = Constants() // error
The above code will be invalid and therefor avoid confusion.
Using Xcode 7.3.1 and Swift 2.2
While I agree with Martin R, and the Ray Wenderlich style guide makes a good point that enums are better in almost all use cases due to it being a pure namespace, there is one place where using a struct trumps enums.
Switch statements
Let's start with the struct version:
struct StaticVars {
static let someString = "someString"
}
switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}
Using a struct, this will match and print out Matched StaticVars.someString.
Now lets consider the caseless enum version (by only changing the keyword struct to enum):
enum StaticVars {
static let someString = "someString"
}
switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}
You'll notice that you get a compile time error in the switch statement on the case StaticVars.someString: line. The error is Enum case 'someString' not found in type 'String'.
There's a pseudo-workaround by converting the static property to a closure that returns the type instead.
So you would change it like this:
enum StaticVars {
static let someString = { return "someString" }
}
switch "someString" {
case StaticVars.someString(): print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}
Note the need for parentheses in the case statement because it's now a function.
The downside is that now that we've made it a function, it gets executed every time it's invoked. So if it's just a simple primitive type like String or Int, this isn't so bad. It's essentially a computed property. If it's a constant that needs to be computed and you only want to compute it once, consider computing it into a different property and returning that already computed value in the closure.
You could also override the default initializer with a private one, and then you'll get the same kind of compile time error goodness as with the caseless enum.
struct StaticVars {
static let someString = "someString"
private init() {}
}
But with this, you'd want to put the declaration of the struct in its own file, because if you declared it in the same file as, say, a View Controller class, that class's file would still be able to accidentally instantiate a useless instance of StaticVars, but outside the class's file it would work as intended. But it's your call.
In the Combine framework, Apple has chosen to prefer enums for namespaces.
enum Publishers
A namespace for types that serve as publishers.
enum Subscribers
A namespace for types that serve as subscribers.
enum Subscriptions
A namespace for symbols related to subscriptions.

How do I store data submitted to computed properties in a protocol extension?

In the app that I'm currently working on, I try to take advantage of the new protocol extension feature in Swift. The idea is that I have a lot of classes implementing the same protocol. Since all these classes should have the same computed properties, and since the properties should behave identically in de different classes, I thought it would be nice to add the functionality only once.
My code is structured as the following example
protocol SomeProtocol { ... }
// There could potentially be unlimited different versions of "SomeClass" that implements "SomeProtocol"
class SomeClass : SomeProtocol { ... }
extension SomeProtocol {
var computedProperty1: Type? {
get { getData(SOME_ENUM) }
set { validateAndSave(newValue, atKey: SOME_ENUM) }
}
var computedProperty2: Type? {
get { getData(SOME_OTHER_ENUM) }
set { validateAndSave(newValue, atKey: SOME_OTEHR_ENUM) }
}
...
func getData(atKey: ENUM_TYPE) -> Type? {
[NEED SOME WAY TO GET THE SAVED DATA AND RETURN IT]
}
func validateAndSave(value: Type?, atKey: ENUM_TYPE) {
[NEED SOME WAY TO SAVE DATA FOR LATER RETURNING]
}
}
// The properties needs to be visible to the client code like this:
class ClientCode {
let someClassObject: SomeProtocol = SomeClass()
someClassObject.computedProperty1 = Type()
print(someClassObject.computedProperty1)
}
(The code above shows signs of storing the data in different dictionaries, which was my first thought)
The problem is that an extension does not support stored properties. But where/how do I store the data submitted to the computed properties then?
I can think of 2 different solutions, but none of them good..
I could transform the extension into a class that implements SomeProtocol instead, and then make SomeClass a subclass of it. That would allow me to save the data in stored properties. But it would also require me to implement all the methods the protocol requires in the new class - and that makes absolutely no sense, since it's the different versions of SomeClass that should provide different functionality..
I could just drop the entire extension idea, and move all the properties into SomeProtocol. But that would require me to implement all the computed properties in all the different versions of SomeClass with identical functionality, and the whole point of my extension idea was to avoid writing the same implementation for the same properties over and over again..
Is there some completely easy logical solution that I have overlooked?
... or a nice way to save data in a protocol extension that I do not know about?
... or another way of obtaining the desired functionality?
... or should I just suck it up and use one of my not-so-pretty solutions?
Assuming I understand the question correctly to work around the fact that protocol extensions don't support stored properties you could extend NSObject and use the objective C runtime to store your properties.
import ObjectiveC
private var AssociationKey: UInt8 = 0
class YourStoredObject {
// Whatever object your are persisting
}
extension NSObject {
var yourStoredObject: (YourStoredObject)! {
get {
return objc_getAssociatedObject(self, &AssociationKey) as? YourStoredObject
}
set(newValue) {
objc_setAssociatedObject(self, &AssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
}
protocol YourProtocol {
var yourStoredObject: YourStoredObject! { get set }
}
extension YourProtocol {
func customYourStoredObjectGetter() -> YourStoredObject {
return yourStoredObject
}
}
extension UILabel : YourProtocol {
func myExtendedFunc() {
// Get (and print) your object directly
print(yourStoredObject)
// Get your object through a protocol custom getter
print(customYourStoredObjectGetter())
// Set your object
yourStoredObject = YourStoredObject()
}
}
I'm not saying this is the best solution but this is the only solution I can think of. I'm also looking for nicer Swift alternatives but still have not found any.
Protocol extension? Why?
Sometimes we get so hung up on an idea that we ignore a practical solution staring right at our face.
1. Do you have set of computed properties? No, you want stored properties.
Since all these classes should have the same computed properties, and
since the properties should behave identically in de different
classes...
... but later
The problem is that an extension does not support stored properties.
But where/how do I store the data submitted to the computed properties
then?
2. Assuming that it is a set of stored properties that you want, you practically provided the solution yourself! Made one change that will make sense now.
I could transform the extension into a class that implements
SomeProtocol instead, and then make SomeClass a subclass of it. That
would allow me to save the data in stored properties.
You extend the class whenever you want to and then confirm its subclasses to SomeProtocol to get the features. This is cleaner.
On a side note, Swift's protocols not being able to store properties is by design. Protocols do not have existence in their own right and it doesn't make sense to add stored properties in them.

Using switch to assign an instance variable

I'd be grateful for any help - been racking my brains for days and I can't see why this isn't working.
Essentially, I have a main view controller which will be controlled by different classes depending on which game the user selects
'classic'
'unlimited'
'timed'
When the user button is pushed, it needs to flick through the options and assign an instance of the class to a variable 'brain'.
this is what I have:
var brain = GuessMeComparer()
func switcher (random:String) {
switch random {
case "Classic": self.brain = ClassicBrain()
case "unlimited": self.brain = GuessMeComparer()
case "timed": self.brain = TimedBrain()
default:break
}
}
I get the error 'cannot assign a value of type 'ClassicBrain' to a value of type 'GuessMeComparer'.
All I can think of is that you cannot assign instance variables using switch?
Any help would be great, cheers!
Using AnyObject will work but – as vadian is saying – will force you to cast to a specific type later. A better option will be abstract a common interface for all the brain classes in a swift protocol, e.g.:
protocol BrainProtocol {
// common interface here
...
}
class /* or struct */ ClassicBrain : BrainProtocol {
// classic implementation here
...
}
class /* or struct */ TimedBrain : BrainProtocol {
// timed implementation here
...
}
...
var brain : BrainProtocol
Swift is a strong type language, the variable brain is declared as type GuessMeComparer.
Once declared you cannot change the type.
To consider different types, declare the variable explicitly as generic type AnyObject.
var brain : AnyObject = GuessMeComparer()
Now you can assign different types to the variable, but in many cases you have to cast the variable to a specific type later in the code.