How to create a static closure inside a function?

I have a closure like this

let activateObject:() -> Void = { [weak self] in 
	DispatchQueue.main.async {
		NotificationCenter.default.post(name: .doIt, object: "70733")
	    self?.spinner.stopAnimation(nil)
		self?.ajustObject()
	}
}

This closure is inside a function and I would like it to continue inside that function.

I want to define this closure as static. Meaning that the first time the function run, the closure is defined and the next time the function runs, the defined value runs.

I have found solutions like this

func theFunction() {
    struct Once {
        static let once = Once()
        init() {
            print("This should be executed only once during the lifetime of the program")
        }
    }
    _ = Once.once
}

but this will not work for this case.

If I do this:

func theFunction() {
    struct Once {
        static let once = Once()
        init() {
		let success:() -> Void = { [weak id] in
							DispatchQueue.main.async {
		NotificationCenter.default.post(name: .doIt, object: "70733")
	    self?.spinner.stopAnimation(nil)
		self?.ajustObject()
	}
        }
    }
    _ = Once.once
}

The compiler will complain because I cannot use self inside a struct.

Any way to do this keeping the closure inside the fuction?

Sounds like a need for a static initialiser.

I wrote a blog post that might be useful

thanks, I suspect that your blog post answer my question but I am a newbie on certain matters of swift and I do not have a clue on how to apply your blog answer to my case. Thanks.

If you only want it to apply to one class, then just combine the Person and Object code together in your class and hardcode the type of your class instead of using the general type(of:_) code in Object.

Like I said, I want to add this inside a function, not as part as a class definition. Thanks anyway.

Then simply create a function that calls YourClass.StaticInit()

What object is self supposed to refer to? That object needs a spinner property, and an ajustObject method. Since you are not providing a reference to an object, self is assumed to be the instance of the Once struct, which doesn't have those attributes.

in the case, self is the class instance.

The closure is inside a function that is inside a class.

In that case, use my code and call the staticInit method in the class's init, after the super.init call.

Just a minute!!! What calls the activateObject var?

Since all the code seems to be on an instance and not on the class, why not simply add a boolean flag and check for that to avoid calling the same code more than once?

Is this an abstraction of your architecture?

import Foundation

struct Spinner {

	func stopAnimation(_ obj: AnyObject?) {
	}

}

struct TheStruct {

	var spinner : Spinner = Spinner()

	func adjustObject() { }

	func theFunction() {
		struct Once {
			static let once = Once()
			init() {
				let success:() -> Void = { [weak id] in
						DispatchQueue.main.async { NotificationCenter.default.post(name: .doIt, object: "70733")
							self?.spinner.stopAnimation(nil)
							self?.adjustObject()
						}
				}
			}
		}
		_ = Once.once
	}
}

Putting this in a Swift playground, other than the obvious errors on id (not defined) and doIt (not defined), the errors I get from init is that you cannot do a chained un-wrap on a non-optional, i.e., self is not an optional, and that struct Once does not have a property spinner and it does not have a method adjustObject. self is referring to an instance of Once, not the an instance of TheStruct. No mention of not being able to use self in the struct, in fact, self is often used in a class/struct/enum to refer to the local state of the instance.

Not sure it this is what you are looking for, but, this compiles.

import Foundation

struct Spinner {

	func stopAnimation(_ obj: AnyObject?) {
	}

}

struct TheStruct {

	var spinner : Spinner = Spinner()

	func adjustObject() { }

	static func theFunction(_ arg : TheStruct?) {
		let success : () -> Void = { [arg] in
			DispatchQueue.main.async {
				//NotificationCenter.default.post(name: .doIt, object: "70733")
				arg?.spinner.stopAnimation(nil)
				arg?.adjustObject()
			}
		}
		success()
	}
}

let a = TheStruct()
TheStruct.theFunction(a)

thanks, that will do the trick.

Just a suggestion, you may need to make success() @escaping.