Call methods from Swift initializer
declare it as an implicitly unwrapped optional
class MyClass : NSObject {
var myProperty: String!
init() {
super.init()
self.setupMyProperty()
}
func setupMyProperty() {
self.myProperty = "x"
}
}
page 499 of "The Swift Programming Language" manual
Calling an instance method in designated initializer of a Swift class
As you correctly mentioned the compiler complains about the "Use of self in method call 'parseString' before super.init initialises self". The reason for that is that the compiler has to ensure that you do not access anything on self
before it did finish initializing. Because the compiler does not want to (or even can not) check every outgoing method call before the initialization finished it simply disallows any usage of self before it finished.
Luckily your method parseString
does not want to change or access any property. Therefore you can and should make it a non-instance function. If it has nothing do with the instance of FooBar
, why should it have be only available on an instance of FooBar
?
You can simply make it a static
or class
function as you already did, which is perfectly fine.
But I would go even further and move it completely out of FooBar
. There are a few options for that:
- create a class
Helper
where you define it as aclass function
as well - create a class
Helper
where you define it asinstance function
and create aHelper
instance in your classFooBar
or create a global one and pass that one in the init as well.
How to call instance method inside class using Swift
An instance of a class is not initialized and able to be referenced (even as 'self') until all of its variables have been assigned values.
An option that may work for you is to declare your variable as an implicitly-unwrapped optional, which is assigned nil by default. Then in the class's init method, since all of the variables have been assigned values, you are able to start calling methods on your instance.
class Rect {
var toPrint: String!
init() {
toPrint = printthis()
}
printthis() -> String {
return "this will work"
}
}
Passing instance method as callback in class initializer
Here's another option:
class Foo {
let bar: Bar
init() {
self.bar = Bar(callback: self.handler)
}
let handler: () -> Void = {
print("handled")
}
}
Maybe it doesn't feel quite as hacky, but if handler
deals with self
at all, this won't work. You can't do it with a Delegate either.
Yea, AFAIK, the only way to do this is to make bar
an implicitly unwrapped var
class Foo {
var bar: Bar!
init() {
bar = Bar(callback: handler)
}
func handler() {
print("Handled")
}
}
Use Function in Initializer - Swift?
I think it is not the greatest solution but still it is working.
class A {
var variable : Int
init() {
self.variable = A.assign(1)
}
private class func assign(y : Int) -> Int {
return y
}
}
Initialising member to class function causes 'self' used in method call error
It might be better to not use a Bool
, but rather a nested Enum
, which is also more extendible if you wanna add some other modes of haptic feedback later on.
I have a generalized solution for a generalized problem of your question. So either you do:
public class FunctionOwner {
private let mode: Mode
public init(`do` mode: Mode = .default) {
self.mode = mode
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
switch mode {
case .foo: foo()
case .bar: bar()
}
}
}
private extension FunctionOwner {
func foo() {
print("doing foo")
}
func bar() {
print("doing bar")
}
}
public extension FunctionOwner.Mode {
static var `default`: FunctionOwner.Mode {
return .foo
}
}
// USAGE
FunctionOwner(do: .bar).fooOrBar() // prints "doing foo"
FunctionOwner(do: .foo).fooOrBar() // prints "doing bar"
Or if you for some reason do want to keep the stored Mode
, you can do this (might be relevant for your actual question on how you do a workaround of referencing self
in the init.):
public class FunctionOwner {
private let _function: (FunctionOwner) -> Void
public init(`do` mode: Mode = .default) {
_function = { functionOwner in
switch mode {
case .foo: functionOwner.foo()
case .bar: functionOwner.bar()
}
}
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
_function(self)
}
}
// The rest of the code is the same as the example above
Swift. Use of 'self' in method call before all stored properties are initialized
You can't call methods on self before all non-optional instance variables are initialized.
There are several ways to go around that.
- Change properties to optionals or implicitly unwrapped optionals
(not recommended) - Make the
buildCircle()
method static or just a
function in the file and call theaddSubview()
for all the circles
after all of the properties were initialized and you calledsuper.init()
- etc. You just have to avoid calls to self before the
class was initialized.
Trouble calling a method in an init
You cannot use self before all the stored properties have been initialised
The rule is simple and you are violating it here
self.date = getDateString()
infact this line is equivalente to
self.date = self.getDateString()
and as you can see you are using self
while date
has not been initialised yet.
You must init date
before calling the instance method getDateString()
.
A class method
If you really want to call a method to initialize date
it must be a class method
class SomeClass {
let title: String
let content: String
let date: String?
init(title: String, content: String) {
self.title = title
self.content = content
self.date = SomeClass.getDateString()
}
class func getDateString() -> String {
return "A date"
}
}
A few improvements
- If then
date
should contain... a Data then its type should be NSDate, notString
- If the
date
property should indicate the time when the value has been created then you can assign it= NSDate()
on the declaration of the property created
is a better name for this property
These 3 suggestions comes from the comment of user user3441734
.
This is the updated code
class SomeClass {
let title: String
let content: String
let created = NSDate()
init(title: String, content: String) {
self.title = title
self.content = content
}
}
Swift. Use of 'self' in method call before all stored properties are initialized
You can't call methods on self before all non-optional instance variables are initialized.
There are several ways to go around that.
- Change properties to optionals or implicitly unwrapped optionals
(not recommended) - Make the
buildCircle()
method static or just a
function in the file and call theaddSubview()
for all the circles
after all of the properties were initialized and you calledsuper.init()
- etc. You just have to avoid calls to self before the
class was initialized.
Related Topics
Get the Callers Phone Number from an Incoming Call on Iphone
How to Get Assets.Xcassets File Names in an Array (Or Some Data Structure)
Default Value of Maxconcurrentoperationcount for Nsoperationqueue
Xcode Duplicate Symbols for Architecture Error After Updating Cocoa Pods
Not Getting the Email Using Google Authentication in Firebase
Firebase - How to Get the Key Value in Observeeventtype = Value
Native Zlib Inflate/Deflate for Swift3 on iOS
How to Truncate Decimals to X Places in Swift
Multiple Unusernotifications Not Firing
Hiding Cancel Button on Search Bar in Uisearchcontroller
Best Analytics Offering for Iphone
Using Sysctlbyname() from Swift
iOS Unrecognized Selector Sent to Instance in Swift
Hit Detection When Drawing Lines in iOS
Ios9: Alternative to Uidevice.Currentdevice().Setvalue(...) to Force Orientation