I'm trying to figure out how to create a pointer to a pointer in Swift. Now, I know we don't exactly have pointers in Swift, but here is what I am trying to accomplish:
var foo = objA() //foo is variable referencing an instance of objA
var bar = foo //bar is a second variable referencing the instance above
foo = objA() //foo is now a reference to a new instance of objA, but bar
//is still a reference to the old instance
I would like to have bar be a reference to the foo variable instead of it being a reference to the foo object. That way, if foo becomes a reference to a different object, bar goes along for the ride.
One way of having a secondary reference to a variable would be a computed variable:
class C {}
var a = C()
var b: C { return a } // b is a computed variable, returning the current value of a
b === a // true
a = C()
b === a // true, whereas "var b = a" would have made this false
I believe this is what you want:
class O {
let n: Int
init(n: Int) { self.n = n }
}
var foo = O(n: 1)
var bar = withUnsafePointer(&foo) {$0}
print(bar.pointee.n) // Prints 1
foo = O(n: 2)
print(bar.pointee.n) // Prints 2
(Replace pointee with memory for Swift < 3.0)
I really don't know why you'd want that though.
You can try to use UnsafeMutablePointer. See an example below:
let string = UnsafeMutablePointer<String>.alloc(1)
string.initialize("Hello Swift")
print(string.memory)
let next = string
next.memory = "Bye Bye Swift"
print(string.memory) // prints "Bye Bye Swift"
But it smells a little and It will be better to avoid using technique like this.
Related
Swift has this awesome error that shows up when you try to do something of the form x = x:
class Foo {
var foo = 1
}
var a = Foo()
a.foo = a.foo // error
This helped me avoid typos where the class had two similarly named properties, and I want to assign one to the other, but mistakenly typed the same one twice.
However, in this particular case:
struct Foo {
var foo = 1 {
didSet {
print("Did set")
}
}
mutating func f() {
foo = foo
}
}
var a = Foo()
a.foo = a.foo
It successfully compiles! There isn't even an error on the foo = foo line! If I change Foo to a class, or if I remove the didSet, then the expected error appears. It's just this struct + didSet combination that makes the compiler think "yeah, a.foo = a.foo makes a lot of sense! Let me allow that!"
I found this related post, which is about how to stop getting this error, rather than how to get it.
I also looked on bugs.swift.org, but there were only 3 results, and none of them are related.
I'm using Swift 5.3.2 and Xcode 12.4.
Is there any reason why assigning a struct property to itself is more "OK" than assigning a class property to itself?
I know swift has both reference types and value types. And I know Int is a value type. But how can I store a reference to an integer?
var x:Int = 1
var y:Int = x // I want y to reference x (not copy)
++y
println(x) // prints 1, but I want 2
I tried using boxed types, and I tried using array of Int, but neither works for holding a reference to integer.
I guess I can write my own
class IntRef {
var a:Int = 0
init(value:Int) { a = value }
}
var x:IntRef = IntRef(value: 3)
var y = x
++y.a
println(x.a)
seems a bit awkward.
Unfortunately there is no reference type Integer or something like that in Swift so you have to make a Box-Type yourself.
For example a generic one:
class Reference<T> {
var value: T
init(_ value: T) { self.value = value }
}
You can also use closures. I think these better because they are more powerful and also more specific. They not only store a reference, but they also indicate how the reference will be used. For example,
var x:Int = 1
var setx = { (a:Int) in x = a }
var getx = { x }
setx(getx() + 1)
println(x) // This will print 2
I don't recommend actually defining getx/setx. Define a closure that does a specific task for your application.
What is the reason I can't give a value to a stored property that depends on the value of another one in Swift 2.0?
The code below gives an error saying:
Something.Type does not have a member named 'foo'
class Something {
let foo = "bar"
let baz = "\(foo) baz"
}
This is odd, as Something.Type certainly does have a member called foo.
Is there a way around this?
Looks like you're trying to initialise the variable baz, before swift has had a chance to know that foo is a property of Something. Place your initialisation inside the init constructor.
class Something {
let foo: String
let baz: String
init () {
foo = "bar"
baz = "\(foo) baz"
}
}
You can also use lazy initialization but now you have to make it a variable:
class Something {
let foo = "bar"
lazy var baz = { "\(self.foo) baz" }()
}
I've been trying to swap 2 objects without using a temp value, which be done like so:
var a = "Hello, "
var b = "world!"
(a,b) = (b,a)
a // "world!"
b // "Hello, "
Does anyone know how the language is doing this, is the second tuple (b,a) stored in memory to allow the first one to reassign itself, or does it do it all by switching references?
Thanks in advance
This kind of "switching" does the following:
Replaces the pointers for class types
var classA = NSString(string: "foo")
var classB = NSString(string: "bar")
NSLog("%p %p", classA, classB) // 0x7fecd351def0 0x7fecd341cc30
(classA, classB) = (classB, classA)
NSLog("%p %p", classA, classB) // 0x7fecd341cc30 0x7fecd351def0
Creates new values (copies) for value types
var valueA = "baz"
var valueB = "qux"
NSLog("%p %p", valueA, valueB) // 0x7fecd34201b0 0x7fecd34211e0
(valueA, valueB) = (valueB, valueA)
NSLog("%p %p", valueA, valueB) // 0x7fecd351c880 0x7fecd351de90
It's known that Swift compiler forces all the properties to be initialised in a constructer. However, sometimes I only want to have some of the properties to be initialised. Below is an example, I only have to use variable b in the second constructer and no need for the variable a but the complier is complaining "a is not initialised". I wonder how to deal with this case.
class aClass{
var a:String
var b:String
init(a:String){
self.a = "a"
}
init(a:String, b:String){
self.a = "a"
self.b = "b"
}
}
This is what optionals are for. your declaration of property b can change to var b: String?. This will make it so you don't have to give it a value in init. Then, when you want to use it, if let self.b = "my string" {...} or, if you know it has a value, you can force unwrap it: var myOtherString = b!.