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
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:
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
How to Move Application's Window Between Virtual Desktops in Os X
How to Use the "Handler" of Uialertaction to Call Another Uialertaction
Bringing iOS Frameworks Through Carthage in Xcode 12.0
Why Can't I Use .Reduce() in a One-Liner Swift Closure with a Variadic, Anonymous Argument
Xcodebuild -Exportarchive Wont Allow Me to Specify Filename
Nsinvocationoperation' Is Unavailable in Xcode 6.1
Swift Repl: How to Save/Load the Repl State? (A.K.A. Suspend/Resume, Snapshot, Clone)
How to Add an Uicollectionviewlayout Programmatically
How to Apply Animation for One Specific Modifier Change Only
Trying to Add a Protocol to a Class Signature in Swift
Solving System of Equations in Swift
Compile Latex Code Using Swift
Type of Expression Is Ambiguous Without More Context in Xcode 11
Running Swift Build in Terminal Leading to "Platform Path" Errors
How to Fix Error: Abort Trap 6 (In Target 'Realmswift' from Project 'Pods')