I want to call a function in initializer, but i couldn't do it
class someclass {
var a : Int
var b : Int
init() {
self.a = 5
self.b = 4
func printx () {
println("you called the function")
}
printx()
}
}
var ab = someclass()
Is it posible to do that something like ab.init().printx
And
Will this printx() function execute when i initialize with someclass()
For your questions: No - you can't reference your printx from outside of init and Yes - your printx will execute when init is called. In Swift 1.2:
20> class Bar {
21. var ping : Int
22. init () {
23. ping = 1
24. func bar () { println ("bar") }
25. bar()
26. }
27. }
28> Bar()
bar
$R4: Bar = {
ping = 1
}
Defining your printx in init is perfectly viable and you should demand that it works (and it does). Having lexically contained function definitions in Swift is critically important. Now, if the language could allow the function name to be recursively visible...
Maybe you would do something like this?
class someclass {
var a : Int
var b : Int
func printx () {
println("you called the function")
}
init() {
self.a = 5
self.b = 4
printx()
}
}
var ab = someclass()
ab.printx()
Consider you never call init() writing it but just with someClass()
This question simply demonstrates a lack of understanding when it comes to scope.
The function printx() is not a method on the class SomeClass, but it a function scoped within the particular init() method you've defined.
As written, printx() will execute (and will print) when you call the init() method:
See the box in the right pane at the top? That's showing us all of the console output from our playground, exactly as it would display if we ran this otherwise.
However, we cannot now call ab.printx() because as I stated earlier, printx() is not a member of the class SomeClass. If we want to call printx() on instances of SomeClass, we must then define it as an instance method of the class (and if we still want to call it in init, we can).
Related
I would like to have some sort of global variable that is synchronized using #MainActor.
Here's an example struct:
#MainActor
struct Foo {}
I'd like to have a global variable something like this:
let foo = Foo()
However, this does not compile and errors with Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context.
Fair enough. I've tried to construct it on the main thread like this:
let foo = DispatchQueue.main.sync {
Foo()
}
This compiles! However, it crashes with EXC_BAD_INSTRUCTION, because DispatchQueue.main.sync cannot be run on the main thread.
I also tried to create a wrapper function like:
func syncMain<T>(_ closure: () -> T) -> T {
if Thread.isMainThread {
return closure()
} else {
return DispatchQueue.main.sync(execute: closure)
}
}
and use
let foo = syncMain {
Foo()
}
But the compiler does not recognize if Thread.isMainThread and throws the same error message again, Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context.
What's the right way to do this? I need some kind of global variable that I can initialize before my application boots.
One way would be to store the variable within a container (like an enum acting as an abstract namespace) and also isolating this to the main actor.
#MainActor
enum Globals {
static var foo = Foo()
}
An equally valid way would be to have a "singleton-like" static property on the object itself, which serves the same purpose but without the additional object.
#MainActor
struct Foo {
static var shared = Foo()
}
You now access the global object via Foo.global.
One thing to note is that this will now be lazily initialized (on the first invocation) rather than immediately initialized.
You can however force an initialization early on by making any access to the object.
// somewhere early on
_ = Foo.shared
Bug in Swift 5.5, 5.6, 5.7
TL;DR: #MainActor sometimes won't call static let variables on the main thread. Use private(set) static var instead.
While this compiles and works, it appears that this may call the initializer off the main thread and subsequently any calls made inside the initializer.
#MainActor
func bar() {
print("bar is main", Thread.isMainThread)
}
#MainActor
struct Foo {
#MainActor
static let shared = Foo()
init() {
print("foo init is main", Thread.isMainThread)
bar()
}
func fooCall() {
print("foo call is main", Thread.isMainThread)
}
}
Task.detached {
await Foo.shared.fooCall()
}
// prints:
// foo init is main false
// bar is main false
// foo call is main true
This is a bug (see issue 58270).
A workaround is to always use a private(set) static var instead of a static let, as the correct isolation behaviour is enforced in that case.
I have a C code:
static __inline__ __attribute__((__always_inline__))
__attribute((swift_name("Test.init()")))
test_t test_init(void) { /* ... */ }
And test Swift code:
let test = Test()
The code is compiled, but function test_init not call.
If I add test argument and call init with him, my method * test_init * is called.
For structures imported from C the compiler creates an init() initializer which takes no arguments and sets all members to zero. For example
__attribute((swift_name("Test")))
typedef struct {
int a;
} test_t;
is imported to Swift as
public struct Test {
public var a: Int32
public init()
public init(a: Int32)
}
as one can see with "Navigate -> Jump to Generated Interface" in Xcode.
You can create additional init methods in C, but you cannot replace
existing init methods.
(One could argue that the compiler should as least warn that the
C function with the Swift name "Test.init()" will be ignored in Swift, so you might consider to file a bug report.)
If you want to define another init method taking no arguments in C
then you have to give it a dummy Void argument:
__attribute((swift_name("Test.init(v:)")))
static __inline__ __attribute__((__always_inline__))
test_t test_init(void) {
test_t t = { 3 };
return t;
}
and call it as
let test = Test(v: ())
print(test) // Test(a: 3)
I'm not talking about pointers to C functions, but to a method within a Swift type.
struct Test: GeneratorType {
var methodPointer: mutating () -> Bool? // Non-working guess
var which: Bool
init() {
which = false
methodPointer = which ? &testMethod1 : &testMethod2 // Also non-working guess
}
//...
}
The compiler says "mutating" isn't legal as part of a function declaration. (Actually, it just suggests a semi-colon there.) And for the pointer initialization (after I remove mutating), the compiler thinks I'm trying to call the functions and use their results instead. I want to use the methods as objects in-and-of themselves here, not as a function call. Later on I want to use the pointed-to method within next; without figuring this out, I'll have to resort to an enumeration flag and manually choosing which method to call within next.
I hope there's some part of closure mechanics that allows this. Maybe something like this page, which describes functions returning functions. But none of the examples I've seen mention mutating methods.
See if this helps you.
class Something {
var f: ( () -> Int )?
let f1 = { () -> Int in /* do some action here */ return 1}
let f2 = { () -> Int in /* do some action here */ return 2}
func ff(which: Bool) {
f = which ? f1 : f2
}
func act() {
if let f = f {
f()
}
}
}
Here is how I do it -
class FcnArgs { //#goal pass a fcn as arg
class func demo() {
let fPtr = funcToPointTo; //#type '((Int)->String)'
print(fPtr(4));
}
class func funcToPointTo(_ i : Int) -> String {
print("I Was passed \(i)");
return "I was returned";
}
}
FcnArgs.demo() output:
I Was passed 4
I was returned
Is there an example of how dispatch_once should be used in Swift? (Preferably one from Apple.)
Note: In this case, I'm not using it for a singleton; I want to run arbitrary code exactly once.
Update: I'm mainly interested in the convention recommended when using this in an instance method, but usage in a class method, function, and in the global context would be useful for completeness sake.
dispatch_once_t is type alias (Int). Header documentation:
/*!
* #typedef dispatch_once_t
*
* #abstract
* A predicate for use with dispatch_once(). It must be initialized to zero.
* Note: static and global variables default to zero.
*/
typealias dispatch_once_t = Int
And here's the quote from dispatch_once documentation:
The predicate must point to a variable stored in global or static
scope. The result of using a predicate with automatic or dynamic
storage (including Objective-C instance variables) is undefined.
Token variable must be stored in global / static scope and must be initialized to zero, which leads to this code:
import Foundation
var token: dispatch_once_t = 0
dispatch_once(&token) { () -> Void in
print("Called once")
}
It doesn't work if you omit = 0 (token initialization), because compiler yields error Address of variable 'token' taken before it is initialized despite the fact that statics and globals default to zero. Tested in Xcode 7B2.
More examples based on comment. If you're inside class method you have several possibilities.
You can't declare static property inside method otherwise compiler yields Static properties may only be declared on a type error. This doesn't work:
class func doItOnce() {
static var token: dispatch_once_t = 0
...
}
Must be declared on a type. This was introduced in Swift 1.2 (Xcode 6.3 IIRC).
“static” methods and properties are now allowed in classes (as an
alias for “class final”). You are now allowed to declare static stored
properties in classes, which have global storage and are lazily
initialized on first access (like global variables). Protocols now
declare type requirements as “static” requirements instead of
declaring them as “class” requirements. (17198298)
So, what we can do if we don't like globals?
Static variable on a type
class MyClass {
private static var token: dispatch_once_t = 0
class func doItOnce() {
dispatch_once(&token) {
print("Do it once")
}
}
}
Static in a method wrapped in struct
Don't like static property on yur class? Would like to have it in your method? Wrap it in struct like this:
class func doItOnce() {
struct Tokens { static var token: dispatch_once_t = 0 }
dispatch_once(&Tokens.token) {
print("Do it once")
}
}
Actually I'm not aware of any Apple recommendation, best practice, ... how to do it for dispatch_once. Simply use whatever you like most, feels good to you and just meet criteria global / static scope.
For those of you who are curious, for me this approach has been useful for this purpose:
class SomeVC : UIViewController {
private var token: dispatch_once_t = 0
public override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
dispatch_once(&token) { () -> Void in
self.doSomethingOnce()
}
}
}
By not declaring a static var it has the expected behaviour. That being said, this is definitely NOT RECOMMENDED for any serious project, since in the Docs (as your well said) it states:
The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.
If we don't want to run into any future weird bugs and undefined behaviour I would just stick to what Apple says. But it's still nice to play around with these things, isn't it? =)
the robertvojta's answer is probably the best. because i try always to avoid import Foundation and use 'pure' Swift solution (with Swift3.0 i could change my opinion), I would like to share with you my own, very simple approach. i hope, this code is self-explanatory
class C {
private var i: Int?
func foo()->Void {
defer {
i = 0
}
guard i == nil else { return }
print("runs once")
}
}
let c = C()
c.foo() // prints "runs once"
c.foo()
c.foo()
let c1 = C()
c1.foo() // prints "runs once"
c1.foo()
class D {
static private var i: Int?
func foo()->Void {
defer {
D.i = 0
}
guard D.i == nil else { return }
print("runs once")
}
}
let d = D()
d.foo() // prints "runs once"
d.foo()
let d2 = D()
d.foo()
struct Foo {
var i = 0 { didSet { println("Current i: \(i)") } }
func delayedPrint() {
dispatch_async(dispatch_get_main_queue(), { _ in
println("Closure i: \(self.i)")
})
}
mutating func foo() {
delayedPrint()
i++
}
}
Now the output of
var a = Foo()
a.foo()
is
Current i: 1
Closure i: 0 // I want current value here.
I'm wondering what is the best way here to avoid capturing a copy of an ivar.
EDIT 1
Yes, moving to class was the first and only thing I've thought of but... this one fooled me to think it can be done somehow with struct... Why it works?
mutating func foo() {
delayedPrint()
dispatch_async(dispatch_get_main_queue(), { _ in
println("From foo: \(self.i)")
})
delayedPrint()
i++
}
Output:
Current i: 1
Closure i: 0
From foo: 1
Closure i: 0
I think you have to use class instead of structure here, because structs are passed by copy and classes by reference
I'm wondering what is the best way here to avoid capturing a copy of an ivar.
That is a misconception. You cannot "capture an ivar" in this way. What you are capturing is self! That is exactly why Swift forces you to say self, so that you understand this fact. Thus, it makes a difference what kind of thing self is. And that is why it matters whether self is a struct or a class. The class instance is mutable in place; the struct instance is not, so a copy is taken at the time of capture and that copy persists independently.
However, you can capture a simple Int (i.e. not an ivar), and when you do, you get the result you expect:
var i = 0
struct Foo {
func delayedPrint() {
dispatch_async(dispatch_get_main_queue(), {
println(i) // 1
})
}
func foo() {
delayedPrint()
i++
}
}
Now let's talk about the second puzzle that you pose. Here's a rewrite, to clarify what the puzzle is:
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
struct Foo {
var i = 0
mutating func foo() {
delay(0.5) {
println("From foo: \(self.i)") // 1
}
bar(2)
i++
}
func bar(d:Double) {
delay(d) {
println("from bar: \(self.i)") // 0
}
}
}
I'll test it like this:
var a = Foo()
a.foo()
a.bar(1)
The console shows:
From foo: 1 [after half a second]
from bar: 1 [after 1 second]
from bar: 0 [after 2 seconds]
So how can bar be called the second time 1 second later, yet show a value of self.i that is earlier? And why does foo behave differently?
The answer has to do with the fact that everything is happening inside functions - including the definitions of the anonymous functions. The code has to run at some point. Until then, the anonymous function is not defined.
First let's consider a.bar(1). This causes bar to run and to define the anonymous function which will capture self. But this happens after we have called foo and incremented i. Thus, the self captured at this time has an incremented i.
Next let's consider what happens when foo calls bar. It does this before incrementing i. So now bar runs and the anonymous function is defined, and captures self with i still set at 0. The fact that this result arrives into the console two seconds later is irrelevant; what is important is when the capture took place.
Finally we come to the surprising case of the anonymous function inside foo. Clearly, the presence of the i++ inside foo make all the difference. Why? Well, when foo runs, it defines an anonymous function that captures self. But this self has also been captured inside foo itself for the purposes of saying i++ — which is really self.i++. Thus, the change on self performed by i++ is seen by this anonymous function as well, because they are looking at the same self.
In other words, I'm suggesting that you have hit the Mysterious Edge Case of the anonymous function defined within a function that itself mutates self. (I don't know if I think this a bug or not; I'm going to submit it to dev forum and see what they think.)
In order to complement #nikolayn perfect answer, here is a sample that can run in the console and that demonstrates how this can be accomplished with a class instead of a struct (and is also free of data races):
(variables are defined explicit so that you can easily debug)
import Foundation
import Cocoa
let queue = dispatch_queue_create("sync_queue", nil)!
class Foo {
var i = 0 { didSet { println("Current i: \(i)") } }
let sem = dispatch_semaphore_create(0);
func delayedPrint() {
let i_copy = i
let t = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(t, queue) { _ in
let _i = self.i
let _i_copy = i_copy
println("Closure i: \(_i)")
println("Closure i_copy: \(_i_copy)")
dispatch_semaphore_signal(self.sem)
}
}
func foo() {
delayedPrint()
dispatch_async(queue) {
self.i++
}
}
func wait() {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER)
}
}
var a = Foo()
a.foo()
a.wait()