Call Methods from Swift Initializer

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

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
}
}

How to call Swift initializer methods with multiple param in Objective-C

To be accessible and usable in Objective-C, a Swift class must be a
descendant of an Objective-C class or it must be marked @objc.

And also this answer.

This apple doc will also help you understand.

So the options for you is to either inherit the class of yours from some Objective C class (In this case compiler adds @objc) or add @objc yourself to your class.

You also need to add to your Objective C class-

#import "<#ProjectName#>-Swift.h"

Real solution to this specific question

Please look at this question, you will get your solution yourself. :)

That question says that optional parameters can't be exposed from Swift to Objective C as all parmeters become _Nonnull.

So I think you will need to create another initializer without optionals and default parameters.

Swift: why I can't call method from override init?

There are two competing initialization safety checks that are causing your problem.

Safety check 1


A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

and

Safety check 4


An initializer cannot call any instance methods, read the values of any instance properties, or refer to self as a value until after the first phase of initialization is complete.

Here is how it works.

override init() {
super.init() // Fails safety check 1: uuid is not initialized.
uuid = createUUID()
}

conversely,

override init() {
uuid = createUUID() // Fails safety check 4: cannot call an instance method before initialization is complete.
super.init()
}

Thanks to @Ruben in his answer

How to call a class method in a convenience initializer in Swift

Instead of creating a class function for figuring out the id, create init functions instead. Since you already have to create one of these functions per subclass, you're not really losing anything. The subclasses init function then calls the super's init with the id name.

Here's an example, I changed some of the properties of your group just for the sake of making the example simple to illustrate the concept.

public class BaseAPIObject {
var objData: [String:String]

required public init(_ data: [String: String]) {
println("Data: \(data)")
self.objData = data

}

public convenience init(id: String, idFieldName: String) {
let data = [idFieldName: id]
self.init(data)
}
}

And then in your subclass, just conceptually something like this:

public class GroupObject: BaseAPIObject {
public convenience init (id: String) {
self.init(id: id, idFieldName: "group")
}
}

let go = GroupObject(id: "foo")
println(go.objData["group"]!) //prints "foo"

Swift: Call self method inside init

No, it's not a defect, simply self cannot be referenced in an initializer until all stored properties have been initialized, and a super class initializer has been invoked (if any).

In your case it seems legit to do the initializations in a method, and call that from the initializer, but unfortunately it doesn't work.

Possible solutions:

  • make the properties optional or implicitly unwrapped (discouraged, unless you really need them optionals)
  • initialize the properties with fake values before calling reset:

    init() {
    self.a = 0
    self.b = 0
    self.c = 0
    self.d = 0

    reset()
    }

    or

    var a = 0
    var b = 0
    var c = 0
    var d = 0

    init() {
    reset()
    }

call a method from another class with required init coder

Looks like you're trying to update tab bar controller from one of tabs.

You can get reference to current tab bar controller (if there's one that's presenting this particular view controller) from your second controller using tabBarController variable, try this:

(tabBarController as? MyTabBarCtrl)?.changeFloatingButtonColor()

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


Related Topics



Leave a reply



Submit