swift - how to access public constants without having to instanciate class, as in C# - swift

Should not be needed create an instance of a class to access a public constant. I recently started working in Swift, so I must be missing something here.
In this simple example:
public class MyConstants{
public let constX=1;
}
public class Consumer{
func foo(){
var x = MyConstants.constX;// Compiler error: MyConstants don't have constX
}
}
This foo code gives an compile error. To work, I need to create an instance of the MyConstants like this:
public class Consumer{
func foo(){
var dummy = MyConstants();
var x = dummy.constX;
}
}
Adding static to constX is not allowed.

Use struct with static types.structare more appropriate as in enum you can only bind one type of associative values but you can contain the "Type Property of any type" in both.
public struct MyConstants{
static let constX=1;
}
public class Consumer{
func foo(){
var x = MyConstants.constX;
}
}

You should use immutable static variables. Unfortunately classes support computed properties only with the class modifier - the compiler outputs an error stating that class variables are not yet supported.
But in structs it's possible to create static data members:
struct Constants {
static let myConstant = 5
}
and of course it's not required to create an instance, as the immutable static property can simply be accessed as:
Constants.myConstant

If you want a constant, you can also "fake" the as-yet-unsupported class variable with a class computed property, which does currently work:
public class MyConstants{
public class var constX: Int { return 1 };
}
public class Consumer{
func foo(){
var x = MyConstants.constX; // Now works fine.
}
}

For string constants what I do is put the bunch of constants into responsible class file in the following way:
public enum NotificationMessage: String {
case kTimerNotificationId = "NotificationIdentifier"
}
Then for use it from any other point of the code just:
println("\(NotificationMessage.kTimerNotificationId.rawValue)")
Do not forget .rawValue.

I found out the solution below, but hope someone can clarify or post a better solution
enum MyConstantsV2 {
static var constX = 1
}
public class Consumerv2{
func foo(){
var x = MyConstantsV2.constX;
}
}

Related

Can i create a an iOS framework conforming to an inside protocol and also define the same protocol in my project?

i'm creating a framework the conforms to a certain protocol
MyTestFramework.framework
public protocol SBFProtocol {
static var sharedInstance: SBFProtocol { get }
func GetVersion() -> String
func GetBuildNumber() -> String
}
public final class FrameworkBase : SBFProtocol {
public static var sharedInstance: SBFProtocol = FrameworkBase()
public func GetVersion() -> String {
return "1.0"
}
public func GetBuildNumber() -> String {
return "0"
}
}
Then i redefine that same protocol in my class and i import the framework.
MyProject
import MyTestFramework
public protocol SBFProtocol {
static var sharedInstance: SBFProtocol { get }
func GetVersion() -> String
func GetBuildNumber() -> String
}
var testInstance: SBFProtocol = MyTestFramework.FrameworkBase.sharedInstance
Is there a way to access that framework obj with my own protocol definition ?
i keep getting the error:
Value of type 'MyTestFramework.SBFProtocol' does not conform to specified type 'MyProject.SBFProtocol'
Is there any way to do this?
the reason is i want to pass that framework instance to yet another framework (call it annonymousFramework) and i want it to know only the SBFProtocol and not the entire MyTestFramework
is that in any way possible?
Eventually i solved it this way:
i've wrapped the protocol inside it's own framework project (Containing only one protocol.swift file with all the definitions in it)
And then i included that protocol.framework inside all the projects/frameworks that are using it.
This way the compiler recognises it as the same protocol and another benefit i get from this is that i can enforce a minimum iOS version, valid build architectures and more project setting within my protocol/framework hybrid.

Swift Inheritance problem with "Abstract Class" (Protocol workaround) due Override

