No More 'Private Init' in Swift

No more `private init` in Swift?

You're probably expecting private to restrict the use to within the class definition, but that's not what it does.

The definition of private is to "restrict the use of an entity to its own defining source file".

From the Swift book, "Access Control" chapter.

EDIT:

As of Swift 3 fileprivate does what private used to and private is now more restrictive in that it "restricts the use of an entity to the enclosing declaration"

How to prevent object construction in Swift

From Apple's guide to Swift:

Private access restricts the use of an entity to its own defining
source file. Use private access to hide the implementation details of
a specific piece of functionality.

Your playground file is all one file, so privacy is not enforced.

For instance, if you create a new project and add a file called Dog.swift to the project that looks like this:

import Foundation

class Dog {
private init() {
print("hello")
}
}

class Cat {
var d = Dog()
}

in ViewController.swift, you can write:

override func viewDidLoad() {

let c = Cat() //=>hello

}

But, if you try:

override func viewDidLoad() {

let d = Dog()

}

Xcode will flag that as an error before you even compile the program:

'Dog' cannot be constructed because it has no accessible initializers

Response to comment:

class A {
init?() {
return nil
}

func greet() {
print("hello")
}
}

let x = A()

if let x = x {
x.greet()
}
else {
print("nice try") //=> nice try
}

Swift - init in singleton class?

The init gets called only the first time you invoke MyClass.shared

At that point the instance of MyClass is saved inside the shared static constant.

Example

Let's consider this Singleton class

final class Singleton {
static let shared = Singleton()
private init() {
print("Singleton initialized")
}

var count = 0
}

Now let's look at the output into the console

Sample Image

As you can see the Singleton initialized string is printed only once. This means the init is only called once.

Note: Of course I assumed the implementation of your Singleton class is correct.

failable init in singleton class with private initializer in swift

In this situation, the problem was cycling access, in myFunction I was creating an object that had a call to MyClass.shared?.someFunction(), and it was the reason for the crash.

Swift how to make the default initializer of a `struct` private

If you are noticing that implementing:

struct Foo {
let bar: String
static let sharedInstance = Foo(bar: "blah")
}

is legal even without giving bar an initial value, why? because Swift Structs have a default initializer, called the memberwise initializer:

Structure types automatically receive a memberwise initializer if they
do not define any of their own custom initializers. Unlike a default
initializer, the structure receives a memberwise initializer even if
it has stored properties that do not have default values.

The memberwise initializer is a shorthand way to initialize the member
properties of new structure instances. Initial values for the
properties of the new instance can be passed to the memberwise
initializer by name.

Meaning that if you tried to create a new instance of Foo struct, the compiler should -automatically- provide:

Sample Image

However, you can get rid of it by implementing private init(), but you have to make sure that all stored properties have -dummy- initial values (or maybe let them optionals...) because the struct no longer has an initializer for guaranteeing that the stored properties has values.

It should be similar to:

struct Foo {
var bar: String = ""
static var shared = Foo()

private init() {}
}

Remark: I would suggest to stuck with class when implementing a singleton pattern, you might want to check this answer (Thanks to
MartinR for mentioning it).

How to get coverage for private init

Move your String constants to an enum then you won't need a private init.

enum SpecificConstants {
static let foo = "foo"
}

Initializing variable in a private function when inheriting from NSObject

initializeMyVar()
super.init()

It has no connection with NSObject. It's general rule when you're calling init of superclass; you can't call method of self before you initialize your object or before you assign all non-optional variables

_myVar = 4
super.init()

super.init()
initializeMyVar()

In second case where you assign variable after super.init(), you don't give value to your variable and this isn't possible because then your value would have nil which also isn't possible because your variable isn't optional. Then in this case make your variable optional

private var _myVar: Int?

Swift extensions on structs make private initialization protection impossible

As per zneak's comments above, this will be disallowed in Swift 5.

Why do I have to override my init in Swift now?

it looks like your convenience initializer is empty which is why you get the error. For example if you change it to:

convenience init() {
self.init(name: "", year: 0, major: "nothing", gpa: "4.0")
}

the error would go away.

I wonder why you set up Student to inherit from NSObject. It doesn't look necessary for your class.



Related Topics



Leave a reply



Submit