So the thing is: Swift doesn't have "abstract" classes. The workaround for that was using a protocol and an extension. So what I did was write the one abstract method and all the variables I have in the protocol. In the extension I then wrote all the default methods I have, which also includes a init() method.
Afterwards I made a class which is inheriting/implementing that protocol. But since I want to make that class a final singleton class, I have to override the init() method and make it private. And because it is a protocol and not a class, I can't call something like super.init().
What exactly is going to happen? And is there no better workaround for abstract classes?
Edit: requestValueFor() is part of a template method
protocol Categorie {
private final var multiplyer: Float;
private final let MAX_VALUE: Float;
private final var actualValues: Dictionary<DistrictName, Float>;
public func requestValueFor(district: DistrictName) -> Float;
}
extension Categorie {
internal init() {
initValues();
}
private func initValues() {//setting actualValues and maxValue}
private func setMultiplyer() {//binding to some ui}
}
final class Culture: Categorie {
private static var instance: Categorie?;
private init() {}
class func shared() {
if (instance == nil)
{
instance = Culture();
}
return instance;
}
func requestValueFor(district: DistrictName) -> Float {
<#code#>
}
}

`supportsSecureCoding` crashes when using Optimize for Speed option

I'm having trouble creating classes that uses NSSecureCoding and its subclasses.
class ClassA: NSObject, NSSecureCoding {
public static var supportsSecureCoding: Bool { return true }
}
class ClassB: ClassA {
public static var supportsSecureCoding: Bool { return true } // "Cannot override static var"
}
I'm supposed to call this since the documentation in NSObject.h says,
This property must return YES on all classes that allow secure coding. Subclasses of classes that adopt NSSecureCoding and override initWithCoder: must also override this method and return YES.
// The Secure Coding Guide should be consulted when writing methods that decode data.
Objective-C:
#property (class, readonly) BOOL supportsSecureCoding;
Swift:
public static var supportsSecureCoding: Bool { get }
I am using Xcode 10.0, tried on both Swift 4.0 and Swift 4.2.
How are people getting around this? Any help is appreciated.
UPDATE:
When using public class var supportsSecureCoding, it compiles but it crashes at runtime when Optimize for Speed is used.
Seems the current optimizer of Swift suppresses to generate the overridden getter method when its definition is the same as its superclass. What a clever optimizer!?
This sort of hack would suppress such too strong optimization.
class ClassB: ClassA {
//...
static private var secureCoding = true
override public class var supportsSecureCoding: Bool { return secureCoding }
}
static private let does not have the same effect. So, when the Swift optimizer being more clever, the code above may not work. Better send a bug report soon.
Seems the Swift optimizer is already clever enough and the workaround above may not work.
(See Martin R's comment.)
You may need to remove private.
class ClassB: ClassA {
//...
static var secureCoding = true
override public class var supportsSecureCoding: Bool { return secureCoding }
}
static in a class declaration is an alias for final class, i.e. a type method
which cannot be overridden in a subclass. What you want is a class method
public class var supportsSecureCoding: Bool { return true }
which can be overridden in the subclass with
override public class var supportsSecureCoding: Bool { return true }
Fix that worked for me
private static var secureCodingWorkaround = true
#objc override public class var supportsSecureCoding: Bool { return secureCodingWorkaround }
I could not get any of the above answers to work. This is definitely a bug on Apple's side they will need to address so make sure you send it in the Feedback system. I even added the #objc without luck.
The Swift 5.3 compiler now gives a deprecation message for NSKeyedArchiver for initializations that don't specify secure coding.. but apparently the language doesn't allow for overriding this in subclasses.
When I don't override the variable I get:
Error: Class 'Subclass' has a superclass that supports secure coding, but 'Subclass' overrides -initWithCoder: and does not override +supportsSecureCoding. The class must implement +supportsSecureCoding and return YES to verify that its implementation of -initWithCoder: is secure coding compliant. (NSInvalidUnarchiveOperationException)
When I do override the variable I get: "Cannot override a static variable"
CONDITIONAL WORKAROUND:
This workaround worked for me, as I have a super type that is sort of abstract in that it is never used without a subtype. If you have a similar setup, this should work for you:
public class Supertype: NSObject, NSCoding {
...
}
Subtype:
public class SubType: Supertype, NSSecureCoding {
public static var supportsSecureCoding = true
...
}
This way the var is at least in all subtypes that I use.
If you instantiate and work with Supertype directly, this will not work for you.

Struct does not conform to RawRepresentable protocol?

I have a struct here, which generates errors when Xcode tries to compile it
public struct GATToIPPermissions : OptionSet {
public init(rawValue: UInt)
public static var read: GATToIPPermissions { get {}}
public static var write: GATToIPPermissions { get {}}
public static var event: GATToIPPermissions { get {}}
public static var all: GATToIPPermissions { get {}}
}
The error I get is Type GATToIPPermissions does not conform to protocol RawRepresentable. However, I dont get any indication as to why it doesn't conform.
Can any of you spot the problem?
That syntax you're written is what you would use within a protocol. If it were in a protocol, it would declare "Conforming types must implement an initializer called init(rawValue:), and have getters for the following properties of type GATToIPPermissions: read, write, event, and all"
But you're not aiming to write declarations in a protocol, you're looking to write implementations in a struct, and here is how that would look:
public struct GATToIPPermissions : OptionSet {
public init(rawValue: UInt) {
//initialize self with `rawValue`
}
public static let read = GATToIPPermissions() //set me to the right value
public static let write = GATToIPPermissions() //set me to the right value
public static let event = GATToIPPermissions() //set me to the right value
public static let all = GATToIPPermissions() //set me to the right value
}

Are static classes supported by Swift?

I would like to know if you can create static classes in swift similar to those in C# i.e. a class that cannot be instantiated which can only have static functions and static properties. Are these types of classes possible in swift?
If not, what is the most efficient way to recreate such a design pattern given the tools available within Swift?
No, Swift has no concept of a static class. But if you have no assignable property anyway, what difference will initialization make? I can think of 2 options:
Mark the class as final so it cannot be inherited: final class MyClass { .... }
Use a struct, which has no inheritance: struct MyUtilities { ... }
Yes, that is possible. You just need to define your class as final and make the constructor private, e.g.
final class Test {
private init() {
}
static func hello() {
print("hello")
}
}
Test.hello()
You can get the same functionality by making the initializer private and use static/class keyword before properties and methods.Using final keyword makes sure your class cannot be subclassed and if you use final, static methods don't make sense anymore because they cannot be overridden.
class Bar{
private init(){}
static let x = 10
class func methodA(){
//do something
}
static func methodB(){
// do something else
}
}